blob: 183dc9be2ca5755fdfb9c5fee87bf819ee975899 [file] [log] [blame]
Oleksiy Petrenkoa5eb0602018-07-26 15:12:25 +03001import logging
2
3log = logging.getLogger(__name__)
4
5
6def __virtual__():
7 return 'ironicv1' if 'ironicv1.node_list' in __salt__ else False
8
9
10def _ironicv1_call(fname, *args, **kwargs):
11 return __salt__['ironicv1.{}'.format(fname)](*args, **kwargs)
12
13
14def node_present(name, cloud_name, driver, **kwargs):
15 resource = 'node'
16 microversion = kwargs.pop('microversion', '1.16')
17 try:
18 method_name = '{}_get_details'.format(resource)
19 exact_resource = _ironicv1_call(
20 method_name, name, cloud_name=cloud_name,
21 microversion=microversion
22 )
23 except Exception as e:
24 if 'Not Found' in str(e):
25 try:
26 method_name = '{}_create'.format(resource)
27 resp = _ironicv1_call(
28 method_name, driver, name=name, cloud_name=cloud_name,
29 microversion=microversion,
30 **kwargs
31 )
32 except Exception as e:
33 log.exception('Ironic {0} create failed with {1}'.
34 format('node', e))
35 return _failed('create', name, resource)
36 return _succeeded('create', name, resource, resp)
37
38 to_change = []
39 for prop in kwargs:
40 path = prop.replace('~', '~0').replace('/', '~1')
41 if prop in exact_resource:
42 if exact_resource[prop] != kwargs[prop]:
43 to_change.append({
44 'op': 'replace',
45 'path': '/{}'.format(path),
46 'value': kwargs[prop],
47 })
48 else:
49 to_change.append({
50 'op': 'add',
51 'path': '/{}'.format(path),
52 'value': kwargs[prop],
53 })
54 if to_change:
55 try:
56 method_name = '{}_update'.format(resource)
57 resp = _ironicv1_call(
58 method_name, name, properties=to_change,
59 microversion=microversion, cloud_name=cloud_name,
60 )
61 except Exception as e:
62 log.exception(
63 'Ironic {0} update failed with {1}'.format(resource, e))
64 return _failed('update', name, resource)
65 return _succeeded('update', name, resource, resp)
66 return _succeeded('no_changes', name, resource)
67
68
69def node_absent(name, cloud_name, **kwargs):
70 resource = 'node'
71 microversion = kwargs.pop('microversion', '1.16')
72 try:
73 method_name = '{}_get_details'.format(resource)
74 _ironicv1_call(
75 method_name, name, cloud_name=cloud_name,
76 microversion=microversion
77 )
78 except Exception as e:
79 if 'Not Found' in str(e):
80 return _succeeded('absent', name, resource)
81 try:
82 method_name = '{}_delete'.format(resource)
83 _ironicv1_call(
84 method_name, name, cloud_name=cloud_name, microversion=microversion
85 )
86 except Exception as e:
87 log.error('Ironic delete {0} failed with {1}'.format(resource, e))
88 return _failed('delete', name, resource)
89 return _succeeded('delete', name, resource)
90
91
92def port_present(name, cloud_name, node, address, **kwargs):
93 resource = 'port'
94 microversion = kwargs.pop('microversion', '1.16')
95 method_name = '{}_list'.format(resource)
96 exact_resource = _ironicv1_call(
97 method_name, node=node, address=address,
98 cloud_name=cloud_name, microversion=microversion
99 )['ports']
100 if len(exact_resource) == 0:
101 try:
102 node_uuid = _ironicv1_call(
103 'node_get_details', node, cloud_name=cloud_name,
104 microversion=microversion
105 )['uuid']
106 except Exception as e:
107 return _failed('create', node, "port's node")
108 try:
109 method_name = '{}_create'.format(resource)
110 resp = _ironicv1_call(
111 method_name, node_uuid, address, cloud_name=cloud_name,
112 microversion=microversion, **kwargs)
113 except Exception as e:
114 log.exception('Ironic {0} create failed with {1}'.
115 format('node', e))
116 return _failed('create', name, resource)
117 return _succeeded('create', name, resource, resp)
118 if len(exact_resource) == 1:
119 exact_resource = exact_resource[0]
120 to_change = []
121 for prop in kwargs:
122 path = prop.replace('~', '~0').replace('/', '~1')
123 if prop in exact_resource:
124 if exact_resource[prop] != kwargs[prop]:
125 to_change.append({
126 'op': 'replace',
127 'path': '/{}'.format(path),
128 'value': kwargs[prop],
129 })
130 else:
131 to_change.append({
132 'op': 'add',
133 'path': '/{}'.format(path),
134 'value': kwargs[prop],
135 })
136 if to_change:
137 try:
138 method_name = '{}_update'.format(resource)
139 resp = _ironicv1_call(
140 method_name, name, properties=to_change,
141 microversion=microversion, cloud_name=cloud_name,
142 )
143 except Exception as e:
144 log.exception(
145 'Ironic {0} update failed with {1}'.format(resource, e))
146 return _failed('update', name, resource)
147 return _succeeded('update', name, resource, resp)
148 return _succeeded('no_changes', name, resource)
149 else:
150 return _failed('find', name, resource)
151
152
153def port_absent(name, cloud_name, node, address, **kwargs):
154 resource = 'port'
155 microversion = kwargs.pop('microversion', '1.16')
156 method_name = '{}_list'.format(resource)
157 exact_resource = _ironicv1_call(
158 method_name, node=node, address=address,
159 cloud_name=cloud_name, microversion=microversion
160 )['ports']
161 if len(exact_resource) == 0:
162 return _succeeded('absent', name, resource)
163 elif len(exact_resource) == 1:
164 port_id = exact_resource[0]['uuid']
165 try:
166 method_name = '{}_delete'.format(resource)
167 _ironicv1_call(
168 method_name, port_id, cloud_name=cloud_name,
169 microversion=microversion
170 )
171 except Exception as e:
172 log.error('Ironic delete {0} failed with {1}'.format(resource, e))
173 return _failed('delete', name, resource)
174 return _succeeded('delete', name, resource)
175 else:
176 return _failed('find', name, resource)
177
178
179def _succeeded(op, name, resource, changes=None):
180 msg_map = {
181 'create': '{0} {1} created',
182 'delete': '{0} {1} removed',
183 'update': '{0} {1} updated',
184 'no_changes': '{0} {1} is in desired state',
185 'absent': '{0} {1} not present'
186 }
187 changes_dict = {
188 'name': name,
189 'result': True,
190 'comment': msg_map[op].format(resource, name),
191 'changes': changes or {},
192 }
193 return changes_dict
194
195
196def _failed(op, name, resource):
197 msg_map = {
198 'create': '{0} {1} failed to create',
199 'delete': '{0} {1} failed to delete',
200 'update': '{0} {1} failed to update',
201 'find': '{0} {1} found multiple {0}'
202 }
203 changes_dict = {
204 'name': name,
205 'result': False,
206 'comment': msg_map[op].format(resource, name),
207 'changes': {},
208 }
209 return changes_dict