cloudstack: cs_storage_pool: fix state handling, add tests
cs_storage_pool: rm CloudStackException dependency cs_storage_pool: fix UnboundLocalError in check mode local variable 'pool' referenced before assignment
This commit is contained in:
parent
7549b27544
commit
f6b7c1a6c1
4 changed files with 771 additions and 182 deletions
|
@ -2,6 +2,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# (c) 2017, Netservers Ltd. <support@netservers.co.uk>
|
||||
# (c) 2017, René Moser <mail@renemoser.net>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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()
|
||||
|
|
2
test/integration/targets/cs_storage_pool/aliases
Normal file
2
test/integration/targets/cs_storage_pool/aliases
Normal file
|
@ -0,0 +1,2 @@
|
|||
cloud/cs
|
||||
posix/ci/cloud/cs
|
3
test/integration/targets/cs_storage_pool/meta/main.yml
Normal file
3
test/integration/targets/cs_storage_pool/meta/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
dependencies:
|
||||
- cs_common
|
465
test/integration/targets/cs_storage_pool/tasks/main.yml
Normal file
465
test/integration/targets/cs_storage_pool/tasks/main.yml
Normal file
|
@ -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"
|
Loading…
Reference in a new issue