Improve cinderv3 module and states
Add states and modules for volumes
and unify volume_type states and modules
Change-Id: I23cc715df696c828e7f7b53d5c4c85b146d93417
Closes-Issue: PROD-25036 (PROD:25036)
diff --git a/_states/cinderv3.py b/_states/cinderv3.py
index c45e970..15cff40 100644
--- a/_states/cinderv3.py
+++ b/_states/cinderv3.py
@@ -5,73 +5,96 @@
import ast
import logging
-LOG = logging.getLogger(__name__)
+log = logging.getLogger(__name__)
def __virtual__():
- return 'cinderv3'
+ return 'cinderv3' if 'cinderv3.volume_list' in __salt__ else False # noqa
def _cinder_call(fname, *args, **kwargs):
return __salt__['cinderv3.{}'.format(fname)](*args, **kwargs)
-def volume_type_present(name=None, cloud_name=None):
- """
- Ensures that the specified volume type is present.
- """
- ret = {
- 'name': name,
- 'changes': {},
- 'result': True,
- 'comment': 'Volume type "{0}" already exists'.format(name)
- }
- type_req = _cinder_call('volume_type_get', name=name, cloud_name=cloud_name)
- if type_req.get("result"):
- return ret
- else:
- create_req = _cinder_call('volume_type_create', name=name,
- cloud_name=cloud_name)
- if create_req.get("result") is False:
- ret = {
- 'name': name,
- 'changes': {},
- 'result': False,
- 'comment': 'Volume type "{0}" failed to create'.format(name)
- }
+def _resource_present(resource, name, cloud_name, **kwargs):
+ try:
+ method_name = '{}_get_details'.format(resource)
+ exact_resource = _cinder_call(
+ method_name, name, cloud_name=cloud_name
+ )[resource]
+ except Exception as e:
+ if 'ResourceNotFound' in repr(e):
+ try:
+ method_name = '{}_create'.format(resource)
+ resp = _cinder_call(
+ method_name, name=name, cloud_name=cloud_name, **kwargs
+ )
+ except Exception as e:
+ log.exception('Cinder {0} create failed with {1}'.
+ format(resource, e))
+ return _failed('create', name, resource)
+ return _succeeded('create', name, resource, resp)
+ elif 'MultipleResourcesFound' in repr(e):
+ return _failed('find', name, resource)
else:
- ret['comment'] = 'Volume type {0} has been created'.format(name)
- ret['changes']['Volume type'] = 'Created'
- return ret
+ raise
+
+ to_update = {}
+ if to_update:
+ for key in kwargs:
+ if key not in exact_resource or kwargs[key] != exact_resource[key]:
+ to_update[key] = kwargs[key]
+ try:
+ method_name = '{}_update'.format(resource)
+ resp = _cinder_call(
+ method_name, name, cloud_name=cloud_name, **to_update
+ )
+ except Exception as e:
+ log.exception('Cinder {0} update failed with {1}'.format(resource, e))
+ return _failed('update', name, resource)
+ return _succeeded('update', name, resource, resp)
+ return _succeeded('no_changes', name, resource)
-def volume_type_absent(name=None, cloud_name=None):
- """
- Ensures that the specified volume type is absent.
- """
- ret = {
- 'name': name,
- 'changes': {},
- 'result': True,
- 'comment': 'Volume type "{0}" not found'.format(name)
- }
- type_req = _cinder_call('volume_type_get', name=name, cloud_name=cloud_name)
- if not type_req.get("result"):
- return ret
- else:
- delete_req = _cinder_call('volume_type_delete', name=name,
- cloud_name=cloud_name)
- if delete_req.get("result") is False:
- ret = {
- 'name': name,
- 'changes': {},
- 'result': False,
- 'comment': 'Volume type "{0}" failed to delete'.format(name)
- }
- else:
- ret['comment'] = 'Volume type {0} has been deleted'.format(name)
- ret['changes']['Volume type'] = 'Deleted'
- return ret
+def _resource_absent(resource, name, cloud_name):
+ try:
+ method_name = '{}_get_details'.format(resource)
+ _cinder_call(
+ method_name, name, cloud_name=cloud_name
+ )[resource]
+ except Exception as e:
+ if 'ResourceNotFound' in repr(e):
+ return _succeeded('absent', name, resource)
+ if 'MultipleResourcesFound' in repr(e):
+ return _failed('find', name, resource)
+ try:
+ method_name = '{}_delete'.format(resource)
+ _cinder_call(
+ method_name, name, cloud_name=cloud_name
+ )
+ except Exception as e:
+ log.error('Cinder delete {0} failed with {1}'.format(resource, e))
+ return _failed('delete', name, resource)
+ return _succeeded('delete', name, resource)
+
+
+def volume_type_present(name, cloud_name, **kwargs):
+ return _resource_present('volume_type', name, cloud_name, **kwargs)
+
+
+def volume_type_absent(name, cloud_name):
+ return _resource_absent('volume_type', name, cloud_name)
+
+
+def volume_present(name, cloud_name, size, **kwargs):
+ kwargs.update({
+ 'size': size,
+ })
+ return _resource_present('volume', name, cloud_name, **kwargs)
+
+
+def volume_absent(name, cloud_name):
+ return _resource_absent('volume', name, cloud_name)
def volume_type_key_present(name=None, key=None, value=None, cloud_name=None):
@@ -80,8 +103,8 @@
"""
keys = "{u'" + key + "': u'" + value + "'}"
keys = ast.literal_eval(keys)
- signal_create = _cinder_call('keys_volume_type_set',
- name=name, keys=keys, cloud_name=cloud_name)
+ signal_create = _cinder_call('keys_volume_type_set', name, keys=keys,
+ cloud_name=cloud_name)
if signal_create["result"] is True:
ret = {
'name': name,
@@ -97,3 +120,37 @@
'comment': signal_create.get("comment")
}
return ret
+
+
+def _succeeded(op, name, resource, changes=None):
+ msg_map = {
+ 'create': '{0} {1} created',
+ 'delete': '{0} {1} removed',
+ 'update': '{0} {1} updated',
+ 'no_changes': '{0} {1} is in desired state',
+ 'absent': '{0} {1} not present',
+ 'resources_moved': '{1} resources were moved from {0}',
+ }
+ changes_dict = {
+ 'name': name,
+ 'result': True,
+ 'comment': msg_map[op].format(resource, name),
+ 'changes': changes or {},
+ }
+ return changes_dict
+
+def _failed(op, name, resource):
+ msg_map = {
+ 'create': '{0} {1} failed to create',
+ 'delete': '{0} {1} failed to delete',
+ 'update': '{0} {1} failed to update',
+ 'find': '{0} {1} found multiple {0}',
+ 'resources_moved': 'failed to move {1} from {0}',
+ }
+ changes_dict = {
+ 'name': name,
+ 'result': False,
+ 'comment': msg_map[op].format(resource, name),
+ 'changes': {},
+ }
+ return changes_dict
\ No newline at end of file