diff --git a/lib/ansible/modules/cloud/cloudstack/cs_storage_pool.py b/lib/ansible/modules/cloud/cloudstack/cs_storage_pool.py index d224f45c730..4a0b31af7c7 100644 --- a/lib/ansible/modules/cloud/cloudstack/cs_storage_pool.py +++ b/lib/ansible/modules/cloud/cloudstack/cs_storage_pool.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # # (c) 2017, Netservers Ltd. +# (c) 2017, René Moser # # This file is part of Ansible # @@ -18,7 +19,7 @@ # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . -ANSIBLE_METADATA = {'metadata_version': '1.0', +ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} @@ -28,83 +29,107 @@ DOCUMENTATION = ''' module: cs_storage_pool short_description: Manages Primary Storage Pools on Apache CloudStack based clouds. description: - - Create and remove storage pools. - - Updates are only possible on enabled, tags, capacity_bytes and capacity_iops. + - Create, update, put into maintenance, disable, enable and remove storage pools. version_added: "2.4" -author: "Netservers Ltd. (@netservers)" +author: + - "Netservers Ltd. (@netservers)" + - "René Moser (@resmo)" options: name: description: - - Pool name. + - Name of the storage pool. required: true zone: description: - - Zone name. - required: true + - Name of the zone in which the host should be deployed. + - If not set, default zone is used. storage_url: description: - - Storage URL. + - URL of the storage pool. + - Required if C(state=present). pod: description: - - Pod name. + - Name of the pod. cluster: description: - - Cluster name. + - Name of the cluster. scope: description: - - The scope of the storage [cluster or zone] - - Defaults to cluster when provided, otherwise zone + - The scope of the storage pool. + - Defaults to cluster when C(cluster) is provided, otherwise zone. + choices: [ cluster, zone ] + managed: + description: + - Whether the storage pool should be managed by CloudStack. + - Only considere on creation. hypervisor: description: - - Required when creating a Zone scoped pool. [KVM, VMware] - tags: + - Required when creating a zone scoped pool. + choices: [ KVM, VMware, BareMetal, XenServer, LXC, HyperV, UCS, OVM, Simulator ] + storage_tags: description: - - Tags associated with this pool + - Tags associated with this storage pool. provider: description: - - Storage provider name [SolidFire, SolidFireShared, DefaultPrimary, CloudByte] - default: 'DefaultPrimary' + - Name of the storage provider e.g. SolidFire, SolidFireShared, DefaultPrimary, CloudByte. + default: DefaultPrimary capacity_bytes: description: - - Bytes CloudStack can provision from this storage pool + - Bytes CloudStack can provision from this storage pool. capacity_iops: description: - - Bytes CloudStack can provision from this storage pool - url: + - Bytes CloudStack can provision from this storage pool. + allocation_state: description: - - URL for the cluster - username: + - Allocation state of the storage pool. + choices: [ enabled, disabled ] + state: description: - - Username for the cluster - password: - description: - - Password for the cluster + - State of the storage pool. + default: present + choices: [ present, absent ] extends_documentation_fragment: cloudstack ''' EXAMPLES = ''' -# Ensure a Zone scoped storage_pool is present -- local_action: +- name: ensure a zone scoped storage_pool is present + local_action: module: cs_storage_pool zone: zone01 storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname provider: DefaultPrimary name: Ceph RBD - scope: ZONE + scope: zone hypervisor: KVM -# Ensure a Cluster scoped storage_pool is present -- local_action: +- name: ensure a cluster scoped storage_pool is disabled + local_action: module: cs_storage_pool + name: Ceph RBD zone: zone01 cluster: cluster01 + pod: pod01 storage_url: rbd://admin:SECRET@ceph-the-mons.domain/poolname provider: DefaultPrimary name: Ceph RBD - scope: CLUSTER + scope: cluster + allocation_state: disabled -# Ensure a storage_pool is absent -- local_action: +- name: ensure a cluster scoped storage_pool is in maintenance + local_action: + module: cs_storage_pool + name: Ceph RBD + zone: zone01 + cluster: cluster01 + pod: pod01 + storage_url: rbd://admin:SECRET@ceph-the-mons.domain/poolname + provider: DefaultPrimary + name: Ceph RBD + scope: cluster + allocation_state: maintenance + +- name: ensure a storage_pool is absent + local_action: module: cs_storage_pool name: Ceph RBD state: absent @@ -113,84 +138,104 @@ EXAMPLES = ''' RETURN = ''' --- id: - description: UUID of the pool. - returned: success - type: string - sample: a3fca65a-7db1-4891-b97c-48806a978a96 + description: UUID of the pool. + returned: success + type: string + sample: a3fca65a-7db1-4891-b97c-48806a978a96 +created: + description: Date of the pool was created. + returned: success + type: string + sample: 2014-12-01T14:57:57+0100 capacity_iops: - description: IOPS CloudStack can provision from this storage pool - returned: when available - type: int - sample: 60000 -zone_id: - description: UUID of the zone. - returned: success - type: string - sample: a3fca65a-7db1-4891-b97c-48806a978a96 + description: IOPS CloudStack can provision from this storage pool + returned: when available + type: int + sample: 60000 zone: - description: The name of the zone. - returned: success - type: string - sample: Zone01 -cluster_id: - description: UUID of the cluster. - returned: when scope is cluster - type: string - sample: a3fca65a-7db1-4891-b97c-48806a978a96 + description: The name of the zone. + returned: success + type: string + sample: Zone01 cluster: - description: The name of the cluster. - returned: when scope is cluster - type: string - sample: Cluster01 -pod_id: - description: UUID of the pod. - returned: when scope is cluster - type: string - sample: a3fca65a-7db1-4891-b97c-48806a978a96 + description: The name of the cluster. + returned: when scope is cluster + type: string + sample: Cluster01 pod: - description: The name of the pod. - returned: when scope is cluster - type: string - sample: Cluster01 + description: The name of the pod. + returned: when scope is cluster + type: string + sample: Cluster01 disk_size_allocated: - description: The pool's currently allocated disk space - returned: success - type: int - sample: 2443517624320 + description: The pool's currently allocated disk space. + returned: success + type: int + sample: 2443517624320 disk_size_total: - description: The total size of the pool - returned: success - type: int - sample: 3915055693824 + description: The total size of the pool. + returned: success + type: int + sample: 3915055693824 disk_size_used: - description: The pool's currently used disk size - returned: success - type: int - sample: 1040862622180 + description: The pool's currently used disk size. + returned: success + type: int + sample: 1040862622180 scope: - description: "The scope of the storage pool [ZONE / CLUSTER]" - returned: success - type: string - sample: CLUSTER + description: The scope of the storage pool. + returned: success + type: string + sample: cluster +hypervisor: + description: Hypervisor related to this storage pool. + returned: when available + type: string + sample: KVM state: - description: The state of the storage pool - returned: success - type: string - sample: Up -tags: - description: the Tags for the storage pool - returned: success - type: list - sample: rbd + description: The state of the storage pool as returned by the API. + returned: success + type: string + sample: Up +allocation_state: + description: The state of the storage pool. + returned: success + type: string + sample: enabled +path: + description: The storage pool path used in the storage_url. + returned: success + type: string + sample: poolname +overprovision_factor: + description: The overprovision factor of the storage pool. + returned: success + type: string + sample: 2.0 +suitable_for_migration: + description: Whether the storage pool is suitable to migrate a volume or not. + returned: success + type: bool + sample: false +storage_capabilities: + description: Capabilities of the torage pool. + returned: success + type: dict + sample: {"VOLUME_SNAPSHOT_QUIESCEVM": "false"} +storage_tags: + description: the tags for the storage pool. + returned: success + type: list + sample: ["perf", "ssd"] ''' # import cloudstack common from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.cloudstack import ( AnsibleCloudStack, - CloudStackException, cs_argument_spec, cs_required_together, + CS_HYPERVISORS, ) @@ -199,7 +244,6 @@ class AnsibleCloudStackStoragePool(AnsibleCloudStack): def __init__(self, module): super(AnsibleCloudStackStoragePool, self).__init__(module) self.returns = { - 'id': 'id', 'capacityiops': 'capacity_iops', 'podname': 'pod', 'clustername': 'cluster', @@ -208,25 +252,115 @@ class AnsibleCloudStackStoragePool(AnsibleCloudStack): 'disksizeused': 'disk_size_used', 'scope': 'scope', 'hypervisor': 'hypervisor', - 'state': 'state', - 'tags': 'tags', + 'type': 'type', + 'ip_address': 'ipaddress', + 'path': 'path', + 'overprovisionfactor': 'overprovision_factor', + 'storagecapabilities': 'storage_capabilities', + 'suitableformigration': 'suitable_for_migration', + } + self.allocation_states = { + # Host state: param state + 'Up': 'enabled', + 'Disabled': 'disabled', + 'Maintenance': 'maintenance', } self.storage_pool = None - self.pod = None - self.cluster = None def _get_common_args(self): - args = { + return { 'name': self.module.params.get('name'), 'url': self.module.params.get('storage_url'), 'zoneid': self.get_zone(key='id'), - 'provider': self.module.params.get('provider'), + 'provider': self.get_storage_provider(), 'scope': self.module.params.get('scope'), 'hypervisor': self.module.params.get('hypervisor'), 'capacitybytes': self.module.params.get('capacity_bytes'), 'capacityiops': self.module.params.get('capacity_iops'), } - return args + + def _allocation_state_enabled_disabled_changed(self, pool, allocation_state): + if allocation_state in ['enabled', 'disabled']: + for pool_state, param_state in self.allocation_states.items(): + if pool_state == pool['state'] and allocation_state != param_state: + return True + return False + + def _handle_allocation_state(self, pool, state=None): + allocation_state = state or self.module.params.get('allocation_state') + if not allocation_state: + return pool + + if self.allocation_states.get(pool['state']) == allocation_state: + return pool + + # Cancel maintenance if target state is enabled/disabled + elif allocation_state in ['enabled', 'disabled']: + pool = self._cancel_maintenance(pool) + pool = self._update_storage_pool(pool=pool, allocation_state=allocation_state) + + # Only an enabled host can put in maintenance + elif allocation_state == 'maintenance': + pool = self._update_storage_pool(pool=pool, allocation_state='enabled') + pool = self._enable_maintenance(pool=pool) + + return pool + + def _create_storage_pool(self): + args = self._get_common_args() + args.update({ + 'clusterid': self.get_cluster(key='id'), + 'podid': self.get_pod(key='id'), + 'managed': self.module.params.get('managed'), + }) + + scope = self.module.params.get('scope') + if scope is None: + args['scope'] = 'cluster' if args['clusterid'] else 'zone' + + self.result['changed'] = True + + if not self.module.check_mode: + res = self.query_api('createStoragePool', **args) + return res['storagepool'] + + def _update_storage_pool(self, pool, allocation_state=None): + args = { + 'id': pool['id'], + 'capacitybytes': self.module.params.get('capacity_bytes'), + 'capacityiops': self.module.params.get('capacity_iops'), + 'tags': self.get_storage_tags(), + } + + if self.has_changed(args, pool) or self._allocation_state_enabled_disabled_changed(pool, allocation_state): + self.result['changed'] = True + args['enabled'] = allocation_state == 'enabled' if allocation_state in ['enabled', 'disabled'] else None + if not self.module.check_mode: + res = self.query_api('updateStoragePool', **args) + pool = res['storagepool'] + return pool + + def _enable_maintenance(self, pool): + if pool['state'].lower() != "maintenance": + self.result['changed'] = True + if not self.module.check_mode: + res = self.query_api('enableStorageMaintenance', id=pool['id']) + pool = self.poll_job(res, 'storagepool') + return pool + + def _cancel_maintenance(self, pool): + if pool['state'].lower() == "maintenance": + self.result['changed'] = True + if not self.module.check_mode: + res = self.query_api('cancelStorageMaintenance', id=pool['id']) + pool = self.poll_job(res, 'storagepool') + return pool + + def get_storage_tags(self): + storage_tags = self.module.params.get('storage_tags') + if storage_tags is None: + return None + return ','.join(storage_tags) def get_storage_pool(self, key=None): if self.storage_pool is None: @@ -241,11 +375,8 @@ class AnsibleCloudStackStoragePool(AnsibleCloudStack): 'name': self.module.params.get('name'), } - res = self.cs.listStoragePools(**args) - if 'errortext' in res: - self.module.fail_json(msg="Failed: '%s'" % res['errortext']) - - elif 'storagepool' not in res: + res = self.query_api('listStoragePools', **args) + if 'storagepool' not in res: return None self.storage_pool = res['storagepool'][0] @@ -255,52 +386,13 @@ class AnsibleCloudStackStoragePool(AnsibleCloudStack): def present_storage_pool(self): pool = self.get_storage_pool() if pool: - pool = self._update_storage_pool() + pool = self._update_storage_pool(pool=pool) else: pool = self._create_storage_pool() - return pool - def _create_storage_pool(self): + if pool: + pool = self._handle_allocation_state(pool=pool) - cluster = self.get_cluster(key='id') - pod = self.get_pod(key='id') - scope = self.module.params.get('scope') - args = self._get_common_args() - args['clusterid'] = cluster - args['podid'] = pod - - if scope is None: - args['scope'] = 'CLUSTER' if cluster else 'ZONE' - - self.result['changed'] = True - - if not self.module.check_mode: - res = self.cs.createStoragePool(**args) - if 'errortext' in res: - self.module.fail_json(msg="Failed: '%s'" % res['errortext']) - pool = res['storagepool'] - return pool - - def _update_storage_pool(self): - pool = self.get_storage_pool() - - args = {} - - args['id'] = pool['id'] - args['capacitybytes'] = self.module.params.get('capacity_bytes') - args['capacityiops'] = self.module.params.get('capacity_iops') - args['tags'] = self.module.params.get('tags') - state = self.module.params.get('state') - if state in ['enabled', 'disabled']: - args['state'] = state.capitalize() - - if self.has_changed(args, pool): - self.result['changed'] = True - - if not self.module.check_mode: - res = self.cs.updateStoragePool(**args) - if 'errortext' in res: - self.module.fail_json(msg="Failed: '%s'" % res['errortext']) return pool def absent_storage_pool(self): @@ -312,11 +404,22 @@ class AnsibleCloudStackStoragePool(AnsibleCloudStack): 'id': pool['id'], } if not self.module.check_mode: - res = self.cs.deleteStoragePool(**args) - if 'errortext' in res: - self.module.fail_json(msg="Failed: '%s'" % res['errortext']) + # Only a pool in maintenance can be deleted + self._handle_allocation_state(pool=pool, state='maintenance') + self.query_api('deleteStoragePool', **args) return pool + def get_storage_provider(self, type="primary"): + args = { + 'type': type, + } + provider = self.module.params.get('provider') + storage_providers = self.query_api('listStorageProviders', **args) + for sp in storage_providers.get('dataStoreProvider') or []: + if sp['name'].lower() == provider.lower(): + return provider + self.fail_json(msg="Storage provider %s not found" % provider) + def get_pod(self, key=None): pod = self.module.params.get('pod') if not pod: @@ -325,65 +428,81 @@ class AnsibleCloudStackStoragePool(AnsibleCloudStack): 'name': pod, 'zoneid': self.get_zone(key='id'), } - pods = self.cs.listPods(**args) + pods = self.query_api('listPods', **args) if pods: return self._get_by_key(key, pods['pod'][0]) - self.module.fail_json(msg="Pod %s not found in zone %s." % ( - self.module.params.get('pod'), - self.get_zone(key='name'))) + + self.fail_json(msg="Pod %s not found" % self.module.params.get('pod')) def get_cluster(self, key=None): cluster = self.module.params.get('cluster') if not cluster: return None + args = { 'name': cluster, 'zoneid': self.get_zone(key='id'), } - clusters = self.cs.listClusters(**args) + + clusters = self.query_api('listClusters', **args) if clusters: return self._get_by_key(key, clusters['cluster'][0]) - self.module.fail_json(msg="Cluster %s not found" % cluster) + + self.fail_json(msg="Cluster %s not found" % cluster) + + def get_result(self, pool): + super(AnsibleCloudStackStoragePool, self).get_result(pool) + if pool: + self.result['storage_url'] = "%s://%s/%s" % (pool['type'], pool['ipaddress'], pool['path']) + self.result['scope'] = pool['scope'].lower() + self.result['storage_tags'] = pool['tags'].split(',') if pool.get('tags') else [] + self.result['allocation_state'] = self.allocation_states.get(pool['state']) + return self.result def main(): argument_spec = cs_argument_spec() argument_spec.update(dict( name=dict(required=True), - storage_url=dict(default=None), - zone=dict(required=True), - pod=dict(default=None), - cluster=dict(default=None), - scope=dict(default=None, choices=['ZONE', 'CLUSTER']), - hypervisor=dict(default=None), + storage_url=dict(), + zone=dict(), + pod=dict(), + cluster=dict(), + scope=dict(choices=['zone', 'cluster']), + hypervisor=dict(choices=CS_HYPERVISORS), provider=dict(default='DefaultPrimary'), - capacity_bytes=dict(default=None), - capacity_iops=dict(default=None), - tags=dict(type='list', aliases=['tag'], default=None), - state=dict(choices=['present', 'enabled', 'disabled', 'absent'], default='present'), + capacity_bytes=dict(type='int'), + capacity_iops=dict(type='int'), + managed=dict(type='bool'), + storage_tags=dict(type='list', aliases=['storage_tag']), + allocation_state=dict(choices=['enabled', 'disabled', 'maintenance']), + state=dict(choices=['present', 'absent'], default='present'), )) + required_together = cs_required_together() + required_together.extend([ + ['pod', 'cluster'], + ]) module = AnsibleModule( argument_spec=argument_spec, - required_together=cs_required_together(), + required_together=required_together, + required_if=[ + ('state', 'present', ['storage_url']), + ], supports_check_mode=True ) - try: - acs_storage_pool = AnsibleCloudStackStoragePool(module) + acs_storage_pool = AnsibleCloudStackStoragePool(module) - state = module.params.get('state') - if state in ['absent']: - pool = acs_storage_pool.absent_storage_pool() - else: - pool = acs_storage_pool.present_storage_pool() - - result = acs_storage_pool.get_result(pool) - - except CloudStackException as e: - module.fail_json(msg='CloudStackException: %s' % str(e)) + state = module.params.get('state') + if state in ['absent']: + pool = acs_storage_pool.absent_storage_pool() + else: + pool = acs_storage_pool.present_storage_pool() + result = acs_storage_pool.get_result(pool) module.exit_json(**result) + if __name__ == '__main__': main() diff --git a/test/integration/targets/cs_storage_pool/aliases b/test/integration/targets/cs_storage_pool/aliases new file mode 100644 index 00000000000..ba249b99d73 --- /dev/null +++ b/test/integration/targets/cs_storage_pool/aliases @@ -0,0 +1,2 @@ +cloud/cs +posix/ci/cloud/cs diff --git a/test/integration/targets/cs_storage_pool/meta/main.yml b/test/integration/targets/cs_storage_pool/meta/main.yml new file mode 100644 index 00000000000..e9a5b9eeaef --- /dev/null +++ b/test/integration/targets/cs_storage_pool/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - cs_common diff --git a/test/integration/targets/cs_storage_pool/tasks/main.yml b/test/integration/targets/cs_storage_pool/tasks/main.yml new file mode 100644 index 00000000000..31e1c5a48e6 --- /dev/null +++ b/test/integration/targets/cs_storage_pool/tasks/main.yml @@ -0,0 +1,465 @@ +--- +- name: setup host is present + cs_host: + name: sim + url: "http://sim/c0-basic/h2" + cluster: C0-adv + pod: POD0-adv + username: root + password: password + hypervisor: Simulator + allocation_state: enabled + zone: "{{ cs_common_zone_adv }}" + register: host +- name: verify setup host is present + assert: + that: + - host|success + +- name: setup storage pool is absent + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + state: absent + register: sp +- name: verify setup storage pool is absent + assert: + that: + - sp|success + +- name: test fail if missing params + cs_storage_pool: + register: sp + ignore_errors: true +- name: verify results of fail if missing params + assert: + that: + - sp|failed + - "sp.msg == 'missing required arguments: name'" + +- name: test fail if provider unknown + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + provider: DNE + scope: cluster + cluster: C0-adv + pod: POD0-adv + register: sp + ignore_errors: true +- name: verify test fail if provider unknown + assert: + that: + - sp|failed + - "sp.msg == 'Storage provider DNE not found'" + +- name: test fail if cluster unknown + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: DNE + pod: POD0-adv + register: sp + ignore_errors: true +- name: verify test fail if cluster unknown + assert: + that: + - sp|failed + - "sp.msg == 'Cluster DNE not found'" + +- name: test fail if pod unknown + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: DNE + register: sp + ignore_errors: true +- name: verify test fail if pod unknown + assert: + that: + - sp|failed + - "sp.msg == 'Pod DNE not found'" + +- name: create storage pool in check mode + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + register: sp + check_mode: true +- name: verify create storage pool in check mode + assert: + that: + - sp|success + - sp|changed + +- name: create storage pool + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + register: sp +- name: verify create storage pool + assert: + that: + - sp|success + - sp|changed + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: create storage pool idempotence + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + cluster: C0-adv + pod: POD0-adv + register: sp +- name: verify create storage pool idempotence + assert: + that: + - sp|success + - not sp|changed + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: disable storage pool in check mode + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + cluster: C0-adv + pod: POD0-adv + allocation_state: disabled + check_mode: true + register: sp +- name: verify disable storage pool in check mode + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'enabled' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: disable storage pool + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + allocation_state: disabled + register: sp +- name: verify disable storage pool + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'disabled' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: disable storage pool idempotence + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + allocation_state: disabled + register: sp +- name: verify disable storage pool idempotence + assert: + that: + - sp|success + - not sp|changed + - sp.allocation_state == 'disabled' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: update while storage pool disabled in check mode + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + storage_tags: + - eco + - ssd + check_mode: true + register: sp +- name: verify update while storage pool disabled in check mode + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'disabled' + - sp.storage_tags == [] + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: update while storage pool disabled + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + storage_tags: + - eco + - ssd + register: sp +- name: verify update while storage pool disabled + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'disabled' + - sp.storage_tags == ['eco', 'ssd'] + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: update while storage pool disabled idempotence + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + storage_tags: + - eco + - ssd + register: sp +- name: verify update while storage pool disabled idempotence + assert: + that: + - sp|success + - not sp|changed + - sp.allocation_state == 'disabled' + - sp.storage_tags == ['eco', 'ssd'] + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: put storage in maintenance pool in check mode + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + allocation_state: maintenance + check_mode: true + register: sp +- name: verify put storage in maintenance pool in check mode + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'disabled' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: put storage in maintenance pool + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + allocation_state: maintenance + register: sp +- name: verify put storage in maintenance pool + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'maintenance' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: put storage in maintenance pool idempotence + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + allocation_state: maintenance + register: sp +- name: verify put storage in maintenance pool idempotence + assert: + that: + - sp|success + - not sp|changed + - sp.allocation_state == 'maintenance' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: update while in maintenance pool + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + storage_tag: perf + register: sp +- name: verify update while in maintenance pool + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'maintenance' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + - sp.storage_tags == ['perf'] + +- name: remove storage pool in check mode + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + state: absent + register: sp + check_mode: true +- name: verify remove storage pool in check mode + assert: + that: + - sp|success + - sp|changed + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: remove storage pool + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + state: absent + register: sp +- name: verify remove storage pool + assert: + that: + - sp|success + - sp|changed + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: remove storage pool idempotence + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + state: absent + register: sp +- name: verify remove storage pool idempotence + assert: + that: + - sp|success + - not sp|changed + +- name: create storage pool in maintenance + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + allocation_state: maintenance + register: sp +- name: verify create storage pool in maintenance + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'maintenance' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: remove storage pool in maintenance + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + state: absent + register: sp +- name: verify storage pool in maintenance + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'maintenance' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: create storage pool disabled + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + storage_url: rbd://admin:SECRET@ceph-mons.domain/poolname + scope: cluster + cluster: C0-adv + pod: POD0-adv + allocation_state: disabled + register: sp +- name: verify create storage pool in disabled + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'disabled' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname" + +- name: verify remove disabled storag e pool + cs_storage_pool: + name: "storage_pool_adv" + zone: "{{ cs_common_zone_adv }}" + state: absent + register: sp +- name: verify remove disabled storage pool + assert: + that: + - sp|success + - sp|changed + - sp.allocation_state == 'disabled' + - sp.cluster == "C0-adv" + - sp.pod == "POD0-adv" + - sp.storage_url == "RBD://ceph-mons.domain/poolname"