blob: 3e2e21c8e54cbc88ad0a352ba6c3cbb0312d0ba9 [file] [log] [blame]
kairat_kushaev5c8626d2018-06-09 18:15:15 +04001"""
2Management of Cinder resources
3"""
4
5import ast
6import logging
7
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +02008log = logging.getLogger(__name__)
kairat_kushaev5c8626d2018-06-09 18:15:15 +04009
10
11def __virtual__():
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020012 return 'cinderv3' if 'cinderv3.volume_list' in __salt__ else False # noqa
kairat_kushaev5c8626d2018-06-09 18:15:15 +040013
14
15def _cinder_call(fname, *args, **kwargs):
16 return __salt__['cinderv3.{}'.format(fname)](*args, **kwargs)
17
18
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020019def _resource_present(resource, name, cloud_name, **kwargs):
20 try:
21 method_name = '{}_get_details'.format(resource)
22 exact_resource = _cinder_call(
23 method_name, name, cloud_name=cloud_name
24 )[resource]
25 except Exception as e:
26 if 'ResourceNotFound' in repr(e):
27 try:
28 method_name = '{}_create'.format(resource)
29 resp = _cinder_call(
30 method_name, name=name, cloud_name=cloud_name, **kwargs
31 )
32 except Exception as e:
33 log.exception('Cinder {0} create failed with {1}'.
34 format(resource, e))
35 return _failed('create', name, resource)
36 return _succeeded('create', name, resource, resp)
37 elif 'MultipleResourcesFound' in repr(e):
38 return _failed('find', name, resource)
kairat_kushaev5c8626d2018-06-09 18:15:15 +040039 else:
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020040 raise
41
42 to_update = {}
43 if to_update:
44 for key in kwargs:
45 if key not in exact_resource or kwargs[key] != exact_resource[key]:
46 to_update[key] = kwargs[key]
47 try:
48 method_name = '{}_update'.format(resource)
49 resp = _cinder_call(
50 method_name, name, cloud_name=cloud_name, **to_update
51 )
52 except Exception as e:
53 log.exception('Cinder {0} update failed with {1}'.format(resource, e))
54 return _failed('update', name, resource)
55 return _succeeded('update', name, resource, resp)
56 return _succeeded('no_changes', name, resource)
kairat_kushaev5c8626d2018-06-09 18:15:15 +040057
58
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020059def _resource_absent(resource, name, cloud_name):
60 try:
61 method_name = '{}_get_details'.format(resource)
62 _cinder_call(
63 method_name, name, cloud_name=cloud_name
64 )[resource]
65 except Exception as e:
66 if 'ResourceNotFound' in repr(e):
67 return _succeeded('absent', name, resource)
68 if 'MultipleResourcesFound' in repr(e):
69 return _failed('find', name, resource)
70 try:
71 method_name = '{}_delete'.format(resource)
72 _cinder_call(
73 method_name, name, cloud_name=cloud_name
74 )
75 except Exception as e:
76 log.error('Cinder delete {0} failed with {1}'.format(resource, e))
77 return _failed('delete', name, resource)
78 return _succeeded('delete', name, resource)
79
80
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +020081def service_enabled(name, binary, cloud_name):
82 """Ensures that the service is enabled on the host
83
84 :param name: name of a host where service is running
85 :param binary: name of the service have to be run
86 """
87 changes = {}
88
89 services = _cinder_call('service_list', host=name, binary=binary, cloud_name=cloud_name)['services']
90
91 enabled_service = [s for s in services if s['status'] == 'enabled']
92
93 if len(enabled_service) > 0:
94 ret = _succeeded('no_changes', name, binary)
95 else:
96 changes = _cinder_call('service_update', name, binary, 'enable', cloud_name=cloud_name)
97 ret = _succeeded('update', name, binary, changes)
98
99 return ret
100
101
102def service_disabled(name, binary, cloud_name, disabled_reason=None):
103 """Ensures that the service is disabled on the host
104
105 :param name: name of a host where service is running
106 :param binary: name of the service have to be disabled
107 """
108 changes = {}
109 kwargs = {}
110
111 if disabled_reason is not None:
112 kwargs['disabled_reason'] = disabled_reason
113
114 services = _cinder_call('service_list', host=name, binary=binary, cloud_name=cloud_name)['services']
115
116 disabled_service = [s for s in services if s['status'] == 'disabled']
117
118 if len(disabled_service) > 0:
119 ret = _succeeded('no_changes', name, binary)
120 else:
121 changes = _cinder_call('service_update', name, binary, 'disable', cloud_name=cloud_name, **kwargs)
122 ret = _succeeded('update', name, binary, changes)
123
124 return ret
125
126
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200127def volume_type_present(name, cloud_name, **kwargs):
128 return _resource_present('volume_type', name, cloud_name, **kwargs)
129
130
131def volume_type_absent(name, cloud_name):
132 return _resource_absent('volume_type', name, cloud_name)
133
134
135def volume_present(name, cloud_name, size, **kwargs):
136 kwargs.update({
137 'size': size,
138 })
139 return _resource_present('volume', name, cloud_name, **kwargs)
140
141
142def volume_absent(name, cloud_name):
143 return _resource_absent('volume', name, cloud_name)
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400144
145
146def volume_type_key_present(name=None, key=None, value=None, cloud_name=None):
147 """
148 Ensures that the extra specs are present on a volume type.
149 """
150 keys = "{u'" + key + "': u'" + value + "'}"
151 keys = ast.literal_eval(keys)
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200152 signal_create = _cinder_call('keys_volume_type_set', name, keys=keys,
153 cloud_name=cloud_name)
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400154 if signal_create["result"] is True:
155 ret = {
156 'name': name,
157 'changes': keys,
158 'result': True,
159 'comment': 'Volume type "{0}" was updated'.format(name)
160 }
161 else:
162 ret = {
163 'name': name,
164 'changes': {},
165 'result': False,
166 'comment': signal_create.get("comment")
167 }
168 return ret
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200169
170
171def _succeeded(op, name, resource, changes=None):
172 msg_map = {
173 'create': '{0} {1} created',
174 'delete': '{0} {1} removed',
175 'update': '{0} {1} updated',
176 'no_changes': '{0} {1} is in desired state',
177 'absent': '{0} {1} not present',
178 'resources_moved': '{1} resources were moved from {0}',
179 }
180 changes_dict = {
181 'name': name,
182 'result': True,
183 'comment': msg_map[op].format(resource, name),
184 'changes': changes or {},
185 }
186 return changes_dict
187
188def _failed(op, name, resource):
189 msg_map = {
190 'create': '{0} {1} failed to create',
191 'delete': '{0} {1} failed to delete',
192 'update': '{0} {1} failed to update',
193 'find': '{0} {1} found multiple {0}',
194 'resources_moved': 'failed to move {1} from {0}',
195 }
196 changes_dict = {
197 'name': name,
198 'result': False,
199 'comment': msg_map[op].format(resource, name),
200 'changes': {},
201 }
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200202 return changes_dict