blob: 97609c12addfa7788b9fcacdeaa28ba90337729b [file] [log] [blame]
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +03001# Copyright 2018 Mirantis Inc
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
Oleksiy Petrenko14384262018-04-12 13:59:04 +030015from oslo_utils.strutils import bool_from_string
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +030016import logging
17log = logging.getLogger(__name__)
18
19
20def __virtual__():
21 '''
22 Only load if manila module is present in __salt__
23 '''
24 return 'manilang' if 'manilang.list_share_types' in __salt__ else False
25
26
27manilang_func = {
28 'list_types': 'manilang.list_share_types',
29 'create_type': 'manilang.create_share_type',
30 'set_type_specs': 'manilang.set_share_type_extra_specs',
31 'unset_type_specs': 'manilang.unset_share_type_extra_specs',
32 'delete_type': 'manilang.delete_share_type',
Oleksandr Shyshkoc08432f2018-11-23 17:15:51 +000033 'service_list': 'manilang.service_list',
34 'service_update': 'manilang.service_update',
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +030035}
36
37
Oleksiy Petrenko14384262018-04-12 13:59:04 +030038def share_type_present(name, extra_specs, cloud_name, microversion=None,
39 **kwargs):
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +030040 """
41 Ensure that share_type is present and has desired parameters
42
43 This function will create the desired share type if one with the requested
44 name does not exist. If it does, it will be updated to correspond to
45 parameters passed to this function.
46
47 :param name: name of the share type.
48 :param extra_specs: dictionary of extra_specs that share type should have.
49 It contains one required parameter - driver_handles_share_servers.
50 :param kwargs: other arguments that will be pushed into share_type
51 dictionary to be POSTed, if specified.
52
53 """
Oleksiy Petrenko14384262018-04-12 13:59:04 +030054 for key in extra_specs:
55 try:
56 extra_specs[key] = str(
57 bool_from_string(extra_specs[key], strict=True)
58 )
59 except ValueError:
60 extra_specs[key] = str(extra_specs[key])
61
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +030062 origin_share_types = __salt__[
63 manilang_func['list_types']
64 ](cloud_name=cloud_name)['share_types']
65 share_types = [
66 share_type
67 for share_type in origin_share_types if share_type['name'] == name
68 ]
69 if not share_types:
70 try:
71 res = __salt__[
72 manilang_func['create_type']
Oleksiy Petrenko14384262018-04-12 13:59:04 +030073 ](name, extra_specs, cloud_name=cloud_name,
74 microversion=microversion, **kwargs)
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +030075 except Exception as e:
76 log.error('Manila share type create failed with {}'.format(e))
77 return _create_failed(name, 'resource')
78 return _created(name, 'share_type', res)
79
80 elif len(share_types) == 1:
81 exact_share_type = share_types[0]
82
83 api_extra_specs = exact_share_type['extra_specs']
84 api_keys = set(api_extra_specs)
85 sls_keys = set(extra_specs)
86
87 to_delete = api_keys - sls_keys
88 to_add = sls_keys - api_keys
89 to_update = sls_keys & api_keys
90 resp = {}
91
92 for key in to_delete:
93 try:
94 __salt__[
95 manilang_func['unset_type_specs']
Oleksiy Petrenko14384262018-04-12 13:59:04 +030096 ](exact_share_type['id'], key, cloud_name=cloud_name,
97 microversion=microversion)
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +030098 except Exception as e:
99 log.error(
100 'Manila share type delete '
101 'extra specs failed with {}'.format(e)
102 )
103 return _update_failed(name, 'share_type_extra_specs')
Oleksiy Petrenko14384262018-04-12 13:59:04 +0300104 resp.update({'deleted_extra_specs': tuple(to_delete)})
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +0300105
106 diff = {}
107
108 for key in to_add:
109 diff[key] = extra_specs[key]
110 for key in to_update:
111 if extra_specs[key] != api_extra_specs[key]:
112 diff[key] = extra_specs[key]
113 if diff:
114 try:
115 resp.update(
116 __salt__[
117 manilang_func['set_type_specs']
Oleksiy Petrenko14384262018-04-12 13:59:04 +0300118 ](exact_share_type['id'], diff,
119 cloud_name=cloud_name, microversion=microversion)
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +0300120 )
121 except Exception as e:
122 log.error(
123 'Manila share type update '
124 'extra specs failed with {}'.format(e)
125 )
126 return _update_failed(name, 'share_type_extra_specs')
127 if to_delete or diff:
128 return _updated(name, 'share_type', resp)
129 return _no_changes(name, 'share_type')
130 else:
131 return _find_failed(name, 'share_type')
132
133
134def share_type_absent(name, cloud_name):
135 origin_share_types = __salt__[
136 manilang_func['list_types']
137 ](cloud_name=cloud_name)['share_types']
138 share_types = [
139 share_type
140 for share_type in origin_share_types if share_type['name'] == name
141 ]
142 if not share_types:
143 return _absent(name, 'share_type')
144 elif len(share_types) == 1:
145 try:
146 __salt__[manilang_func['delete_type']](share_types[0]['id'],
147 cloud_name=cloud_name)
148 except Exception as e:
149 log.error('Manila share type delete failed with {}'.format(e))
150 return _delete_failed(name, 'share_type')
151 return _deleted(name, 'share_type')
152 else:
153 return _find_failed(name, 'share_type')
154
155
Oleksandr Shyshkoc08432f2018-11-23 17:15:51 +0000156def service_enabled(name, binary, cloud_name, microversion=None):
157 """
158 Method allows enable service by binary and name.
159
160 :param name: name of a host where service is running
161 :param binary: name of the service have to be run
162 """
163
164 ret = {}
165
166 services = __salt__[manilang_func['service_list']](binary=binary, cloud_name=cloud_name)['services']
167
168 # You are able to either enable certain manila-share instance by name@driver
169 # or all existed instances on a node by name
170 if '@' in name:
171 disabled_services = [s for s in services if name == s['host'] and s['status'] == 'disabled']
172 else:
173 disabled_services = [s for s in services if name == s['host'].split('@')[0] and s['status'] == 'disabled']
174
175 if len(disabled_services):
176 for service in disabled_services:
177
178 changes = __salt__[manilang_func['service_update']](service['host'], binary, 'enable', cloud_name=cloud_name, microversion=microversion)
179 ret[service['host']] = {'disabled': changes['disabled']}
180
181 return _updated(name, binary, ret)
182 return _no_changes(name, binary)
183
184
185def service_disabled(name, binary, cloud_name, microversion=None):
186 """
187 Method allows disable service by binary and name.
188
189 :param name: name of a host where service is running
190 :param binary: name of the service have to be disabled
191 """
192
193 ret = {}
194
195 services = __salt__[manilang_func['service_list']](binary=binary, cloud_name=cloud_name)['services']
196
197 # You are able to either disable certain manila-share instance by name@driver
198 # or all existed instances on a node by name
199 if '@' in name:
200 enabled_services = [s for s in services if name == s['host'] and s['status'] == 'enabled']
201 else:
202 enabled_services = [s for s in services if name == s['host'].split('@')[0] and s['status'] == 'enabled']
203
204 if len(enabled_services):
205 for service in enabled_services:
206
207 changes = __salt__[manilang_func['service_update']](service['host'], binary, 'disable', cloud_name=cloud_name, microversion=microversion)
208 ret[service['host']] = {'disabled': changes['disabled']}
209
210 return _updated(name, binary, ret)
211 return _no_changes(name, binary)
212
213
Oleksiy Petrenkoe2c8da22018-03-30 18:27:58 +0300214def _created(name, resource, resource_definition):
215 changes_dict = {
216 'name': name,
217 'changes': resource_definition,
218 'result': True,
219 'comment': '{}{} created'.format(resource, name)
220 }
221 return changes_dict
222
223
224def _updated(name, resource, resource_definition):
225 changes_dict = {
226 'name': name,
227 'changes': resource_definition,
228 'result': True,
229 'comment': '{}{} updated'.format(resource, name)
230 }
231 return changes_dict
232
233
234def _no_changes(name, resource):
235 changes_dict = {
236 'name': name,
237 'changes': {},
238 'result': True,
239 'comment': '{}{} is in desired state'.format(resource, name)
240 }
241 return changes_dict
242
243
244def _deleted(name, resource):
245 changes_dict = {
246 'name': name,
247 'changes': {},
248 'result': True,
249 'comment': '{}{} removed'.format(resource, name)
250 }
251 return changes_dict
252
253
254def _absent(name, resource):
255 changes_dict = {'name': name,
256 'changes': {},
257 'comment': '{0} {1} not present'.format(resource, name),
258 'result': True}
259 return changes_dict
260
261
262def _delete_failed(name, resource):
263 changes_dict = {'name': name,
264 'changes': {},
265 'comment': '{0} {1} failed to delete'.format(resource,
266 name),
267 'result': False}
268 return changes_dict
269
270
271def _create_failed(name, resource):
272 changes_dict = {'name': name,
273 'changes': {},
274 'comment': '{0} {1} failed to create'.format(resource,
275 name),
276 'result': False}
277 return changes_dict
278
279
280def _update_failed(name, resource):
281 changes_dict = {'name': name,
282 'changes': {},
283 'comment': '{0} {1} failed to update'.format(resource,
284 name),
285 'result': False}
286 return changes_dict
287
288
289def _find_failed(name, resource):
290 changes_dict = {
291 'name': name,
292 'changes': {},
293 'comment': '{0} {1} found multiple {0}'.format(resource, name),
294 'result': False,
295 }
296 return changes_dict