blob: 65ffc84bebc76dd587eac88a6e8f7387645b1d4f [file] [log] [blame]
Ondrej Smolab57a23b2018-01-24 11:18:24 +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
16import collections
17import copy
18import hashlib
19import io
20import json
21import logging
22import os.path
23import time
24import urllib2
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020025# Salt utils
Ondrej Smolab57a23b2018-01-24 11:18:24 +010026from salt.exceptions import CommandExecutionError, SaltInvocationError
27
28LOG = logging.getLogger(__name__)
29
30SIZE = {
31 "M": 1000000,
32 "G": 1000000000,
33 "T": 1000000000000,
34}
35
36RAID = {
37 0: "raid-0",
38 1: "raid-1",
39 5: "raid-5",
40 10: "raid-10",
41}
42
43# Import third party libs
44HAS_MASS = False
45try:
46 from maas_client import MAASClient, MAASDispatcher, MAASOAuth
47 HAS_MASS = True
48except ImportError:
49 LOG.debug('Missing MaaS client module is Missing. Skipping')
50
51
52def __virtual__():
53 '''
54 Only load this module if maas-client
55 is installed on this minion.
56 '''
57 if HAS_MASS:
58 return 'maasng'
59 return False
60
61
62APIKEY_FILE = '/var/lib/maas/.maas_credentials'
63
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020064
Ondrej Smolab57a23b2018-01-24 11:18:24 +010065def _format_data(data):
66 class Lazy:
67 def __str__(self):
68 return ' '.join(['{0}={1}'.format(k, v)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020069 for k, v in data.iteritems()])
Ondrej Smolab57a23b2018-01-24 11:18:24 +010070 return Lazy()
71
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020072
Ondrej Smolab57a23b2018-01-24 11:18:24 +010073def _create_maas_client():
74 global APIKEY_FILE
75 try:
76 api_token = file(APIKEY_FILE).read().splitlines()[-1].strip()\
77 .split(':')
78 except:
79 LOG.exception('token')
80 auth = MAASOAuth(*api_token)
81 api_url = 'http://localhost:5240/MAAS'
82 dispatcher = MAASDispatcher()
83 return MAASClient(auth, dispatcher, api_url)
84
Ondrej Smolab57a23b2018-01-24 11:18:24 +010085
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020086def _get_blockdevice_id_by_name(hostname, device):
87
88 # TODO validation
Ondrej Smolab57a23b2018-01-24 11:18:24 +010089 return list_blockdevices(hostname)[device]["id"]
90
Ondrej Smolab57a23b2018-01-24 11:18:24 +010091
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020092def _get_volume_group_id_by_name(hostname, device):
93
94 # TODO validation
Ondrej Smolab57a23b2018-01-24 11:18:24 +010095 return list_volume_groups(hostname)[device]["id"]
96
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020097
Ondrej Smolab57a23b2018-01-24 11:18:24 +010098def _get_partition_id_by_name(hostname, device, partition):
99
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200100 # TODO validation
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100101 return list_partitions(hostname, device)[partition]["id"]
102
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200103# MACHINE SECTION
104
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100105
106def get_machine(hostname):
107 '''
108 Get information aboout specified machine
109
110 CLI Example:
111
112 .. code-block:: bash
113
114 salt-call maasng.get_machine server_hostname
115 '''
116 try:
117 return list_machines()[hostname]
118 except KeyError:
119 return {"error": "Machine not found on MaaS server"}
120
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200121
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100122def list_machines():
123 '''
124 Get list of all machines from maas server
125
126 CLI Example:
127
128 .. code-block:: bash
129
130 salt 'maas-node' maasng.list_machines
131 '''
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200132 machines = {}
133 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100134 json_res = json.loads(maas.get(u'api/2.0/machines/').read())
135 for item in json_res:
136 machines[item["hostname"]] = item
137 return machines
138
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200139
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100140def create_machine():
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200141 # TODO
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100142
143 return False
144
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200145
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100146def update_machine():
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200147 # TODO
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100148
149 return False
150
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200151# MACHINE OPERATIONS
152# TODO
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100153
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200154# RAID SECTION
155
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100156
157def create_raid(hostname, name, level, disks=[], partitions=[], **kwargs):
158 '''
159 Create new raid on machine.
160
161 CLI Example:
162
163 .. code-block:: bash
164
165 salt-call maasng.create_raid hostname=kvm03 name=md0 level=1 disks=[vdb,vdc] partitions=[vdd-part1,vde-part1]
166 '''
167
168 result = {}
169
170 if len(disks) == 0 and len(partitions) == 0:
171 result["error"] = "Disks or partitions need to be provided"
172
173 disk_ids = []
174 partition_ids = []
175
176 for disk in disks:
177 try:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200178 disk_ids.append(str(_get_blockdevice_id_by_name(hostname, disk)))
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100179 except KeyError:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200180 result["error"] = "Device {0} does not exists on machine {1}".format(
181 disk, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100182 return result
183
184 for partition in partitions:
185 try:
186 device = partition.split("-")[0]
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200187 device_part = list_partitions(hostname, device)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100188 partition_ids.append(str(device_part[partition]["id"]))
189 except KeyError:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200190 result["error"] = "Partition {0} does not exists on machine {1}".format(
191 partition, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100192 return result
193
194 data = {
195 "name": name,
196 "level": RAID[int(level)],
197 "block_devices": disk_ids,
198 "partitions": partition_ids,
199 }
200
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200201 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100202 system_id = get_machine(hostname)["system_id"]
203 LOG.info(system_id)
204
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200205 # TODO validation
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100206 LOG.info(data)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200207 json_res = json.loads(
208 maas.post(u"api/2.0/nodes/{0}/raids/".format(system_id), None, **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100209 LOG.info(json_res)
210 result["new"] = "Raid {0} created".format(name)
211
212 return result
213
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200214
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100215def list_raids(hostname):
216 '''
217 Get list all raids on machine
218
219 CLI Example:
220
221 .. code-block:: bash
222
223 salt-call maasng.list_raids server_hostname
224 '''
225
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200226 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100227 system_id = get_machine(hostname)["system_id"]
228 LOG.info(system_id)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200229 # TODO validation
230 json_res = json.loads(
231 maas.get(u"api/2.0/nodes/{0}/raids/".format(system_id)).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100232 LOG.info(json_res)
233
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200234 # TODO return list of raid devices
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100235 return True
236
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200237
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100238def get_raid(hostname, name):
239 '''
240 Get information about specific raid on machine
241
242 CLI Example:
243
244 .. code-block:: bash
245
246 salt-call maasng.get_raids server_hostname md0
247 '''
248
249 return list_raids(hostname)[name]
250
251
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200252# BLOCKDEVICES SECTION
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100253
254def list_blockdevices(hostname):
255 '''
256 Get list of all blockdevices (disks) on machine
257
258 CLI Example:
259
260 .. code-block:: bash
261
262 salt 'maas-node' maasng.list_blockdevices server_hostname
263 salt-call maasng.list_blockdevices server_hostname
264 '''
265 ret = {}
266
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200267 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100268 system_id = get_machine(hostname)["system_id"]
269 LOG.info(system_id)
270
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200271 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100272
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200273 json_res = json.loads(
274 maas.get(u"api/2.0/nodes/{0}/blockdevices/".format(system_id)).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100275 LOG.info(json_res)
276 for item in json_res:
277 ret[item["name"]] = item
278
279 return ret
280
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200281
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100282def get_blockdevice(hostname, name):
283 '''
284 Get information about blockdevice (disk) on machine
285
286 CLI Example:
287
288 .. code-block:: bash
289
290 salt 'maas-node' maasng.get_blockdevice server_hostname sda
291 salt-call maasng.get_blockdevice server_hostname sda
292 '''
293
294 return list_blockdevices(hostname)[name]
295
296
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200297# PARTITIONS
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100298
299def list_partitions(hostname, device):
300 '''
301 Get list of all partitions on specific device located on specific machine
302
303 CLI Example:
304
305 .. code-block:: bash
306
307 salt 'maas-node' maasng.list_partitions server_hostname sda
308 salt-call maasng.list_partitions server_hostname sda
309 '''
310 ret = {}
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200311 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100312 system_id = get_machine(hostname)["system_id"]
313 LOG.info(system_id)
314
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200315 partitions = get_blockdevice(hostname, device)["partitions"]
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100316 LOG.info(partitions)
317
318 #json_res = json.loads(maas.get(u"api/2.0/nodes/{0}/blockdevices/{1}/partitions/".format(system_id, device_id)).read())
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200319 # LOG.info(json_res)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100320
321 if len(device) > 0:
322 for item in partitions:
323 name = item["path"].split('/')[-1]
324 ret[name] = item
325
326 return ret
327
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200328
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100329def get_partition(hostname, device, partition):
330 '''
331 Get information about specific parition on device located on machine
332
333 CLI Example:
334
335 .. code-block:: bash
336
337 salt 'maas-node' maasng.get_partition server_hostname disk_name partition
338 salt-call maasng.get_partition server_hostname disk_name partition
339
340 root_size = size in GB
341 '''
342
343 return list_partitions(partition)[name]
344
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200345
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100346def create_partition(hostname, disk, size, fs_type=None, mount=None):
347 '''
348 Create new partition on device.
349
350 CLI Example:
351
352 .. code-block:: bash
353
354 salt 'maas-node' maasng.create_partition server_hostname disk_name 10 ext4 "/"
355 salt-call maasng.create_partition server_hostname disk_name 10 ext4 "/"
356 '''
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200357 # TODO validation
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100358 result = {}
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200359 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100360 system_id = get_machine(hostname)["system_id"]
361 LOG.info(system_id)
362
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200363 device_id = _get_blockdevice_id_by_name(hostname, disk)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100364 LOG.info(device_id)
365
366 value, unit = size[:-1], size[-1]
367 calc_size = str(int(value) * SIZE[unit])
368 LOG.info(calc_size)
369
370 data = {
371 "size": calc_size
372 }
373
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200374 # TODO validation
375 partition = json.loads(maas.post(
376 u"api/2.0/nodes/{0}/blockdevices/{1}/partitions/".format(system_id, device_id), None, **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100377 LOG.info(partition)
378 result["partition"] = "Partition created on {0}".format(disk)
379
380 if fs_type != None:
381 data_fs_type = {
382 "fstype": fs_type
383 }
384 partition_id = str(partition["id"])
385 LOG.info("Partition id: " + partition_id)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200386 # TODO validation
387 json_res = json.loads(maas.post(u"api/2.0/nodes/{0}/blockdevices/{1}/partition/{2}".format(
388 system_id, device_id, partition_id), "format", **data_fs_type).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100389 LOG.info(json_res)
390 result["filesystem"] = "Filesystem {0} created".format(fs_type)
391
392 if mount != None:
393 data = {
394 "mount_point": mount
395 }
396
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200397 # TODO validation
398 json_res = json.loads(maas.post(u"api/2.0/nodes/{0}/blockdevices/{1}/partition/{2}".format(
399 system_id, device_id, str(partition['id'])), "mount", **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100400 LOG.info(json_res)
401 result["mount"] = "Mount point {0} created".format(mount)
402
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100403 return result
404
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200405
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100406def delete_partition(hostname, disk, partition_name):
407 '''
408 Delete partition on device.
409
410 CLI Example:
411
412 .. code-block:: bash
413
414 salt 'maas-node' maasng.delete_partition server_hostname disk_name partition_name
415 salt-call maasng.delete_partition server_hostname disk_name partition_name
416
417 root_size = size in GB
418 '''
419 result = {}
420 data = {}
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200421 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100422 system_id = get_machine(hostname)["system_id"]
423 LOG.info(system_id)
424
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200425 device_id = _get_blockdevice_id_by_name(hostname, disk)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100426 LOG.info(device_id)
427
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200428 partition_id = _get_partition_id_by_name(hostname, disk, partition_name)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100429
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200430 maas.delete(u"api/2.0/nodes/{0}/blockdevices/{1}/partition/{2}".format(
431 system_id, device_id, partition_id)).read()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100432 result["new"] = "Partition {0} deleted".format(partition_name)
433 return result
434
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200435
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100436def delete_partition_by_id(hostname, disk, partition_id):
437 '''
438 Delete partition on device. Partition spefified by id of parition
439
440 CLI Example:
441
442 .. code-block:: bash
443
444 salt 'maas-node' maasng.delete_partition_by_id server_hostname disk_name partition_id
445 salt-call maasng.delete_partition_by_id server_hostname disk_name partition_id
446
447 root_size = size in GB
448 '''
449 result = {}
450 data = {}
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200451 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100452 system_id = get_machine(hostname)["system_id"]
453 LOG.info(system_id)
454
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200455 device_id = _get_blockdevice_id_by_name(hostname, disk)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100456 LOG.info(device_id)
457
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200458 maas.delete(u"api/2.0/nodes/{0}/blockdevices/{1}/partition/{2}".format(
459 system_id, device_id, partition_id)).read()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100460 result["new"] = "Partition {0} deleted".format(partition_id)
461 return result
462
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200463# CREATE DISK LAYOUT
464# TODO
465
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100466
467def update_disk_layout(hostname, layout, root_size=None, root_device=None, volume_group=None, volume_name=None, volume_size=None):
468 '''
469 Update disk layout. Flat or LVM layout supported.
470
471 CLI Example:
472
473 .. code-block:: bash
474
475 salt 'maas-node' maasng.update_disk_layout server_hostname lvm root_size=None, root_device=None, volume_group=None, volume_name=None, volume_size=None
476 salt-call maasng.update_disk_layout server_hostname lvm root_size=None, root_device=None, volume_group=None, volume_name=None, volume_size=None
477
478 root_size = size in GB
479 '''
480 result = {}
481 data = {
482 "storage_layout": layout,
483 }
484
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200485 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100486 system_id = get_machine(hostname)["system_id"]
487 LOG.info(system_id)
488
489 if root_size != None:
490 bit_size = str(root_size * 1073741824)
491 LOG.info(bit_size)
492 data["root_size"] = bit_size
493
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100494 if root_device != None:
495 LOG.info(root_device)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200496 data["root_device"] = str(
497 _get_blockdevice_id_by_name(hostname, root_device))
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100498
499 if layout == 'lvm':
500 if volume_group != None:
501 LOG.info(volume_group)
502 data["vg_name"] = volume_group
503 if volume_name != None:
504 LOG.info(volume_name)
505 data["lv_name"] = volume_name
506 if volume_size != None:
507 vol_size = str(volume_size * 1073741824)
508 LOG.info(vol_size)
509 data["lv_size"] = vol_size
510
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200511 # TODO validation
512 json_res = json.loads(maas.post(
513 u"api/2.0/machines/{0}/".format(system_id), "set_storage_layout", **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100514 LOG.info(json_res)
515 result["new"] = {
516 "storage_layout": layout,
517 }
518
519 return result
520
521
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200522# LVM
523# TODO
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100524
525def list_volume_groups(hostname):
526 '''
527 Get list of all volume group on machine.
528
529 CLI Example:
530
531 .. code-block:: bash
532
533 salt 'maas-node' maasng.list_volume_groups server_hostname
534 salt-call maasng.list_volume_groups server_hostname
535 '''
536 volume_groups = {}
537
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200538 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100539 system_id = get_machine(hostname)["system_id"]
540 LOG.info(system_id)
541
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200542 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100543
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200544 json_res = json.loads(
545 maas.get(u"api/2.0/nodes/{0}/volume-groups/".format(system_id)).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100546 LOG.info(json_res)
547 for item in json_res:
548 volume_groups[item["name"]] = item
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200549 # return
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100550 return volume_groups
551
552
553def get_volume_group(hostname, name):
554 '''
555 Get information about specific volume group on machine.
556
557 CLI Example:
558
559 .. code-block:: bash
560
561 salt 'maas-node' maasng.list_blockdevices server_hostname
562 salt-call maasng.list_blockdevices server_hostname
563 '''
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200564 # TODO validation that exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100565 return list_volume_groups(hostname)[name]
566
567
568def create_volume_group(hostname, volume_group_name, disks=[], partitions=[]):
569 '''
570 Create new volume group on machine. Disks or partitions needs to be provided.
571
572 CLI Example:
573
574 .. code-block:: bash
575
576 salt 'maas-node' maasng.create_volume_group volume_group_name, disks=[sda,sdb], partitions=[]
577 salt-call maasng.create_volume_group server_hostname
578 '''
579 result = {}
580
581 data = {
582 "name": volume_group_name,
583 }
584
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200585 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100586 system_id = get_machine(hostname)["system_id"]
587 LOG.info(system_id)
588
589 disk_ids = []
590 partition_ids = []
591
592 for disk in disks:
593 p_disk = get_blockdevice(hostname, disk)
594 if p_disk["partition_table_type"] == None:
595 disk_ids.append(str(p_disk["id"]))
596 else:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200597 result["error"] = "Device {0} on machine {1} cointains partition table".format(
598 disk, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100599 return result
600
601 for partition in partitions:
602 try:
603 device = partition.split("-")[0]
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200604 device_part = list_partitions(hostname, device)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100605 partition_ids.append(str(device_part[partition]["id"]))
606 except KeyError:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200607 result["error"] = "Partition {0} does not exists on machine {1}".format(
608 partition, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100609 return result
610
611 data["block_devices"] = disk_ids
612 data["partitions"] = partition_ids
613 LOG.info(partition_ids)
614 LOG.info(partitions)
615
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200616 # TODO validation
617 json_res = json.loads(maas.post(
618 u"api/2.0/nodes/{0}/volume-groups/".format(system_id), None, **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100619 LOG.info(json_res)
620 result["new"] = "Volume group {0} created".format(json_res["name"])
621
622 return result
623
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200624
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100625def delete_volume_group(hostname, name):
626 '''
627 Delete volume group on machine.
628
629 CLI Example:
630
631 .. code-block:: bash
632
633 salt 'maas-node' maasng.delete_volume_group server_hostname vg0
634 salt-call maasng.delete_volume_group server_hostname vg0
635 '''
636
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200637 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100638 system_id = get_machine(hostname)["system_id"]
639 LOG.info(system_id)
640
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200641 # TODO partitions
642 # for partition in partitions:
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100643 # temp = disk.split("-")
644 # disk_ids.append(str(_get_blockdevice_id_by_name(hostname, temp[] partition)))
645
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200646 # TODO partitions
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100647 vg_id = name
648
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200649 # TODO validation
650 json_res = json.loads(maas.delete(
651 u"api/2.0/nodes/{0}/volume-group/{1}/".format(system_id, vg_id)).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100652 LOG.info(json_res)
653
654 return True
655
656
657def create_volume(hostname, volume_name, volume_group, size, fs_type=None, mount=None):
658 '''
659 Create volume on volume group.
660
661 CLI Example:
662
663 .. code-block:: bash
664
665 salt 'maas-node' maasng.create_volume server_hostname volume_name, volume_group, size, fs_type=None, mount=None
666 salt-call maasng.create_volume server_hostname volume_name, volume_group, size, fs_type=None, mount=None
667 '''
668
669 data = {
670 "name": volume_name,
671 }
672
673 value, unit = size[:-1], size[-1]
674 bit_size = str(int(value) * SIZE[unit])
675 LOG.info(bit_size)
676
677 data["size"] = bit_size
678
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200679 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100680 system_id = get_machine(hostname)["system_id"]
681 LOG.info(system_id)
682
683 volume_group_id = str(_get_volume_group_id_by_name(hostname, volume_group))
684
685 LOG.info(volume_group_id)
686
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200687 # TODO validation
688 json_res = json.loads(maas.post(u"api/2.0/nodes/{0}/volume-group/{1}/".format(
689 system_id, volume_group_id), "create_logical_volume", **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100690 LOG.info(json_res)
691
692 if fs_type != None or mount != None:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200693 ret = create_volume_filesystem(
694 hostname, volume_group + "-" + volume_name, fs_type, mount)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100695
696 return True
697
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100698
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200699def create_volume_filesystem(hostname, device, fs_type=None, mount=None):
700
701 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100702 system_id = get_machine(hostname)["system_id"]
703
704 blockdevices_id = _get_blockdevice_id_by_name(hostname, device)
705 data = {}
706 if fs_type != None:
707 data["fstype"] = fs_type
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200708 # TODO validation
709 json_res = json.loads(maas.post(u"/api/2.0/nodes/{0}/blockdevices/{1}/".format(
710 system_id, blockdevices_id), "format", **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100711 LOG.info(json_res)
712
713 if mount != None:
714 data["mount_point"] = mount
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200715 # TODO validation
716 json_res = json.loads(maas.post(u"/api/2.0/nodes/{0}/blockdevices/{1}/".format(
717 system_id, blockdevices_id), "mount", **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100718 LOG.info(json_res)
719
720 return True
721
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100722
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200723def create_partition_filesystem(hostname, partition, fs_type=None, mount=None):
724
725 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100726 system_id = get_machine(hostname)["system_id"]
727
728 blockdevices_id = _get_blockdevice_id_by_name(hostname, device)
729 data = {}
730 if fs_type != None:
731 data["fstype"] = fs_type
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200732 # TODO validation
733 json_res = json.loads(maas.post(u"/api/2.0/nodes/{0}/blockdevices/{1}/".format(
734 system_id, blockdevices_id), "format", **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100735 LOG.info(json_res)
736
737 if mount != None:
738 data["mount_point"] = mount
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200739 # TODO validation
740 json_res = json.loads(maas.post(u"/api/2.0/nodes/{0}/blockdevices/{1}/".format(
741 system_id, blockdevices_id), "mount", **data).read())
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100742 LOG.info(json_res)
743
744 return True
745
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200746
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100747def set_boot_disk(hostname, name):
748 '''
749 Create volume on volume group.
750
751 CLI Example:
752
753 .. code-block:: bash
754
755 salt 'maas-node' maasng.set_boot_disk server_hostname disk_name
756 salt-call maasng.set_boot_disk server_hostname disk_name
757 '''
758 data = {}
759 result = {}
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200760 maas = _create_maas_client()
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100761 system_id = get_machine(hostname)["system_id"]
762 blockdevices_id = _get_blockdevice_id_by_name(hostname, name)
763
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200764 maas.post(u"/api/2.0/nodes/{0}/blockdevices/{1}/".format(
765 system_id, blockdevices_id), "set_boot_disk", **data).read()
766 # TODO validation for error response (disk does not exists and node does not exists)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100767 result["new"] = "Disk {0} was set as bootable".format(name)
768
769 return result
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200770
771
772def list_fabric():
773 '''
774 Get list of all fabric
775
776 CLI Example:
777
778 .. code-block:: bash
779
780 salt 'maas-node' maasng.list_fabric
781 '''
782 fabrics = {}
783 maas = _create_maas_client()
784 json_res = json.loads(maas.get(u'api/2.0/fabrics/').read())
785 LOG.info(json_res)
786 for item in json_res:
787 fabrics[item["name"]] = item
788 return fabrics
789
790
791def create_fabric(name):
792 '''
793 Create new fabric.
794
795 CLI Example:
796
797 .. code-block:: bash
798
799 salt 'maas-node' maasng.create_fabric
800 '''
801 result = {}
802 data = {
803 "name": name,
804 "description": '',
805 "class_type": '',
806
807 }
808
809 maas = _create_maas_client()
810 json_res = json.loads(maas.post(u"api/2.0/fabrics/", None, **data).read())
811 LOG.info(json_res)
812 result["new"] = "Fabrics {0} created".format(json_res["name"])
813 return result
814
815
816def list_subnet():
817 '''
818 Get list of all subnets
819
820 CLI Example:
821
822 .. code-block:: bash
823
824 salt 'maas-node' maasng.list_subnet
825 '''
826 subnets = {}
827 maas = _create_maas_client()
828 json_res = json.loads(maas.get(u'api/2.0/subnets/').read())
829 LOG.info(json_res)
830 for item in json_res:
831 subnets[item["name"]] = item
832 return subnets
833
834
835def list_vlans(fabric):
836 '''
837 Get list of all vlans for specific fabric
838
839 CLI Example:
840
841 .. code-block:: bash
842
843 salt 'maas-node' maasng.list_vlans
844 '''
845 vlans = {}
846 maas = _create_maas_client()
847 fabric_id = get_fabric(fabric)
848
849 json_res = json.loads(
850 maas.get(u'api/2.0/fabrics/{0}/vlans/'.format(fabric_id)).read())
851 LOG.info(json_res)
852 for item in json_res:
853 vlans[item["name"]] = item
854 return vlans
855
856
857def get_fabric(fabric):
858 '''
859 Get id for specific fabric
860
861 CLI Example:
862
863 .. code-block:: bash
864
865 salt-call maasng.get_fabric fabric_name
866 '''
867 try:
868 return list_fabric()[fabric]['id']
869 except KeyError:
870 return {"error": "Frabic not found on MaaS server"}
871
872
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200873def update_vlan(name, fabric, vid, description, primary_rack, dhcp_on=False):
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200874 '''
875 Update vlan
876
877 CLI Example:
878
879 .. code-block:: bash
880
881 salt 'maas-node' maasng.update_vlan name, fabric, vid, description, dhcp_on
882 '''
883 result = {}
884
885 data = {
886 "name": name,
887 "dhcp_on": str(dhcp_on),
888 "description": description,
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200889 "primary_rack": primary_rack,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200890 }
891 maas = _create_maas_client()
892 fabric_id = get_fabric(fabric)
893
894 json_res = json.loads(maas.put(
895 u'api/2.0/fabrics/{0}/vlans/{1}/'.format(fabric_id, vid), **data).read())
896 print(json_res)
897 result["new"] = "Vlan {0} was updated".format(json_res["name"])
898
899 return result