blob: 97a53d056833663173e5ebb07e9075cd04057bb2 [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):
Sergey Galkin4501d0c2020-02-10 17:50:45 +040016 if __opts__.get('test') and not (fname.find('_list') > 0 or fname.find('_get_') > 0):
17 return {'changes': 'cinderv3 state {} with options {} {} will be executed'.format(fname, args, kwargs),
18 'result': None}
19 else:
20 return __salt__['cinderv3.{}'.format(fname)](*args, **kwargs)
kairat_kushaev5c8626d2018-06-09 18:15:15 +040021
22
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020023def _resource_present(resource, name, cloud_name, **kwargs):
24 try:
25 method_name = '{}_get_details'.format(resource)
26 exact_resource = _cinder_call(
root08402652018-12-28 15:04:23 +000027 method_name, name, cloud_name=cloud_name, **kwargs
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020028 )[resource]
29 except Exception as e:
30 if 'ResourceNotFound' in repr(e):
31 try:
32 method_name = '{}_create'.format(resource)
33 resp = _cinder_call(
34 method_name, name=name, cloud_name=cloud_name, **kwargs
35 )
36 except Exception as e:
37 log.exception('Cinder {0} create failed with {1}'.
38 format(resource, e))
39 return _failed('create', name, resource)
40 return _succeeded('create', name, resource, resp)
41 elif 'MultipleResourcesFound' in repr(e):
42 return _failed('find', name, resource)
kairat_kushaev5c8626d2018-06-09 18:15:15 +040043 else:
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020044 raise
45
46 to_update = {}
47 if to_update:
48 for key in kwargs:
49 if key not in exact_resource or kwargs[key] != exact_resource[key]:
50 to_update[key] = kwargs[key]
51 try:
52 method_name = '{}_update'.format(resource)
53 resp = _cinder_call(
54 method_name, name, cloud_name=cloud_name, **to_update
55 )
56 except Exception as e:
57 log.exception('Cinder {0} update failed with {1}'.format(resource, e))
58 return _failed('update', name, resource)
59 return _succeeded('update', name, resource, resp)
60 return _succeeded('no_changes', name, resource)
kairat_kushaev5c8626d2018-06-09 18:15:15 +040061
62
root08402652018-12-28 15:04:23 +000063def _resource_absent(resource, name, cloud_name, connection_params=None):
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020064 try:
65 method_name = '{}_get_details'.format(resource)
66 _cinder_call(
root08402652018-12-28 15:04:23 +000067 method_name, name, cloud_name=cloud_name,
68 connection_params=connection_params
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020069 )[resource]
70 except Exception as e:
71 if 'ResourceNotFound' in repr(e):
72 return _succeeded('absent', name, resource)
73 if 'MultipleResourcesFound' in repr(e):
74 return _failed('find', name, resource)
75 try:
76 method_name = '{}_delete'.format(resource)
77 _cinder_call(
root08402652018-12-28 15:04:23 +000078 method_name, name, cloud_name=cloud_name,
79 connection_params=connection_params
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +020080 )
81 except Exception as e:
82 log.error('Cinder delete {0} failed with {1}'.format(resource, e))
83 return _failed('delete', name, resource)
84 return _succeeded('delete', name, resource)
85
86
root08402652018-12-28 15:04:23 +000087def service_enabled(name, binary, cloud_name, connection_params=None):
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +020088 """Ensures that the service is enabled on the host
89
root08402652018-12-28 15:04:23 +000090 :param name: name of a host where service is running
91 :param binary: name of the service have to be run
92 :param connection_params: dictionary with salt internal connection params
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +020093 """
94 changes = {}
Oleksandr Shyshko25513822018-12-07 15:26:56 +000095 ret = []
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +020096
root08402652018-12-28 15:04:23 +000097 services = _cinder_call('service_list', host=name, binary=binary, cloud_name=cloud_name,
98 connection_params=connection_params)['services']
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +020099
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000100 disabled_service = [s for s in services if s['status'] == 'disabled']
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200101
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000102 if len(disabled_service):
103 for service in disabled_service:
root08402652018-12-28 15:04:23 +0000104 changes = _cinder_call('service_update', service['host'], binary, 'enable', cloud_name=cloud_name,
105 connection_params=connection_params)
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000106 ret.append(changes)
107 return _succeeded('update', name, binary, {'changes':ret})
108 return _succeeded('no_changes', name, binary)
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200109
110
root08402652018-12-28 15:04:23 +0000111def service_disabled(name, binary, cloud_name, disabled_reason=None, connection_params=None):
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200112 """Ensures that the service is disabled on the host
113
114 :param name: name of a host where service is running
115 :param binary: name of the service have to be disabled
root08402652018-12-28 15:04:23 +0000116 :param connection_params: dictionary with salt internal connection params
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200117 """
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200118 kwargs = {}
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000119 ret = []
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200120
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000121 if disabled_reason:
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200122 kwargs['disabled_reason'] = disabled_reason
123
root08402652018-12-28 15:04:23 +0000124 services = _cinder_call('service_list', host=name, binary=binary, cloud_name=cloud_name,
125 connection_params=connection_params)['services']
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200126
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000127 enabled_services = [s for s in services if s['status'] == 'enabled']
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200128
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000129 if len(enabled_services):
130 for service in enabled_services:
root08402652018-12-28 15:04:23 +0000131 changes = _cinder_call('service_update', service['host'], binary, 'disable',
132 cloud_name=cloud_name, connection_params=connection_params,
133 **kwargs)
Oleksandr Shyshko25513822018-12-07 15:26:56 +0000134 ret.append(changes)
135 return _succeeded('update', name, binary, {'changes':ret})
136 return _succeeded('no_changes', name, binary)
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200137
138
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200139def volume_type_present(name, cloud_name, **kwargs):
140 return _resource_present('volume_type', name, cloud_name, **kwargs)
141
142
root08402652018-12-28 15:04:23 +0000143def volume_type_absent(name, cloud_name, connection_params=None):
144 return _resource_absent('volume_type', name, cloud_name, connection_params)
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200145
146
147def volume_present(name, cloud_name, size, **kwargs):
148 kwargs.update({
149 'size': size,
150 })
151 return _resource_present('volume', name, cloud_name, **kwargs)
152
153
root08402652018-12-28 15:04:23 +0000154def volume_absent(name, cloud_name, connection_params=None):
155 return _resource_absent('volume', name, cloud_name, connection_params)
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400156
157
root08402652018-12-28 15:04:23 +0000158def volume_type_key_present(name=None, key=None, value=None, cloud_name=None,
159 connection_params=None):
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400160 """
161 Ensures that the extra specs are present on a volume type.
162 """
163 keys = "{u'" + key + "': u'" + value + "'}"
164 keys = ast.literal_eval(keys)
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200165 signal_create = _cinder_call('keys_volume_type_set', name, keys=keys,
root08402652018-12-28 15:04:23 +0000166 cloud_name=cloud_name,
167 connection_params=connection_params)
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400168 if signal_create["result"] is True:
169 ret = {
170 'name': name,
171 'changes': keys,
172 'result': True,
173 'comment': 'Volume type "{0}" was updated'.format(name)
174 }
Sergey Galkin4501d0c2020-02-10 17:50:45 +0400175 elif signal_create["result"] is None:
176 ret = {
177 'name': name,
Ivan Berezovskiy0578eee2020-03-30 19:22:28 +0400178 'changes': {},
Sergey Galkin4501d0c2020-02-10 17:50:45 +0400179 'result': None,
180 'comment': 'Volume type "{0}" will be updated'.format(name)
181 }
kairat_kushaev5c8626d2018-06-09 18:15:15 +0400182 else:
183 ret = {
184 'name': name,
185 'changes': {},
186 'result': False,
187 'comment': signal_create.get("comment")
188 }
189 return ret
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200190
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200191def _succeeded(op, name, resource, changes=None):
192 msg_map = {
193 'create': '{0} {1} created',
194 'delete': '{0} {1} removed',
195 'update': '{0} {1} updated',
196 'no_changes': '{0} {1} is in desired state',
197 'absent': '{0} {1} not present',
198 'resources_moved': '{1} resources were moved from {0}',
199 }
200 changes_dict = {
201 'name': name,
Ivan Berezovskiy0578eee2020-03-30 19:22:28 +0400202 'result': None if __opts__.get('test') else True,
Oleksiy Petrenkoe38f5a62018-11-21 12:58:07 +0200203 'comment': msg_map[op].format(resource, name),
204 'changes': changes or {},
205 }
206 return changes_dict
207
208def _failed(op, name, resource):
209 msg_map = {
210 'create': '{0} {1} failed to create',
211 'delete': '{0} {1} failed to delete',
212 'update': '{0} {1} failed to update',
213 'find': '{0} {1} found multiple {0}',
214 'resources_moved': 'failed to move {1} from {0}',
215 }
216 changes_dict = {
217 'name': name,
218 'result': False,
219 'comment': msg_map[op].format(resource, name),
220 'changes': {},
221 }
Oleksandr Shyshko04099ea2018-11-22 16:02:52 +0200222 return changes_dict