blob: bc7e83cf174cded61f4e6d57bb662c7063ba17d6 [file] [log] [blame]
Ales Komarek663b85c2016-03-11 14:26:42 +01001# -*- coding: utf-8 -*-
2'''
3Module for handling maas calls.
4
5:optdepends: pyapi-maas Python adapter
6:configuration: This module is not usable until the following are specified
7 either in a pillar or in the minion's config file::
8
9 maas.url: 'https://maas.domain.com/'
10 maas.token: fdsfdsdsdsfa:fsdfae3fassd:fdsfdsfsafasdfsa
11
12'''
13
14from __future__ import absolute_import
15
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010016import io
Ales Komarek663b85c2016-03-11 14:26:42 +010017import logging
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010018import os.path
19import subprocess
20import urllib2
21import hashlib
Ales Komarek663b85c2016-03-11 14:26:42 +010022
smolaon27359ae2016-03-11 17:15:34 +010023import json
24
Ales Komarek663b85c2016-03-11 14:26:42 +010025LOG = logging.getLogger(__name__)
26
27# Import third party libs
28HAS_MASS = False
29try:
Damian Szelugad0ac0ac2017-03-29 15:15:33 +020030 from maas_client import MAASClient, MAASDispatcher, MAASOAuth
Ales Komarek663b85c2016-03-11 14:26:42 +010031 HAS_MASS = True
32except ImportError:
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010033 LOG.exception('why??')
Ales Komarek663b85c2016-03-11 14:26:42 +010034
35def __virtual__():
36 '''
37 Only load this module if maas-client
38 is installed on this minion.
39 '''
40 if HAS_MASS:
41 return 'maas'
42 return False
43
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010044APIKEY_FILE = '/var/lib/maas/.maas_credentials'
45
46def _format_data(data):
47 class Lazy:
48 def __str__(self):
49 return ' '.join(['{0}={1}'.format(k, v)
50 for k, v in data.iteritems()])
51
52 return Lazy()
Ales Komarek663b85c2016-03-11 14:26:42 +010053
54
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010055def _create_maas_client():
56 global APIKEY_FILE
57 try:
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +010058 api_token = file(APIKEY_FILE).read().splitlines()[-1].strip().split(':')
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010059 except:
60 LOG.exception('token')
61 auth = MAASOAuth(*api_token)
62 api_url = 'http://localhost:5240/MAAS'
Ales Komarek663b85c2016-03-11 14:26:42 +010063 dispatcher = MAASDispatcher()
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010064 return MAASClient(auth, dispatcher, api_url)
Ales Komarek663b85c2016-03-11 14:26:42 +010065
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010066class MaasObject(object):
67 def __init__(self):
68 self._maas = _create_maas_client()
69 self._extra_data_urls = {}
70 self._extra_data = {}
71 self._update = False
72 self._element_key = 'name'
73 self._update_key = 'id'
74
75 def send(self, data):
76 LOG.info('%s %s', self.__class__.__name__.lower(), _format_data(data))
77 if self._update:
78 return self._maas.put(self._update_url.format(data[self._update_key]), **data).read()
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +010079 if isinstance(self._create_url, tuple):
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +020080 return self._maas.post(self._create_url[0].format(**data),
81 *self._create_url[1:], **data).read()
82 return self._maas.post(self._create_url.format(**data), None, **data).read()
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010083
84 def process(self):
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +020085 try:
86 config = __salt__['config.get']('maas')
87 for part in self._config_path.split('.'):
88 config = config.get(part, {})
89 extra = {}
90 for name, url_call in self._extra_data_urls.iteritems():
91 key = 'id'
92 key_name = 'name'
93 if isinstance(url_call, tuple):
94 if len(url_call) == 2:
95 url_call, key = url_call[:]
96 else:
97 url_call, key, key_name = url_call[:]
98 if key:
99 extra[name] = {v[key_name]: v[key] for v in
100 json.loads(self._maas.get(url_call).read())}
101 else:
102 extra[name] = {v[key_name]: v for v in
103 json.loads(self._maas.get(url_call).read())}
104 if self._all_elements_url:
105 all_elements = {}
106 elements = self._maas.get(self._all_elements_url).read()
107 res_json = json.loads(elements)
108 for element in res_json:
109 if isinstance(element, (str, unicode)):
110 all_elements[element] = {}
111 else:
112 all_elements[element[self._element_key]] = element
113 else:
114 all_elements = {}
115 ret = {
116 'success': [],
117 'errors': {},
118 'updated': [],
119 }
120 for name, config_data in config.iteritems():
121 self._update = False
122 try:
123 data = self.fill_data(name, config_data, **extra)
124 if data is None:
125 ret['updated'].append(name)
126 continue
127 if name in all_elements:
128 self._update = True
129 data = self.update(data, all_elements[name])
130 self.send(data)
131 ret['updated'].append(name)
132 else:
133 self.send(data)
134 ret['success'].append(name)
135 except urllib2.HTTPError as e:
136 etxt = e.read()
137 LOG.exception('Failed for object %s reason %s', name, etxt)
138 ret['errors'][name] = str(etxt)
139 except Exception as e:
140 LOG.exception('Failed for object %s reason %s', name, e)
141 ret['errors'][name] = str(e)
142 except Exception:
143 LOG.exception('WTF')
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100144 if ret['errors']:
145 raise Exception(ret)
146 return ret
Ales Komarek663b85c2016-03-11 14:26:42 +0100147
148
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100149class Fabric(MaasObject):
150 def __init__(self):
151 super(Fabric, self).__init__()
152 self._all_elements_url = u'api/2.0/fabrics/'
153 self._create_url = u'api/2.0/fabrics/'
154 self._update_url = u'api/2.0/fabrics/{0}/'
155 self._config_path = 'region.fabrics'
Ales Komarek663b85c2016-03-11 14:26:42 +0100156
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100157 def fill_data(self, name, fabric):
158 data = {
159 'name': name,
160 'description': fabric.get('description', ''),
161 }
162 if 'class_type' in fabric:
163 data['class_type'] = fabric.get('class_type'),
164 return data
Ales Komarek663b85c2016-03-11 14:26:42 +0100165
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100166 def update(self, new, old):
167 new['id'] = str(old['id'])
168 return new
Ales Komarek663b85c2016-03-11 14:26:42 +0100169
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100170class Subnet(MaasObject):
171 def __init__(self):
172 super(Subnet, self).__init__()
173 self._all_elements_url = u'api/2.0/subnets/'
174 self._create_url = u'api/2.0/subnets/'
175 self._update_url = u'api/2.0/subnets/{0}/'
176 self._config_path = 'region.subnets'
177 self._extra_data_urls = {'fabrics':u'api/2.0/fabrics/'}
Ales Komarek0fafa572016-03-11 14:56:44 +0100178
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100179 def fill_data(self, name, subnet, fabrics):
180 data = {
181 'name': name,
182 'fabric': str(fabrics[subnet.get('fabric', '')]),
183 'cidr': subnet.get('cidr'),
184 'gateway_ip': subnet['gateway_ip'],
185 }
186 self._iprange = subnet['iprange']
187 return data
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100188
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100189 def update(self, new, old):
190 new['id'] = str(old['id'])
191 return new
Ales Komarek0fafa572016-03-11 14:56:44 +0100192
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100193 def send(self, data):
194 response = super(Subnet, self).send(data)
195 res_json = json.loads(response)
196 self._process_iprange(res_json['id'])
197 return response
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100198
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100199 def _process_iprange(self, subnet_id):
200 ipranges = json.loads(self._maas.get(u'api/2.0/ipranges/').read())
201 LOG.warn('all %s ipranges %s', subnet_id, ipranges)
202 update = False
203 old_data = None
204 for iprange in ipranges:
205 if iprange['subnet']['id'] == subnet_id:
206 update = True
207 old_data = iprange
208 break
209 data = {
210 'start_ip': self._iprange.get('start'),
211 'end_ip': self._iprange.get('end'),
212 'subnet': str(subnet_id),
213 'type': self._iprange.get('type', 'dynamic')
214 }
215 LOG.warn('INFO: %s\n OLD: %s', data, old_data)
216 LOG.info('iprange %s', _format_data(data))
217 if update:
218 LOG.warn('UPDATING %s %s', data, old_data)
219 self._maas.put(u'api/2.0/ipranges/{0}/'.format(old_data['id']), **data)
smolaonc3385f82016-03-11 19:01:24 +0100220 else:
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100221 self._maas.post(u'api/2.0/ipranges/', None, **data)
smolaonc3385f82016-03-11 19:01:24 +0100222
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100223class DHCPSnippet(MaasObject):
224 def __init__(self):
225 super(DHCPSnippet, self).__init__()
226 self._all_elements_url = u'api/2.0/dhcp-snippets/'
227 self._create_url = u'api/2.0/dhcp-snippets/'
228 self._update_url = u'api/2.0/dhcp-snippets/{0}/'
229 self._config_path = 'region.dhcp_snippets'
230 self._extra_data_urls = {'subnets': u'api/2.0/subnets/'}
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100231
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100232 def fill_data(self, name, snippet, subnets):
233 data = {
234 'name': name,
235 'value': snippet['value'],
236 'description': snippet['description'],
237 'enabled': str(snippet['enabled'] and 1 or 0),
238 'subnet': str(subnets[snippet['subnet']]),
239 }
240 return data
smolaonc3385f82016-03-11 19:01:24 +0100241
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100242 def update(self, new, old):
243 new['id'] = str(old['id'])
244 return new
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100245
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100246class PacketRepository(MaasObject):
247 def __init__(self):
248 super(PacketRepository, self).__init__()
249 self._all_elements_url = u'api/2.0/package-repositories/'
250 self._create_url = u'api/2.0/package-repositories/'
251 self._update_url = u'api/2.0/package-repositories/{0}/'
252 self._config_path = 'region.package_repositories'
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100253
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100254 def fill_data(self, name, package_repository):
255 data = {
256 'name': name,
257 'url': package_repository['url'],
258 'distributions': package_repository['distributions'],
259 'components': package_repository['components'],
260 'arches': package_repository['arches'],
261 'key': package_repository['key'],
262 'enabled': str(package_repository['enabled'] and 1 or 0),
263 }
264 if 'disabled_pockets' in package_repository:
265 data['disabled_pockets'] = package_repository['disable_pockets'],
266 return data
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100267
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100268 def update(self, new, old):
269 new['id'] = str(old['id'])
270 return new
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100271
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100272class Device(MaasObject):
273 def __init__(self):
274 super(Device, self).__init__()
275 self._all_elements_url = u'api/2.0/devices/'
276 self._create_url = u'api/2.0/devices/'
277 self._update_url = u'api/2.0/devices/{0}/'
278 self._config_path = 'region.devices'
279 self._element_key = 'hostname'
280 self._update_key = 'system_id'
smolaonc3385f82016-03-11 19:01:24 +0100281
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100282 def fill_data(self, name, device_data):
283 data = {
284 'mac_addresses': device_data['mac'],
285 'hostname': name,
286 }
287 self._interface = device_data['interface']
288 return data
289
290 def update(self, new, old):
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100291 old_macs = set(v['mac_address'].lower() for v in old['interface_set'])
292 if new['mac_addresses'].lower() not in old_macs:
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100293 self._update = False
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100294 LOG.info('Mac changed deleting old device %s', old['system_id'])
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100295 self._maas.delete(u'api/2.0/devices/{0}/'.format(old['system_id']))
296 else:
297 new[self._update_key] = str(old[self._update_key])
298 return new
299
300 def send(self, data):
301 response = super(Device, self).send(data)
302 resp_json = json.loads(response)
303 system_id = resp_json['system_id']
304 iface_id = resp_json['interface_set'][0]['id']
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100305 self._link_interface(system_id, iface_id)
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100306 return response
307
308 def _link_interface(self, system_id, interface_id):
309 data = {
310 'mode': self._interface.get('mode', 'STATIC'),
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100311 'subnet': self._interface['subnet'],
312 'ip_address': self._interface['ip_address'],
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100313 }
314 if 'default_gateway' in self._interface:
315 data['default_gateway'] = self._interface.get('default_gateway')
316 if self._update:
317 data['force'] = '1'
318 LOG.info('interfaces link_subnet %s %s %s', system_id, interface_id,
319 _format_data(data))
320 self._maas.post(u'/api/2.0/nodes/{0}/interfaces/{1}/'
321 .format(system_id, interface_id), 'link_subnet',
322 **data)
323
324
325class Machine(MaasObject):
326 def __init__(self):
327 super(Machine, self).__init__()
328 self._all_elements_url = u'api/2.0/machines/'
329 self._create_url = u'api/2.0/machines/'
330 self._update_url = u'api/2.0/machines/{0}/'
331 self._config_path = 'region.machines'
332 self._element_key = 'hostname'
333 self._update_key = 'system_id'
334
335 def fill_data(self, name, machine_data):
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100336 power_data = machine_data['power_parameters']
337 data = {
338 'hostname': name,
339 'architecture': machine_data.get('architecture', 'amd64/generic'),
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +0200340 'mac_addresses': machine_data['interface']['mac'],
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100341 'power_type': machine_data.get('power_type', 'ipmi'),
342 'power_parameters_power_address': power_data['power_address'],
343 }
344 if 'power_user' in power_data:
345 data['power_parameters_power_user'] = power_data['power_user']
346 if 'power_password' in power_data:
347 data['power_parameters_power_pass'] = \
348 power_data['power_password']
349 return data
350
351 def update(self, new, old):
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100352 old_macs = set(v['mac_address'].lower() for v in old['interface_set'])
353 if new['mac_addresses'].lower() not in old_macs:
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100354 self._update = False
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100355 LOG.info('Mac changed deleting old machine %s', old['system_id'])
356 self._maas.delete(u'api/2.0/machines/{0}/'.format(old['system_id']))
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100357 else:
358 new[self._update_key] = str(old[self._update_key])
359 return new
360
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +0200361
362class AssignMachinesIP(MaasObject):
363 def __init__(self):
364 super(AssignMachinesIP, self).__init__()
365 self._all_elements_url = None
366 self._create_url = (u'/api/2.0/nodes/{system_id}/interfaces/{interface_id}/', 'link_subnet')
367 self._config_path = 'region.machines'
368 self._element_key = 'hostname'
369 self._update_key = 'system_id'
370 self._extra_data_urls = {'machines' : (u'api/2.0/machines/', None, 'hostname')}
371
372 def fill_data(self, name, data, machines):
373 interface = data['interface']
374 machine = machines[name]
375 if 'ip' not in interface:
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100376 return
377 data = {
378 'mode': 'STATIC',
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +0200379 'subnet': str(interface.get('subnet')),
380 'ip_address': str(interface.get('ip')),
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100381 }
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +0200382 if 'default_gateway' in interface:
383 data['default_gateway'] = interface.get('gateway')
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100384 if self._update:
385 data['force'] = '1'
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +0200386 data['system_id'] = str(machine['system_id'])
387 data['interface_id'] = str(machine['interface_set'][0]['id'])
388 return data
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100389
390
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100391class BootResource(MaasObject):
392 def __init__(self):
393 super(BootResource, self).__init__()
394 self._all_elements_url = u'api/2.0/boot-resources/'
395 self._create_url = u'api/2.0/boot-resources/'
396 self._update_url = u'api/2.0/boot-resources/{0}/'
397 self._config_path = 'region.boot_resources'
398
399 def fill_data(self, name, boot_data):
400 sha256 = hashlib.sha256()
401 sha256.update(file(boot_data['content']).read())
402 data = {
403 'name': name,
404 'title': boot_data['title'],
405 'architecture': boot_data['architecture'],
406 'filetype': boot_data['filetype'],
407 'size': str(os.path.getsize(boot_data['content'])),
408 'sha256': sha256.hexdigest(),
409 'content': io.open(boot_data['content']),
410 }
411 return data
412
413 def update(self, new, old):
414 self._update = False
415 return new
416
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100417class CommissioningScripts(MaasObject):
418 def __init__(self):
419 super(CommissioningScripts, self).__init__()
420 self._all_elements_url = u'api/2.0/commissioning-scripts/'
421 self._create_url = u'api/2.0/commissioning-scripts/'
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100422 self._config_path = 'region.commissioning_scripts'
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100423 self._update_url = u'api/2.0/commissioning-scripts/{0}'
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100424 self._update_key = 'name'
425
426 def fill_data(self, name, file_path):
427 data = {
428 'name': name,
429 'content': io.open(file_path),
430 }
431 return data
432
433 def update(self, new, old):
434 return new
435
436class MaasConfig(MaasObject):
437 def __init__(self):
438 super(MaasConfig, self).__init__()
439 self._all_elements_url = None
440 self._create_url = (u'api/2.0/maas/', u'set_config')
441 self._config_path = 'region.maas_config'
442
443 def fill_data(self, name, value):
444 data = {
445 'name': name,
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100446 'value': str(value),
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100447 }
448 return data
449
450 def update(self, new, old):
451 self._update = False
452 return new
453
454
Krzysztof Szukiełojća1bd77e2017-03-30 08:34:22 +0200455class SSHPrefs(MaasObject):
456 def __init__(self):
457 super(SSHPrefs, self).__init__()
458 self._all_elements_url = None
459 self._create_url = u'api/2.0/account/prefs/sshkeys/'
460 self._config_path = 'region.sshprefs'
461 self._element_key = 'hostname'
462 self._update_key = 'system_id'
463
464 def fill_data(self, value):
465 data = {
466 'key': value,
467 }
468 return data
469
470 def process(self):
471 config = __salt__['config.get']('maas')
472 for part in self._config_path.split('.'):
473 config = config.get(part, {})
474 extra = {}
475 for name, url_call in self._extra_data_urls.iteritems():
476 key = 'id'
477 if isinstance(url_call, tuple):
478 url_call, key = url_call[:]
479 extra[name] = {v['name']: v[key] for v in
480 json.loads(self._maas.get(url_call).read())}
481 if self._all_elements_url:
482 all_elements = {}
483 elements = self._maas.get(self._all_elements_url).read()
484 res_json = json.loads(elements)
485 for element in res_json:
486 if isinstance(element, (str, unicode)):
487 all_elements[element] = {}
488 else:
489 all_elements[element[self._element_key]] = element
490 else:
491 all_elements = {}
492 ret = {
493 'success': [],
494 'errors': {},
495 'updated': [],
496 }
497 for config_data in config:
498 name = config_data[:10]
499 try:
500 data = self.fill_data(config_data, **extra)
501 self.send(data)
502 ret['success'].append(name)
503 except urllib2.HTTPError as e:
504 etxt = e.read()
505 LOG.exception('Failed for object %s reason %s', name, etxt)
506 ret['errors'][name] = str(etxt)
507 except Exception as e:
508 LOG.exception('Failed for object %s reason %s', name, e)
509 ret['errors'][name] = str(e)
510 if ret['errors']:
511 raise Exception(ret)
512 return ret
Krzysztof Szukiełojć8cc32b42017-03-29 15:22:57 +0200513
514class Domain(MaasObject):
515 def __init__(self):
516 super(Domain, self).__init__()
517 self._all_elements_url = u'/api/2.0/domains/'
518 self._create_url = u'/api/2.0/domains/'
519 self._config_path = 'region.domain'
520 self._update_url = u'/api/2.0/domains/{0}/'
521
522 def fill_data(self, value):
523 data = {
524 'name': value,
525 }
526 self._update = True
527 return data
528
529 def update(self, new, old):
530 new['id'] = str(old['id'])
531 new['authoritative'] = str(old['authoritative'])
532 return new
533
534 def process(self):
535 config = __salt__['config.get']('maas')
536 for part in self._config_path.split('.'):
537 config = config.get(part, {})
538 extra = {}
539 for name, url_call in self._extra_data_urls.iteritems():
540 key = 'id'
541 if isinstance(url_call, tuple):
542 url_call, key = url_call[:]
543 extra[name] = {v['name']: v[key] for v in
544 json.loads(self._maas.get(url_call).read())}
545 if self._all_elements_url:
546 all_elements = {}
547 elements = self._maas.get(self._all_elements_url).read()
548 res_json = json.loads(elements)
549 for element in res_json:
550 if isinstance(element, (str, unicode)):
551 all_elements[element] = {}
552 else:
553 all_elements[element[self._element_key]] = element
554 else:
555 all_elements = {}
556 ret = {
557 'success': [],
558 'errors': {},
559 'updated': [],
560 }
561 try:
562 data = self.fill_data(config, **extra)
563 data = self.update(data, all_elements.values()[0])
564 self.send(data)
565 ret['success'].append('domain')
566 except urllib2.HTTPError as e:
567 etxt = e.read()
568 LOG.exception('Failed for object %s reason %s', 'domain', etxt)
569 ret['errors']['domain'] = str(etxt)
570 except Exception as e:
571 LOG.exception('Failed for object %s reason %s', 'domain', e)
572 ret['errors']['domain'] = str(e)
573 if ret['errors']:
574 raise Exception(ret)
575 return ret
576
577
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100578def process_fabrics():
579 return Fabric().process()
580
581def process_subnets():
582 return Subnet().process()
583
584def process_dhcp_snippets():
585 return DHCPSnippet().process()
586
587def process_package_repositories():
588 return PacketRepository().process()
589
590def process_devices():
591 return Device().process()
592
593def process_machines():
594 return Machine().process()
595
596def process_boot_resources():
597 return BootResource().process()
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100598
599def process_maas_config():
600 return MaasConfig().process()
601
602def process_commissioning_scripts():
603 return CommissioningScripts().process()
Krzysztof Szukiełojć8cc32b42017-03-29 15:22:57 +0200604
605def process_domain():
606 return Domain().process()
Krzysztof Szukiełojća1bd77e2017-03-30 08:34:22 +0200607
608def process_sshprefs():
609 return SSHPrefs().process()
Krzysztof Szukiełojćd57a32d2017-04-04 11:25:02 +0200610
611def process_assign_machines_ip():
612 return AssignMachinesIP().process()