blob: 4b127d85e74f40ee76eadb2b40c6c2bbaf43f38c [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):
80 return self._maas.post(*self._create_url, **data).read()
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +010081 return self._maas.post(self._create_url, None, **data).read()
82
83 def process(self):
84 config = __salt__['config.get']('maas')
85 for part in self._config_path.split('.'):
86 config = config.get(part, {})
87 extra = {}
88 for name, url_call in self._extra_data_urls.iteritems():
89 key = 'id'
90 if isinstance(url_call, tuple):
91 url_call, key = url_call[:]
92 extra[name] = {v['name']: v[key] for v in
93 json.loads(self._maas.get(url_call).read())}
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +010094 if self._all_elements_url:
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +010095 all_elements = {}
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +010096 elements = self._maas.get(self._all_elements_url).read()
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +010097 res_json = json.loads(elements)
98 for element in res_json:
99 if isinstance(element, (str, unicode)):
100 all_elements[element] = {}
101 else:
102 all_elements[element[self._element_key]] = element
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100103 else:
104 all_elements = {}
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100105 ret = {
106 'success': [],
107 'errors': {},
108 'updated': [],
109 }
110 for name, config_data in config.iteritems():
Krzysztof Szukiełojć7780a7d2017-03-29 16:57:02 +0200111 self._update = False
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100112 try:
113 data = self.fill_data(name, config_data, **extra)
114 if name in all_elements:
115 self._update = True
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100116 data = self.update(data, all_elements[name])
117 self.send(data)
118 ret['updated'].append(name)
119 else:
120 self.send(data)
121 ret['success'].append(name)
122 except urllib2.HTTPError as e:
123 etxt = e.read()
124 LOG.exception('Failed for object %s reason %s', name, etxt)
125 ret['errors'][name] = str(etxt)
126 except Exception as e:
127 LOG.exception('Failed for object %s reason %s', name, e)
128 ret['errors'][name] = str(e)
129 if ret['errors']:
130 raise Exception(ret)
131 return ret
Ales Komarek663b85c2016-03-11 14:26:42 +0100132
133
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100134class Fabric(MaasObject):
135 def __init__(self):
136 super(Fabric, self).__init__()
137 self._all_elements_url = u'api/2.0/fabrics/'
138 self._create_url = u'api/2.0/fabrics/'
139 self._update_url = u'api/2.0/fabrics/{0}/'
140 self._config_path = 'region.fabrics'
Ales Komarek663b85c2016-03-11 14:26:42 +0100141
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100142 def fill_data(self, name, fabric):
143 data = {
144 'name': name,
145 'description': fabric.get('description', ''),
146 }
147 if 'class_type' in fabric:
148 data['class_type'] = fabric.get('class_type'),
149 return data
Ales Komarek663b85c2016-03-11 14:26:42 +0100150
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100151 def update(self, new, old):
152 new['id'] = str(old['id'])
153 return new
Ales Komarek663b85c2016-03-11 14:26:42 +0100154
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100155class Subnet(MaasObject):
156 def __init__(self):
157 super(Subnet, self).__init__()
158 self._all_elements_url = u'api/2.0/subnets/'
159 self._create_url = u'api/2.0/subnets/'
160 self._update_url = u'api/2.0/subnets/{0}/'
161 self._config_path = 'region.subnets'
162 self._extra_data_urls = {'fabrics':u'api/2.0/fabrics/'}
Ales Komarek0fafa572016-03-11 14:56:44 +0100163
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100164 def fill_data(self, name, subnet, fabrics):
165 data = {
166 'name': name,
167 'fabric': str(fabrics[subnet.get('fabric', '')]),
168 'cidr': subnet.get('cidr'),
169 'gateway_ip': subnet['gateway_ip'],
170 }
171 self._iprange = subnet['iprange']
172 return data
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100173
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100174 def update(self, new, old):
175 new['id'] = str(old['id'])
176 return new
Ales Komarek0fafa572016-03-11 14:56:44 +0100177
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100178 def send(self, data):
179 response = super(Subnet, self).send(data)
180 res_json = json.loads(response)
181 self._process_iprange(res_json['id'])
182 return response
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100183
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100184 def _process_iprange(self, subnet_id):
185 ipranges = json.loads(self._maas.get(u'api/2.0/ipranges/').read())
186 LOG.warn('all %s ipranges %s', subnet_id, ipranges)
187 update = False
188 old_data = None
189 for iprange in ipranges:
190 if iprange['subnet']['id'] == subnet_id:
191 update = True
192 old_data = iprange
193 break
194 data = {
195 'start_ip': self._iprange.get('start'),
196 'end_ip': self._iprange.get('end'),
197 'subnet': str(subnet_id),
198 'type': self._iprange.get('type', 'dynamic')
199 }
200 LOG.warn('INFO: %s\n OLD: %s', data, old_data)
201 LOG.info('iprange %s', _format_data(data))
202 if update:
203 LOG.warn('UPDATING %s %s', data, old_data)
204 self._maas.put(u'api/2.0/ipranges/{0}/'.format(old_data['id']), **data)
smolaonc3385f82016-03-11 19:01:24 +0100205 else:
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100206 self._maas.post(u'api/2.0/ipranges/', None, **data)
smolaonc3385f82016-03-11 19:01:24 +0100207
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100208class DHCPSnippet(MaasObject):
209 def __init__(self):
210 super(DHCPSnippet, self).__init__()
211 self._all_elements_url = u'api/2.0/dhcp-snippets/'
212 self._create_url = u'api/2.0/dhcp-snippets/'
213 self._update_url = u'api/2.0/dhcp-snippets/{0}/'
214 self._config_path = 'region.dhcp_snippets'
215 self._extra_data_urls = {'subnets': u'api/2.0/subnets/'}
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100216
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100217 def fill_data(self, name, snippet, subnets):
218 data = {
219 'name': name,
220 'value': snippet['value'],
221 'description': snippet['description'],
222 'enabled': str(snippet['enabled'] and 1 or 0),
223 'subnet': str(subnets[snippet['subnet']]),
224 }
225 return data
smolaonc3385f82016-03-11 19:01:24 +0100226
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100227 def update(self, new, old):
228 new['id'] = str(old['id'])
229 return new
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100230
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100231class PacketRepository(MaasObject):
232 def __init__(self):
233 super(PacketRepository, self).__init__()
234 self._all_elements_url = u'api/2.0/package-repositories/'
235 self._create_url = u'api/2.0/package-repositories/'
236 self._update_url = u'api/2.0/package-repositories/{0}/'
237 self._config_path = 'region.package_repositories'
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100238
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100239 def fill_data(self, name, package_repository):
240 data = {
241 'name': name,
242 'url': package_repository['url'],
243 'distributions': package_repository['distributions'],
244 'components': package_repository['components'],
245 'arches': package_repository['arches'],
246 'key': package_repository['key'],
247 'enabled': str(package_repository['enabled'] and 1 or 0),
248 }
249 if 'disabled_pockets' in package_repository:
250 data['disabled_pockets'] = package_repository['disable_pockets'],
251 return data
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100252
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100253 def update(self, new, old):
254 new['id'] = str(old['id'])
255 return new
Krzysztof Szukiełojć15b62b72017-02-15 08:58:18 +0100256
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100257class Device(MaasObject):
258 def __init__(self):
259 super(Device, self).__init__()
260 self._all_elements_url = u'api/2.0/devices/'
261 self._create_url = u'api/2.0/devices/'
262 self._update_url = u'api/2.0/devices/{0}/'
263 self._config_path = 'region.devices'
264 self._element_key = 'hostname'
265 self._update_key = 'system_id'
smolaonc3385f82016-03-11 19:01:24 +0100266
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100267 def fill_data(self, name, device_data):
268 data = {
269 'mac_addresses': device_data['mac'],
270 'hostname': name,
271 }
272 self._interface = device_data['interface']
273 return data
274
275 def update(self, new, old):
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100276 old_macs = set(v['mac_address'].lower() for v in old['interface_set'])
277 if new['mac_addresses'].lower() not in old_macs:
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100278 self._update = False
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100279 LOG.info('Mac changed deleting old device %s', old['system_id'])
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100280 self._maas.delete(u'api/2.0/devices/{0}/'.format(old['system_id']))
281 else:
282 new[self._update_key] = str(old[self._update_key])
283 return new
284
285 def send(self, data):
286 response = super(Device, self).send(data)
287 resp_json = json.loads(response)
288 system_id = resp_json['system_id']
289 iface_id = resp_json['interface_set'][0]['id']
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100290 self._link_interface(system_id, iface_id)
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100291 return response
292
293 def _link_interface(self, system_id, interface_id):
294 data = {
295 'mode': self._interface.get('mode', 'STATIC'),
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100296 'subnet': self._interface['subnet'],
297 'ip_address': self._interface['ip_address'],
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100298 }
299 if 'default_gateway' in self._interface:
300 data['default_gateway'] = self._interface.get('default_gateway')
301 if self._update:
302 data['force'] = '1'
303 LOG.info('interfaces link_subnet %s %s %s', system_id, interface_id,
304 _format_data(data))
305 self._maas.post(u'/api/2.0/nodes/{0}/interfaces/{1}/'
306 .format(system_id, interface_id), 'link_subnet',
307 **data)
308
309
310class Machine(MaasObject):
311 def __init__(self):
312 super(Machine, self).__init__()
313 self._all_elements_url = u'api/2.0/machines/'
314 self._create_url = u'api/2.0/machines/'
315 self._update_url = u'api/2.0/machines/{0}/'
316 self._config_path = 'region.machines'
317 self._element_key = 'hostname'
318 self._update_key = 'system_id'
319
320 def fill_data(self, name, machine_data):
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100321 self._interface = machine_data['interface']
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100322 power_data = machine_data['power_parameters']
323 data = {
324 'hostname': name,
325 'architecture': machine_data.get('architecture', 'amd64/generic'),
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100326 'mac_addresses': self._interface['mac'],
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100327 'power_type': machine_data.get('power_type', 'ipmi'),
328 'power_parameters_power_address': power_data['power_address'],
329 }
330 if 'power_user' in power_data:
331 data['power_parameters_power_user'] = power_data['power_user']
332 if 'power_password' in power_data:
333 data['power_parameters_power_pass'] = \
334 power_data['power_password']
335 return data
336
337 def update(self, new, old):
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100338 old_macs = set(v['mac_address'].lower() for v in old['interface_set'])
339 if new['mac_addresses'].lower() not in old_macs:
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100340 self._update = False
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100341 LOG.info('Mac changed deleting old machine %s', old['system_id'])
342 self._maas.delete(u'api/2.0/machines/{0}/'.format(old['system_id']))
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100343 else:
344 new[self._update_key] = str(old[self._update_key])
345 return new
346
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100347 def _link_interface(self, system_id, interface_id):
348 if 'ip' not in self._interface:
349 return
350 data = {
351 'mode': 'STATIC',
352 'subnet': self._interface.get('subnet'),
353 'ip_address': self._interface.get('ip'),
354 }
355 if 'default_gateway' in self._interface:
356 data['default_gateway'] = self._interface.get('gateway')
357 if self._update:
358 data['force'] = '1'
359 LOG.info('interfaces link_subnet %s %s %s', system_id, interface_id,
360 _format_data(data))
361 self._maas.post(u'/api/2.0/nodes/{0}/interfaces/{1}/'
362 .format(system_id, interface_id), 'link_subnet',
363 **data)
364
365 def send(self, data):
366 response = super(Machine, self).send(data)
367 resp_json = json.loads(response)
368 system_id = resp_json['system_id']
369 iface_id = resp_json['interface_set'][0]['id']
370 self._link_interface(system_id, iface_id)
371 return response
372
373
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100374class BootResource(MaasObject):
375 def __init__(self):
376 super(BootResource, self).__init__()
377 self._all_elements_url = u'api/2.0/boot-resources/'
378 self._create_url = u'api/2.0/boot-resources/'
379 self._update_url = u'api/2.0/boot-resources/{0}/'
380 self._config_path = 'region.boot_resources'
381
382 def fill_data(self, name, boot_data):
383 sha256 = hashlib.sha256()
384 sha256.update(file(boot_data['content']).read())
385 data = {
386 'name': name,
387 'title': boot_data['title'],
388 'architecture': boot_data['architecture'],
389 'filetype': boot_data['filetype'],
390 'size': str(os.path.getsize(boot_data['content'])),
391 'sha256': sha256.hexdigest(),
392 'content': io.open(boot_data['content']),
393 }
394 return data
395
396 def update(self, new, old):
397 self._update = False
398 return new
399
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100400class CommissioningScripts(MaasObject):
401 def __init__(self):
402 super(CommissioningScripts, self).__init__()
403 self._all_elements_url = u'api/2.0/commissioning-scripts/'
404 self._create_url = u'api/2.0/commissioning-scripts/'
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100405 self._config_path = 'region.commissioning_scripts'
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100406 self._update_url = u'api/2.0/commissioning-scripts/{0}'
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100407 self._update_key = 'name'
408
409 def fill_data(self, name, file_path):
410 data = {
411 'name': name,
412 'content': io.open(file_path),
413 }
414 return data
415
416 def update(self, new, old):
417 return new
418
419class MaasConfig(MaasObject):
420 def __init__(self):
421 super(MaasConfig, self).__init__()
422 self._all_elements_url = None
423 self._create_url = (u'api/2.0/maas/', u'set_config')
424 self._config_path = 'region.maas_config'
425
426 def fill_data(self, name, value):
427 data = {
428 'name': name,
Krzysztof Szukiełojća6352a42017-03-17 14:21:57 +0100429 'value': str(value),
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100430 }
431 return data
432
433 def update(self, new, old):
434 self._update = False
435 return new
436
437
Krzysztof Szukiełojća1bd77e2017-03-30 08:34:22 +0200438class SSHPrefs(MaasObject):
439 def __init__(self):
440 super(SSHPrefs, self).__init__()
441 self._all_elements_url = None
442 self._create_url = u'api/2.0/account/prefs/sshkeys/'
443 self._config_path = 'region.sshprefs'
444 self._element_key = 'hostname'
445 self._update_key = 'system_id'
446
447 def fill_data(self, value):
448 data = {
449 'key': value,
450 }
451 return data
452
453 def process(self):
454 config = __salt__['config.get']('maas')
455 for part in self._config_path.split('.'):
456 config = config.get(part, {})
457 extra = {}
458 for name, url_call in self._extra_data_urls.iteritems():
459 key = 'id'
460 if isinstance(url_call, tuple):
461 url_call, key = url_call[:]
462 extra[name] = {v['name']: v[key] for v in
463 json.loads(self._maas.get(url_call).read())}
464 if self._all_elements_url:
465 all_elements = {}
466 elements = self._maas.get(self._all_elements_url).read()
467 res_json = json.loads(elements)
468 for element in res_json:
469 if isinstance(element, (str, unicode)):
470 all_elements[element] = {}
471 else:
472 all_elements[element[self._element_key]] = element
473 else:
474 all_elements = {}
475 ret = {
476 'success': [],
477 'errors': {},
478 'updated': [],
479 }
480 for config_data in config:
481 name = config_data[:10]
482 try:
483 data = self.fill_data(config_data, **extra)
484 self.send(data)
485 ret['success'].append(name)
486 except urllib2.HTTPError as e:
487 etxt = e.read()
488 LOG.exception('Failed for object %s reason %s', name, etxt)
489 ret['errors'][name] = str(etxt)
490 except Exception as e:
491 LOG.exception('Failed for object %s reason %s', name, e)
492 ret['errors'][name] = str(e)
493 if ret['errors']:
494 raise Exception(ret)
495 return ret
Krzysztof Szukiełojć8cc32b42017-03-29 15:22:57 +0200496
497class Domain(MaasObject):
498 def __init__(self):
499 super(Domain, self).__init__()
500 self._all_elements_url = u'/api/2.0/domains/'
501 self._create_url = u'/api/2.0/domains/'
502 self._config_path = 'region.domain'
503 self._update_url = u'/api/2.0/domains/{0}/'
504
505 def fill_data(self, value):
506 data = {
507 'name': value,
508 }
509 self._update = True
510 return data
511
512 def update(self, new, old):
513 new['id'] = str(old['id'])
514 new['authoritative'] = str(old['authoritative'])
515 return new
516
517 def process(self):
518 config = __salt__['config.get']('maas')
519 for part in self._config_path.split('.'):
520 config = config.get(part, {})
521 extra = {}
522 for name, url_call in self._extra_data_urls.iteritems():
523 key = 'id'
524 if isinstance(url_call, tuple):
525 url_call, key = url_call[:]
526 extra[name] = {v['name']: v[key] for v in
527 json.loads(self._maas.get(url_call).read())}
528 if self._all_elements_url:
529 all_elements = {}
530 elements = self._maas.get(self._all_elements_url).read()
531 res_json = json.loads(elements)
532 for element in res_json:
533 if isinstance(element, (str, unicode)):
534 all_elements[element] = {}
535 else:
536 all_elements[element[self._element_key]] = element
537 else:
538 all_elements = {}
539 ret = {
540 'success': [],
541 'errors': {},
542 'updated': [],
543 }
544 try:
545 data = self.fill_data(config, **extra)
546 data = self.update(data, all_elements.values()[0])
547 self.send(data)
548 ret['success'].append('domain')
549 except urllib2.HTTPError as e:
550 etxt = e.read()
551 LOG.exception('Failed for object %s reason %s', 'domain', etxt)
552 ret['errors']['domain'] = str(etxt)
553 except Exception as e:
554 LOG.exception('Failed for object %s reason %s', 'domain', e)
555 ret['errors']['domain'] = str(e)
556 if ret['errors']:
557 raise Exception(ret)
558 return ret
559
560
Krzysztof Szukiełojćc4b33092017-02-15 13:25:38 +0100561def process_fabrics():
562 return Fabric().process()
563
564def process_subnets():
565 return Subnet().process()
566
567def process_dhcp_snippets():
568 return DHCPSnippet().process()
569
570def process_package_repositories():
571 return PacketRepository().process()
572
573def process_devices():
574 return Device().process()
575
576def process_machines():
577 return Machine().process()
578
579def process_boot_resources():
580 return BootResource().process()
Krzysztof Szukiełojć43bc7e02017-03-17 10:32:07 +0100581
582def process_maas_config():
583 return MaasConfig().process()
584
585def process_commissioning_scripts():
586 return CommissioningScripts().process()
Krzysztof Szukiełojć8cc32b42017-03-29 15:22:57 +0200587
588def process_domain():
589 return Domain().process()
Krzysztof Szukiełojća1bd77e2017-03-30 08:34:22 +0200590
591def process_sshprefs():
592 return SSHPrefs().process()