blob: 763795d80f4d8ef72689cf62e2914aa7e2a66101 [file] [log] [blame]
Ondrej Smolab57a23b2018-01-24 11:18:24 +01001import logging
2from salt.exceptions import CommandExecutionError, SaltInvocationError
3
4LOG = logging.getLogger(__name__)
5
6SIZE = {
7 "M": 1000000,
8 "G": 1000000000,
9 "T": 1000000000000,
10}
11
12RAID = {
13 0: "raid-0",
14 1: "raid-1",
15 5: "raid-5",
16 10: "raid-10",
17}
18
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020019
Ondrej Smolab57a23b2018-01-24 11:18:24 +010020def __virtual__():
azvyagintsevf3515c82018-06-26 18:59:05 +030021 """
Ondrej Smolab57a23b2018-01-24 11:18:24 +010022 Load MaaSng module
azvyagintsevf3515c82018-06-26 18:59:05 +030023 """
Ondrej Smolab57a23b2018-01-24 11:18:24 +010024 return 'maasng'
25
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020026
azvyagintseve2e37a12018-11-01 14:45:49 +020027def maasng(funcname, *args, **kwargs):
28 """
29 Simple wrapper, for __salt__ maasng
30 :param funcname:
31 :param args:
32 :param kwargs:
33 :return:
34 """
35 return __salt__['maasng.{}'.format(funcname)](*args, **kwargs)
36
37
38def merge2dicts(d1, d2):
39 z = d1.copy()
40 z.update(d2)
41 return z
42
43
azvyagintsev3ff2ef12018-06-01 21:30:45 +030044def disk_layout_present(hostname, layout_type, root_size=None, root_device=None,
45 volume_group=None, volume_name=None, volume_size=None,
46 disk={}, **kwargs):
Ondrej Smolab57a23b2018-01-24 11:18:24 +010047 '''
48 Ensure that the disk layout does exist
49
50 :param name: The name of the cloud that should not exist
51 '''
52 ret = {'name': hostname,
53 'changes': {},
54 'result': True,
55 'comment': 'Disk layout "{0}" updated'.format(hostname)}
56
57 machine = __salt__['maasng.get_machine'](hostname)
58 if "error" in machine:
Alexei Lugovoie5b64122018-11-06 12:30:01 +010059 if 0 in machine["error"]:
60 ret['comment'] = "No such machine {0}".format(hostname)
61 ret['changes'] = machine
62 else:
63 ret['comment'] = "State execution failed for machine {0}".format(hostname)
64 ret['result'] = False
65 ret['changes'] = machine
Ondrej Smolab57a23b2018-01-24 11:18:24 +010066 return ret
67
68 if machine["status_name"] != "Ready":
69 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
70 return ret
71
72 if __opts__['test']:
73 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020074 ret['comment'] = 'Disk layout will be updated on {0}, this action will delete current layout.'.format(
75 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010076 return ret
77
78 if layout_type == "flat":
79
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020080 ret["changes"] = __salt__['maasng.update_disk_layout'](
81 hostname, layout_type, root_size, root_device)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010082
83 elif layout_type == "lvm":
84
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020085 ret["changes"] = __salt__['maasng.update_disk_layout'](
86 hostname, layout_type, root_size, root_device, volume_group, volume_name, volume_size)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010087
azvyagintsevbca1f462018-05-25 19:06:46 +030088 elif layout_type == "custom":
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +020089 ret["changes"] = __salt__[
90 'maasng.update_disk_layout'](hostname, layout_type)
azvyagintsevbca1f462018-05-25 19:06:46 +030091
Ondrej Smolab57a23b2018-01-24 11:18:24 +010092 else:
93 ret["comment"] = "Not supported layout provided. Choose flat or lvm"
94 ret['result'] = False
95
96 return ret
97
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020098
azvyagintsev3ff2ef12018-06-01 21:30:45 +030099def raid_present(hostname, name, level, devices=[], partitions=[],
100 partition_schema={}):
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100101 '''
102 Ensure that the raid does exist
103
104 :param name: The name of the cloud that should not exist
105 '''
106
107 ret = {'name': name,
108 'changes': {},
109 'result': True,
110 'comment': 'Raid {0} presented on {1}'.format(name, hostname)}
111
112 machine = __salt__['maasng.get_machine'](hostname)
113 if "error" in machine:
Alexei Lugovoie5b64122018-11-06 12:30:01 +0100114 if 0 in machine["error"]:
115 ret['comment'] = "No such machine {0}".format(hostname)
116 ret['changes'] = machine
117 else:
118 ret['comment'] = "State execution failed for machine {0}".format(
119 hostname)
120 ret['result'] = False
121 ret['changes'] = machine
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100122 return ret
123
124 if machine["status_name"] != "Ready":
125 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
126 return ret
127
128 if __opts__['test']:
129 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200130 ret['comment'] = 'Raid {0} will be updated on {1}'.format(
131 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100132 return ret
133
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200134 # Validate that raid exists
135 # With correct devices/partition
136 # OR
137 # Create raid
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100138
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200139 ret["changes"] = __salt__['maasng.create_raid'](
140 hostname=hostname, name=name, level=level, disks=devices, partitions=partitions)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100141
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200142 # TODO partitions
143 ret["changes"].update(disk_partition_present(
144 hostname, name, partition_schema)["changes"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100145
146 if "error" in ret["changes"]:
147 ret["result"] = False
148
149 return ret
150
151
Denis Egorenkodecf41b2018-11-07 13:04:18 +0400152def disk_partition_present(hostname, name, partition_schema={}):
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100153 '''
154 Ensure that the disk has correct partititioning schema
155
156 :param name: The name of the cloud that should not exist
157 '''
158
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200159 # 1. Validate that disk has correct values for size and mount
160 # a. validate count of partitions
161 # b. validate size of partitions
162 # 2. If not delete all partitions on disk and recreate schema
163 # 3. Validate type exists
164 # if should not exits
165 # delete mount and unformat
166 # 4. Validate mount exists
167 # 5. if not enforce umount or mount
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100168
169 ret = {'name': hostname,
170 'changes': {},
171 'result': True,
Denis Egorenkodecf41b2018-11-07 13:04:18 +0400172 'comment': 'Disk layout {0} presented'.format(name)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100173
174 machine = __salt__['maasng.get_machine'](hostname)
175 if "error" in machine:
Alexei Lugovoie5b64122018-11-06 12:30:01 +0100176 if 0 in machine["error"]:
177 ret['comment'] = "No such machine {0}".format(hostname)
178 ret['changes'] = machine
179 else:
180 ret['comment'] = "State execution failed for machine {0}".format(
181 hostname)
182 ret['result'] = False
183 ret['changes'] = machine
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100184 return ret
185
186 if machine["status_name"] != "Ready":
187 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
188 return ret
189
190 if __opts__['test']:
191 ret['result'] = None
Denis Egorenkodecf41b2018-11-07 13:04:18 +0400192 ret['comment'] = 'Partition schema will be changed on {0}'.format(name)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100193 return ret
194
Denis Egorenkodecf41b2018-11-07 13:04:18 +0400195 partitions = __salt__['maasng.list_partitions'](hostname, name)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100196
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200197 # Calculate actual size in bytes from provided data
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100198 for part_name, part in partition_schema.iteritems():
199 size, unit = part["size"][:-1], part["size"][-1]
200 part["calc_size"] = int(size) * SIZE[unit]
201
202 if len(partitions) == len(partition_schema):
203
204 for part_name, part in partition_schema.iteritems():
205 LOG.info('validated {0}'.format(part["calc_size"]))
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200206 LOG.info('validated {0}'.format(
Denis Egorenkodecf41b2018-11-07 13:04:18 +0400207 int(partitions[name+"-"+part_name.split("-")[-1]]["size"])))
208 if part["calc_size"] == int(partitions[name+"-"+part_name.split("-")[-1]]["size"]):
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100209 LOG.info('validated')
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200210 # TODO validate size (size from maas is not same as calculate?)
211 # TODO validate mount
212 # TODO validate fs type
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100213 else:
214 LOG.info('breaking')
215 break
216 return ret
217
218 #DELETE and RECREATE
219 LOG.info('delete')
220 for partition_name, partition in partitions.iteritems():
221 LOG.info(partition)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200222 # TODO IF LVM create ERROR
223 ret["changes"] = __salt__['maasng.delete_partition_by_id'](
Denis Egorenkodecf41b2018-11-07 13:04:18 +0400224 hostname, name, partition["id"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100225
226 LOG.info('recreating')
227 for part_name, part in partition_schema.iteritems():
228 LOG.info("partitition for creation")
229 LOG.info(part)
230 if "mount" not in part:
231 part["mount"] = None
Serhii Lystopad6f2fca92020-05-17 19:32:01 +0300232 if "mount_options" not in part:
233 part["mount_options"] = None
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100234 if "type" not in part:
235 part["type"] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200236 ret["changes"] = __salt__['maasng.create_partition'](
Serhii Lystopad6f2fca92020-05-17 19:32:01 +0300237 hostname, name, part["size"], part["type"], part["mount"],
238 part["mount_options"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100239
240 if "error" in ret["changes"]:
241 ret["result"] = False
242
243 return ret
244
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200245
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100246def volume_group_present(hostname, name, devices=[], partitions=[]):
247 '''
248 Ensure that the disk layout does exist
249
250 :param name: The name of the cloud that should not exist
251 '''
252 ret = {'name': hostname,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200253 'changes': {},
254 'result': True,
255 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100256
257 machine = __salt__['maasng.get_machine'](hostname)
258 if "error" in machine:
Alexei Lugovoie5b64122018-11-06 12:30:01 +0100259 if 0 in machine["error"]:
260 ret['comment'] = "No such machine {0}".format(hostname)
261 ret['changes'] = machine
262 else:
263 ret['comment'] = "State execution" \
264 "failed for machine {0}".format(hostname)
265 ret['result'] = False
266 ret['changes'] = machine
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100267 return ret
268
269 if machine["status_name"] != "Ready":
270 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
271 return ret
272
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200273 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100274 vgs = __salt__['maasng.list_volume_groups'](hostname)
275
276 if name in vgs:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200277 # TODO validation for devices and partitions
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100278 return ret
279
280 if __opts__['test']:
281 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200282 ret['comment'] = 'LVM group {0} will be updated on {1}'.format(
283 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100284 return ret
285
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200286 ret["changes"] = __salt__['maasng.create_volume_group'](
287 hostname, name, devices, partitions)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100288
289 if "error" in ret["changes"]:
290 ret["result"] = False
291
292 return ret
293
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200294
azvyagintsevf3515c82018-06-26 18:59:05 +0300295def volume_present(hostname, name, volume_group_name, size, type=None,
Serhii Lystopad6f2fca92020-05-17 19:32:01 +0300296 mount=None, mount_options=None):
azvyagintsevf3515c82018-06-26 18:59:05 +0300297 """
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100298 Ensure that the disk layout does exist
299
300 :param name: The name of the cloud that should not exist
azvyagintsevf3515c82018-06-26 18:59:05 +0300301 """
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100302
303 ret = {'name': hostname,
304 'changes': {},
305 'result': True,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200306 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100307
308 machine = __salt__['maasng.get_machine'](hostname)
309 if "error" in machine:
Alexei Lugovoie5b64122018-11-06 12:30:01 +0100310 if 0 in machine["error"]:
311 ret['comment'] = "No such machine {0}".format(hostname)
312 ret['changes'] = machine
313 else:
314 ret['comment'] = "State execution failed for machine {0}".format(
315 hostname)
316 ret['result'] = False
317 ret['changes'] = machine
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100318 return ret
319
320 if machine["status_name"] != "Ready":
321 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
322 return ret
323
324 if __opts__['test']:
325 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200326 ret['comment'] = 'LVM volume {0} will be updated on {1}'.format(
327 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100328
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200329 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100330
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200331 ret["changes"] = __salt__['maasng.create_volume'](
Serhii Lystopad6f2fca92020-05-17 19:32:01 +0300332 hostname, name, volume_group_name, size, type, mount, mount_options)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100333
334 return ret
335
336
337def select_boot_disk(hostname, name):
338 '''
339 Select disk that will be used to boot partition
340
341 :param name: The name of disk on machine
342 :param hostname: The hostname of machine
343 '''
344
345 ret = {'name': hostname,
346 'changes': {},
347 'result': True,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200348 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100349
350 machine = __salt__['maasng.get_machine'](hostname)
351 if "error" in machine:
Alexei Lugovoie5b64122018-11-06 12:30:01 +0100352 if 0 in machine["error"]:
353 ret['comment'] = "No such machine {0}".format(hostname)
354 ret['changes'] = machine
355 else:
356 ret['comment'] = "State execution" \
357 "failed for machine {0}".format(hostname)
358 ret['result'] = False
359 ret['changes'] = machine
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100360 return ret
361
362 if machine["status_name"] != "Ready":
363 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
364 return ret
365
366 if __opts__['test']:
367 ret['result'] = None
azvyagintsevf3515c82018-06-26 18:59:05 +0300368 ret['comment'] = 'LVM volume {0}' \
369 'will be updated on {1}'.format(name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100370
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200371 # TODO disk validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100372
373 ret["changes"] = __salt__['maasng.set_boot_disk'](hostname, name)
374
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200375 return ret
376
377
Ivan Berezovskiy499b2502019-10-07 16:31:32 +0400378def vlan_present_in_fabric(name, fabric, vlan, primary_rack, description='', dhcp_on=False, mtu=1500, relay_vlan=None):
azvyagintsevf3515c82018-06-26 18:59:05 +0300379 """
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200380
381 :param name: Name of vlan
382 :param fabric: Name of fabric
azvyagintsevf3515c82018-06-26 18:59:05 +0300383 :param vlan: Vlan id
Petr Ruzicka80471852018-07-13 14:08:27 +0200384 :param mtu: MTU
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200385 :param description: Description of vlan
386 :param dhcp_on: State of dhcp
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200387 :param primary_rack: primary_rack
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200388
azvyagintsevf3515c82018-06-26 18:59:05 +0300389 """
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200390
391 ret = {'name': fabric,
392 'changes': {},
393 'result': True,
394 'comment': 'Module function maasng.update_vlan executed'}
395
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200396 if __opts__['test']:
397 ret['result'] = None
Pavel Cizinsky8f9ba8e2018-09-10 14:31:49 +0200398 ret['comment'] = 'Vlan {0} will be updated for {1}'.format(
399 vlan, fabric)
azvyagintsevf3515c82018-06-26 18:59:05 +0300400 return ret
401 # Check, that vlan already defined
402 _rez = __salt__['maasng.check_vlan_in_fabric'](fabric=fabric,
403 vlan=vlan)
404 if _rez == 'not_exist':
405 changes = __salt__['maasng.create_vlan_in_fabric'](name=name,
406 fabric=fabric,
407 vlan=vlan,
Petr Ruzicka80471852018-07-13 14:08:27 +0200408 mtu=mtu,
azvyagintsevf3515c82018-06-26 18:59:05 +0300409 description=description,
410 primary_rack=primary_rack,
Ivan Berezovskiy499b2502019-10-07 16:31:32 +0400411 dhcp_on=dhcp_on,
412 relay_vlan=relay_vlan)
Michael Polenchukd25da792018-07-19 18:27:11 +0400413 ret['comment'] = 'Vlan {0} has ' \
azvyagintsevf3515c82018-06-26 18:59:05 +0300414 'been created for {1}'.format(name, fabric)
415 elif _rez == 'update':
416 _id = __salt__['maasng.list_vlans'](fabric)[vlan]['id']
417 changes = __salt__['maasng.create_vlan_in_fabric'](name=name,
418 fabric=fabric,
419 vlan=vlan,
Petr Ruzicka80471852018-07-13 14:08:27 +0200420 mtu=mtu,
azvyagintsevf3515c82018-06-26 18:59:05 +0300421 description=description,
422 primary_rack=primary_rack,
423 dhcp_on=dhcp_on,
424 update=True,
Ivan Berezovskiy499b2502019-10-07 16:31:32 +0400425 vlan_id=_id,
426 relay_vlan=relay_vlan)
Michael Polenchukd25da792018-07-19 18:27:11 +0400427 ret['comment'] = 'Vlan {0} has been ' \
azvyagintsevf3515c82018-06-26 18:59:05 +0300428 'updated for {1}'.format(name, fabric)
429 ret['changes'] = changes
430
431 if "error" in changes:
432 ret['comment'] = "State execution failed for fabric {0}".format(fabric)
433 ret['result'] = False
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200434 return ret
435
436 return ret
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300437
438
azvyagintseve2e37a12018-11-01 14:45:49 +0200439def boot_source_present(url, keyring_file='', keyring_data='',
440 delete_undefined_sources=False,
441 delete_undefined_sources_except_urls=[]):
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300442 """
443 Process maas boot-sources: link to maas-ephemeral repo
444
445
446 :param url: The URL of the BootSource.
447 :param keyring_file: The path to the keyring file for this BootSource.
448 :param keyring_data: The GPG keyring for this BootSource, base64-encoded data.
azvyagintseve2e37a12018-11-01 14:45:49 +0200449 :param delete_undefined_sources: Delete all boot-sources, except defined in reclass
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300450 """
451 ret = {'name': url,
452 'changes': {},
453 'result': True,
454 'comment': 'boot-source {0} presented'.format(url)}
455
456 if __opts__['test']:
457 ret['result'] = None
458 ret['comment'] = 'boot-source {0} will be updated'.format(url)
azvyagintseve2e37a12018-11-01 14:45:49 +0200459 maas_boot_sources = maasng('get_boot_source')
460 # TODO implement check and update for keyrings!
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300461 if url in maas_boot_sources.keys():
462 ret["result"] = True
463 ret["comment"] = 'boot-source {0} alredy exist'.format(url)
azvyagintseve2e37a12018-11-01 14:45:49 +0200464 else:
465 ret["changes"] = maasng('create_boot_source', url,
466 keyring_filename=keyring_file,
467 keyring_data=keyring_data)
468 if delete_undefined_sources:
469 ret["changes"] = merge2dicts(ret.get('changes', {}),
470 maasng('boot_sources_delete_all_others',
471 except_urls=delete_undefined_sources_except_urls))
472 # Re-import data
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300473 return ret
474
475
476def boot_sources_selections_present(bs_url, os, release, arches="*",
477 subarches="*", labels="*", wait=True):
478 """
azvyagintsevcb54d142018-06-19 16:18:32 +0300479 Process maas boot-sources selection: set of resource configurathions,
480 to be downloaded from boot-source bs_url.
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300481
482 :param bs_url: Boot-source url
azvyagintsevcb54d142018-06-19 16:18:32 +0300483 :param os: The OS (e.g. ubuntu, centos) for which to import
484 resources.Required.
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300485 :param release: The release for which to import resources. Required.
486 :param arches: The architecture list for which to import resources.
487 :param subarches: The subarchitecture list for which to import resources.
488 :param labels: The label lists for which to import resources.
489 :param wait: Initiate import and wait for done.
490
491 """
492 ret = {'name': bs_url,
493 'changes': {},
494 'result': True,
495 'comment': 'boot-source {0} selection present'.format(bs_url)}
496
497 if __opts__['test']:
498 ret['result'] = None
azvyagintsevf3515c82018-06-26 18:59:05 +0300499 ret['comment'] = 'boot-source {0}' \
500 'selection will be updated'.format(bs_url)
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300501
azvyagintseve2e37a12018-11-01 14:45:49 +0200502 maas_boot_sources = maasng('get_boot_source')
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300503 if bs_url not in maas_boot_sources.keys():
504 ret["result"] = False
azvyagintsevf3515c82018-06-26 18:59:05 +0300505 ret["comment"] = 'Requested boot-source' \
506 '{0} not exist! Unable' \
507 'to proceed selection for it'.format(bs_url)
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300508 return ret
509
azvyagintseve2e37a12018-11-01 14:45:49 +0200510 ret = maasng('create_boot_source_selections', bs_url, os, release,
511 arches=arches,
512 subarches=subarches,
513 labels=labels,
514 wait=wait)
azvyagintsev3ff2ef12018-06-01 21:30:45 +0300515 return ret
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200516
517
azvyagintsevefb6f5d2018-07-10 14:16:19 +0300518def iprange_present(name, type_range, start_ip, end_ip, subnet=None,
519 comment=None):
520 """
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200521
522 :param name: Name of iprange
523 :param type_range: Type of iprange
524 :param start_ip: Start ip of iprange
525 :param end_ip: End ip of iprange
526 :param comment: Comment for specific iprange
527
azvyagintsevefb6f5d2018-07-10 14:16:19 +0300528 """
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200529
530 ret = {'name': name,
531 'changes': {},
532 'result': True,
533 'comment': 'Module function maasng.iprange_present executed'}
534
azvyagintsevf3515c82018-06-26 18:59:05 +0300535 # Check, that range already defined
536 _rez = __salt__['maasng.get_startip'](start_ip)
537 if 'start_ip' in _rez.keys():
538 if _rez["start_ip"] == start_ip:
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200539 ret['comment'] = 'Iprange {0} already exist.'.format(name)
540 return ret
541
542 if __opts__['test']:
543 ret['result'] = None
azvyagintsevf3515c82018-06-26 18:59:05 +0300544 ret['comment'] = 'Ip range {0} will be ' \
545 'created with start ip: {1} ' \
546 'and end ip: {2} and ' \
547 'type {3}'.format(name, start_ip, end_ip, type_range)
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200548 return ret
549
azvyagintsevf3515c82018-06-26 18:59:05 +0300550 changes = __salt__['maasng.create_iprange'](type_range=type_range,
551 start_ip=start_ip,
Pavel Cizinsky8f9ba8e2018-09-10 14:31:49 +0200552 end_ip=end_ip, subnet=subnet, comment=comment)
azvyagintsevf3515c82018-06-26 18:59:05 +0300553 ret["changes"] = changes
554 if "error" in changes:
555 ret['comment'] = "State execution failed for iprange {0}".format(name)
556 ret['result'] = False
557 return ret
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200558 return ret
559
560
azvyagintsevf3515c82018-06-26 18:59:05 +0300561def subnet_present(cidr, name, fabric, gateway_ip, vlan):
azvyagintsevefb6f5d2018-07-10 14:16:19 +0300562 """
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200563
564 :param cidr: Cidr for subnet
565 :param name: Name of subnet
566 :param fabric: Name of fabric for subnet
567 :param gateway_ip: gateway_ip
568
azvyagintsevefb6f5d2018-07-10 14:16:19 +0300569 """
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200570
571 ret = {'name': name,
572 'changes': {},
573 'result': True,
574 'comment': 'Module function maasng.subnet_present executed'}
575
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200576 if __opts__['test']:
577 ret['result'] = None
578 ret['comment'] = 'Subnet {0} will be created for {1}'.format(
579 name, fabric)
580 return ret
azvyagintsevf3515c82018-06-26 18:59:05 +0300581 # Check, that subnet already defined
582 _rez = __salt__['maasng.check_subnet'](cidr, name, fabric, gateway_ip)
583 if _rez == 'not_exist':
584 changes = __salt__['maasng.create_subnet'](cidr=cidr, name=name,
585 fabric=fabric,
586 gateway_ip=gateway_ip,
587 vlan=vlan)
588 ret['comment'] = 'Subnet {0} ' \
589 'has been created for {1}'.format(name, fabric)
590 elif _rez == 'update':
591 _id = __salt__['maasng.list_subnets'](sort_by='cidr')[cidr]['id']
592 changes = __salt__['maasng.create_subnet'](cidr=cidr, name=name,
593 fabric=fabric,
594 gateway_ip=gateway_ip,
595 vlan=vlan, update=True,
596 subnet_id=_id)
597 ret['comment'] = 'Subnet {0} ' \
598 'has been updated for {1}'.format(name, fabric)
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200599
azvyagintsevf3515c82018-06-26 18:59:05 +0300600 if "error" in changes:
601 ret['comment'] = "State execution failed for subnet {0}".format(name)
602 ret['result'] = False
603 ret['changes'] = changes
604 return ret
605
606 return ret
607
608
azvyagintsevf0904ac2018-07-05 18:53:26 +0300609def fabric_present(name, description=None):
azvyagintsevf3515c82018-06-26 18:59:05 +0300610 """
611
612 :param name: Name of fabric
613 :param description: Name of description
614
615 """
616
617 ret = {'name': name,
618 'changes': {},
619 'result': True,
620 'comment': 'Module function maasng.fabric_present executed'}
621
622 if __opts__['test']:
623 ret['result'] = None
azvyagintseva80fdfb2018-07-16 22:34:45 +0300624 ret['comment'] = 'fabric {0} will be updated'.format(name)
azvyagintsevf3515c82018-06-26 18:59:05 +0300625 return ret
626 # All requested subnets
627 _r_subnets = __salt__['config.get']('maas').get('region', {}).get('subnets',
628 {})
629 # Assumed subnet CIDrs, expected to be in requested fabric
azvyagintsevefb6f5d2018-07-10 14:16:19 +0300630 _a_subnets = [_r_subnets[f]['cidr'] for f in _r_subnets.keys() if
azvyagintsevf3515c82018-06-26 18:59:05 +0300631 _r_subnets[f]['fabric'] == name]
632 _rez = __salt__['maasng.check_fabric_guess_with_cidr'](name=name,
633 cidrs=_a_subnets)
634
635 if 'not_exist' in _rez:
636 changes = __salt__['maasng.create_fabric'](name=name,
637 description=description)
638 ret['new'] = 'Fabric {0} has been created'.format(name)
639 elif 'update' in _rez:
640 f_id = _rez['update']
641 changes = __salt__['maasng.create_fabric'](name=name,
642 description=description,
643 update=True, fabric_id=f_id)
644 ret['new'] = 'Fabric {0} has been updated'.format(name)
645 ret['changes'] = changes
646
647 if "error" in changes:
648 ret['comment'] = "State execution failed for fabric {0}".format(fabric)
649 ret['result'] = False
650 return ret
Pavel Cizinsky8dd85b52018-06-18 21:40:13 +0200651
652 return ret
Pavel Cizinsky8f9ba8e2018-09-10 14:31:49 +0200653
654
655def sshkey_present(name, sshkey):
656 """
657
658 :param name: Name of user
659 :param sshkey: SSH key for MAAS user
660
661 """
662
663 ret = {'name': name,
664 'changes': {},
665 'result': True,
666 'comment': 'Module function maasng.ssshkey_present executed'}
667
668 # Check, that subnet already defined
669 _rez = __salt__['maasng.get_sshkey'](sshkey)
670 if 'key' in _rez.keys():
671 if _rez["key"] == sshkey:
672 ret['comment'] = 'SSH key {0} already exist for user {1}.'.format(
673 sshkey, name)
674 return ret
675
676 if __opts__['test']:
677 ret['result'] = None
678 ret['comment'] = 'SSH key {0} will be add it to MAAS for user {1}'.format(
679 sshkey, name)
680
681 return ret
682
683 changes = __salt__['maasng.add_sshkey'](sshkey=sshkey)
684 ret['comment'] = 'SSH-key {0} ' \
685 'has been added for user {1}'.format(sshkey, name)
686
687 ret['changes'] = changes
688
689 if "error" in changes:
690 ret['comment'] = "State execution failed for sshkey: {0}".format(
691 sshkey)
692 ret['result'] = False
693 ret['changes'] = changes
694 return ret
695
696 return ret