summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorin Hochstein <lorinh@gmail.com>2016-06-23 20:51:27 -0700
committerGitHub <noreply@github.com>2016-06-23 20:51:27 -0700
commite7fb60432a1e16c8bc2dd1c7d2219f98b6d7f371 (patch)
tree012f9fd1dfac281d65b2f1b2bd877c17998729b1
parente05d87652450d774da29e5beb700495df66c7882 (diff)
parent8225e947b0cd87881f518192742ff68af6b7f308 (diff)
downloadopenstack-ansible-modules-e7fb60432a1e16c8bc2dd1c7d2219f98b6d7f371.tar.gz
Merge pull request #59 from rodrigobot/cinder-modules
Added modules to manage Cinder QOS and Volume Types.
-rw-r--r--cinder_qos250
-rw-r--r--cinder_volume_types179
2 files changed, 429 insertions, 0 deletions
diff --git a/cinder_qos b/cinder_qos
new file mode 100644
index 0000000..8560a8a
--- /dev/null
+++ b/cinder_qos
@@ -0,0 +1,250 @@
+#!/bin/python
+
+from ansible.module_utils.basic import *
+try:
+ from cinderclient.v2 import client
+except ImportError:
+ print("failed=True msg='cinder client is required'")
+
+DOCUMENTATION = '''
+---
+module: cinder_configure
+short_description: Configure Openstack Block Storage (Cinder)
+description: Create QoS needed for deploying Cinder
+options:
+ action:
+ description:
+ - The action corresponds to a Cinder qos command, such as cinder qos-create.
+ required: true
+ choices: [create, associate, disassociate, key]
+ username:
+ description:
+ - username used to authenticate with keystone
+ required: true
+ password:
+ description:
+ - password used to authenticate with keystone
+ required: true
+ url_auth:
+ description:
+ - keystone url for authentication
+ required: true
+ tenant_name:
+ description:
+ - tenant name or project name of the login user
+ required: true
+ region_name:
+ description:
+ - region to connect to
+ required: true
+ name:
+ description:
+ - Name to be given to the QoS
+ required: true
+ extra_specs:
+ description:
+ - A dictionary of extra specs to add to the QoS
+ required: true
+ qos_volume_type:
+ description:
+ - The name of the volume-type to assign QoS to.
+ required: true
+requirements: [ cinder ]
+author: Rodrigo Soto
+'''
+
+EXAMPLES = '''
+cinder_qos:
+ action: create
+ username: admin
+ password: admin
+ url_auth: "http://keystone/v2"
+ tenant_name: admin
+ region_name: RegionOne
+ name: qos-test
+ extra_specs: "test=hello,test2=world"
+ qos_volume_type: some-type
+'''
+
+def _get_cinderclient(module):
+ try:
+ cinder_client = client.Client(
+ module.params.get('username'),
+ module.params.get('password'),
+ module.params.get('tenant_name'),
+ module.params.get('url_auth'),
+ region_name=module.params.get('region_name')
+ )
+ except Exception as e:
+ module.fail_json(msg="Error authenticating to cinder: %s" % e.message)
+ return cinder_client
+
+def _get_qos_id(module, cinderclient):
+ name = module.params.get('name')
+ try:
+ qos_list = cinderclient.qos_specs.list()
+ for qos in qos_list:
+ if qos.name == name:
+ return qos.id
+ except Exception:
+ return None
+
+
+def _create_qos(module, cinderclient):
+ name = module.params.get('name')
+ extra_specs = module.params.get('extra_specs').split(',')
+ extra_specs_dict = {}
+ for extra_spec in extra_specs:
+ key, value = extra_spec.split('=')
+ extra_specs_dict[key] = value
+
+ before = cinderclient.qos_specs.list()
+ try:
+ qos = cinderclient.qos_specs.create(name, extra_specs_dict)
+ except Exception as e:
+ module.fail_json(msg="Error creating qos: %s" % e.message)
+
+ after = cinderclient.qos_specs.list()
+ changes = _qos_changes(before, after)
+ changed = True if changes else False
+ results = {'action': 'create'}
+ results.update(changes)
+ return (changed, results)
+
+def _get_volume_type_id(module, cinderclient):
+ name = module.params.get('qos_volume_type')
+ type_list = cinderclient.volume_types.list()
+
+ volume_type_id = ''
+ try:
+ for type in type_list:
+ if type.name == name:
+ volume_type_id = type.id
+ except Exception as e:
+ module.fail_json(msg="Error getting QoS Volume Type ID: %s" % e.message)
+
+ return volume_type_id
+
+def _associate_qos(module, cinderclient):
+ volume_type_id = _get_volume_type_id(module, cinderclient)
+ qos_id = _get_qos_id(module, cinderclient)
+ before = cinderclient.qos_specs.get_associations(qos_id)
+ try:
+ associate = cinderclient.qos_specs.associate(qos_id, volume_type_id)
+
+ except Exception as e:
+ module.fail_json(msg="Error associating qos: %s" % e.message)
+ after = cinderclient.qos_specs.get_associations(qos_id)
+ changes = _qos_changes(before, after)
+ changed = True if changes else False
+ results = {'action': 'associate'}
+ results.update(changes)
+ return (changed, results)
+
+def _disassociate_qos(module, cinderclient):
+ volume_type_id = _get_volume_type_id(module, cinderclient)
+ qos_id = _get_qos_id(module, cinderclient)
+
+ before = cinderclient.qos_specs.get_associations(qos_id)
+
+ try:
+ cinderclient.qos_specs.disassociate(qos_id, volume_type_id)
+
+ except Exception as e:
+ module.fail_json(msg="Error disassociating qos: %s" % e.message)
+
+ after = cinderclient.qos_specs.get_associations(qos_id)
+ changes = _qos_changes(before, after)
+ changed = True if changes else False
+ results = {'action': 'disassociate'}
+ results.update(changes)
+ return (changed, results)
+
+
+def _set_qos_keys(module, cinderclient):
+ volume_type_id = _get_volume_type_id(module, cinderclient)
+ qos_id = _get_qos_id(module, cinderclient)
+ name = module.params.get('name')
+ extra_specs = module.params.get('extra_specs').split(',')
+ extra_specs_dict = {}
+
+ for extra_spec in extra_specs:
+ key, value = extra_spec.split('=')
+ extra_specs_dict[key] = value
+
+ before = cinderclient.qos_specs.get(qos_id)
+ try:
+ cinderclient.qos_specs.set_keys(qos_id, extra_specs_dict)
+
+ except Exception as e:
+ module.fail_json(msg="Error setting key(s) for qos: %s" % e.message)
+
+ after = cinderclient.qos_specs.get(qos_id)
+ changes = _qos_changes(before, after)
+ changed = True if changes else False
+ results = {'action': 'set-key'}
+ results.update(changes)
+ return (changed, results)
+
+
+def _qos_changes(before, after):
+
+ changes = {}
+
+ if type(before) is list:
+ if before == after:
+ return changes
+ else:
+ changes['Changed']='True'
+ return changes
+
+ before_dict = {}
+ for attr,value in before.__dict__.iteritems():
+ before_dict[attr] = value
+
+ after_dict = {}
+ for attr,value in after.__dict__.iteritems():
+ after_dict[attr] = value
+
+ for key in before_dict:
+ if before_dict[key] != after_dict[key]:
+ changes[key] = after_dict[key]
+
+ return changes
+
+def main():
+ module = AnsibleModule(
+ argument_spec={
+ 'action': {'required': True, 'default': None},
+ 'username': {'required': True},
+ 'password': {'required': True},
+ 'url_auth': {'required': True},
+ 'tenant_name': {'required': True},
+ 'region_name': {'required': True},
+ 'name': {'required': True},
+ 'extra_specs': {'required': True},
+ 'qos_volume_type': {'required': True}
+ },
+ )
+ cinderclient = _get_cinderclient(module)
+ if module.params.get('action') == 'create':
+ qos_id = _get_qos_id(module, cinderclient)
+ if qos_id is None:
+ changed, results = _create_qos(module, cinderclient)
+ else:
+ module.exit_json(changed=False, result="Success", msg=qos_id)
+
+ elif module.params.get('action') == 'associate':
+ qos_id = _get_qos_id(module, cinderclient)
+ changed, results = _associate_qos(module, cinderclient)
+
+ elif module.params.get('action') == 'key':
+ qos_id = _get_qos_id(module, cinderclient)
+ changed, results = _set_qos_keys(module, cinderclient)
+
+ elif module.params.get('action') == 'disassociate':
+ qos_id = _get_qos_id(module, cinderclient)
+ changed, results = _disassociate_qos(module, cinderclient)
+
+ module.exit_json(changed=changed, item=results)
+main() \ No newline at end of file
diff --git a/cinder_volume_types b/cinder_volume_types
new file mode 100644
index 0000000..ea990b4
--- /dev/null
+++ b/cinder_volume_types
@@ -0,0 +1,179 @@
+#!/bin/python
+
+from ansible.module_utils.basic import *
+try:
+ from cinderclient.v2 import client
+except ImportError:
+ print("failed=True msg='cinder client is required'")
+
+
+DOCUMENTATION = '''
+---
+module: cinder_configure
+short_description: Configure Openstack Block Storage (Cinder)
+description: Create Volume Types needed for deploying Cinder
+options:
+ action:
+ description:
+ - Currently only supported option is create
+ required: true
+ choices: [create]
+ username:
+ description:
+ - username used to authenticate with keystone.
+ required: true
+ password:
+ description:
+ - password used to authenticate with keystone.
+ required: true
+ url_auth:
+ description:
+ - keystone url for authentication.
+ required: true
+ tenant_name:
+ description:
+ - tenant name or project name of the login user
+ required: true
+ region_name:
+ description:
+ - region to connect to
+ required: true
+ name:
+ description:
+ - Name to be given to the volume type.
+ required: true
+ extra_specs:
+ description:
+ - A dictionary of extra specs to add to the volume type.
+ required: false
+requirements: [ cinder ]
+author: Rodrigo Soto
+'''
+
+EXAMPLES = '''
+cinder_volume_types:
+ action: create
+ username: admin
+ password: "{{keystone_admin_password}}"
+ tenant_name: admin
+ region_name: RegionOne
+ url_auth: "{{keystone_admin_url}}"
+ name: some-name
+ extra_specs: "volume_backend_name=some-name"
+'''
+
+
+def _get_cinderclient(module):
+ try:
+ cinder_client = client.Client(
+ module.params.get('username'),
+ module.params.get('password'),
+ module.params.get('tenant_name'),
+ module.params.get('url_auth'),
+ region_name=module.params.get('region_name')
+ )
+ except Exception as e:
+ module.fail_json(msg="Error authenticating to cinder: %s" % e.message)
+ return cinder_client
+
+
+def _get_volume_type(module, cinderclient):
+ name = module.params.get('name')
+ try:
+ volume_type = cinderclient.volume_types.find(name=name)
+ if volume_type is not None:
+ return volume_type
+ except Exception:
+ return None
+ return None
+
+
+def _create_volume_type(module, cinderclient):
+ name = module.params.get('name')
+ try:
+ volume_type_result = cinderclient.volume_types.create(name)
+ except Exception as e:
+ module.fail_json(msg="Error in creating volume type: %s" % e.message)
+ return volume_type_result
+
+
+def _delete_volume_type(module, cinderclient):
+ name = module.params.get('name')
+ try:
+ volume_type = cinderclient.volume_types.find(name=name)
+ except Exception as e:
+ module.fail_json(
+ msg="Error finding volume type to delete: %s" % e.message
+ )
+ try:
+ cinderclient.volume_types.delete(volume_type.id)
+ except Exception as e:
+ module.fail_json(
+ msg="Error in deleting the volume type: %s" % e.message
+ )
+ return True
+
+
+def _volume_type_set_keys(volume_type, extra_specs):
+ if extra_specs is not None:
+ extra_specs_dict = {}
+ extra_specs = extra_specs.split(',')
+ for extra_spec in extra_specs:
+ key, value = extra_spec.split('=')
+ extra_specs_dict[key] = value
+ try:
+ volume_type.set_keys(extra_specs_dict)
+ except Exception as e:
+ raise e
+
+
+def _get_volume_type_id(module, cinderclient):
+ name = module.params.get('name')
+ try:
+ volume_type = cinderclient.volume_types.find(name=name)
+ except Exception as e:
+ module.fail_json(
+ msg="Error finding volume type %s: %s" % (name, e.message)
+ )
+ return volume_type.id
+
+
+def main():
+ module = AnsibleModule(
+ argument_spec={
+ 'action': {'default': 'create'},
+ 'username': {'required': True},
+ 'password': {'required': True},
+ 'url_auth': {'required': True},
+ 'tenant_name': {'required': True},
+ 'region_name': {'required': True},
+ 'name': {'required': True},
+ 'extra_specs': {'required': False},
+ },
+ )
+
+ cinderclient = _get_cinderclient(module)
+
+ if module.params.get('action') == 'create':
+ volume_type = _get_volume_type(module, cinderclient)
+ if volume_type is None:
+ volume_type = _create_volume_type(module, cinderclient)
+ _volume_type_set_keys(
+ volume_type, module.params.get('extra_specs')
+ )
+ module.exit_json(
+ changed=True,
+ result="Created",
+ msg=volume_type.id
+ )
+ else:
+ _volume_type_set_keys(
+ volume_type, module.params.get('extra_specs')
+ )
+ module.exit_json(
+ changed=False,
+ result="Success",
+ msg=_get_volume_type_id(module, cinderclient)
+ )
+
+main() \ No newline at end of file