blob: 3d2331154a99aefca54286e117c2fb569ae783b1 [file] [log] [blame]
Ondrej Smolab57a23b2018-01-24 11:18:24 +01001
2import logging
3from salt.exceptions import CommandExecutionError, SaltInvocationError
4
5LOG = logging.getLogger(__name__)
6
7SIZE = {
8 "M": 1000000,
9 "G": 1000000000,
10 "T": 1000000000000,
11}
12
13RAID = {
14 0: "raid-0",
15 1: "raid-1",
16 5: "raid-5",
17 10: "raid-10",
18}
19
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020020
Ondrej Smolab57a23b2018-01-24 11:18:24 +010021def __virtual__():
22 '''
23 Load MaaSng module
24 '''
25 return 'maasng'
26
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020027
28def disk_layout_present(hostname, layout_type, root_size=None, root_device=None, volume_group=None, volume_name=None, volume_size=None, disk={}, **kwargs):
Ondrej Smolab57a23b2018-01-24 11:18:24 +010029 '''
30 Ensure that the disk layout does exist
31
32 :param name: The name of the cloud that should not exist
33 '''
34 ret = {'name': hostname,
35 'changes': {},
36 'result': True,
37 'comment': 'Disk layout "{0}" updated'.format(hostname)}
38
39 machine = __salt__['maasng.get_machine'](hostname)
40 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020041 ret['comment'] = "State execution failed for machine {0}".format(
42 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010043 ret['result'] = False
44 ret['changes'] = machine
45 return ret
46
47 if machine["status_name"] != "Ready":
48 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
49 return ret
50
51 if __opts__['test']:
52 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020053 ret['comment'] = 'Disk layout will be updated on {0}, this action will delete current layout.'.format(
54 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010055 return ret
56
57 if layout_type == "flat":
58
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020059 ret["changes"] = __salt__['maasng.update_disk_layout'](
60 hostname, layout_type, root_size, root_device)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010061
62 elif layout_type == "lvm":
63
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020064 ret["changes"] = __salt__['maasng.update_disk_layout'](
65 hostname, layout_type, root_size, root_device, volume_group, volume_name, volume_size)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010066
azvyagintsevbca1f462018-05-25 19:06:46 +030067 elif layout_type == "custom":
68 ret["changes"] = __salt__['maasng.update_disk_layout'](hostname, layout_type)
69
Ondrej Smolab57a23b2018-01-24 11:18:24 +010070 else:
71 ret["comment"] = "Not supported layout provided. Choose flat or lvm"
72 ret['result'] = False
73
74 return ret
75
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020076
Ondrej Smolab57a23b2018-01-24 11:18:24 +010077def raid_present(hostname, name, level, devices=[], partitions=[], partition_schema={}):
78 '''
79 Ensure that the raid does exist
80
81 :param name: The name of the cloud that should not exist
82 '''
83
84 ret = {'name': name,
85 'changes': {},
86 'result': True,
87 'comment': 'Raid {0} presented on {1}'.format(name, hostname)}
88
89 machine = __salt__['maasng.get_machine'](hostname)
90 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020091 ret['comment'] = "State execution failed for machine {0}".format(
92 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010093 ret['result'] = False
94 ret['changes'] = machine
95 return ret
96
97 if machine["status_name"] != "Ready":
98 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
99 return ret
100
101 if __opts__['test']:
102 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200103 ret['comment'] = 'Raid {0} will be updated on {1}'.format(
104 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100105 return ret
106
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200107 # Validate that raid exists
108 # With correct devices/partition
109 # OR
110 # Create raid
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100111
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200112 ret["changes"] = __salt__['maasng.create_raid'](
113 hostname=hostname, name=name, level=level, disks=devices, partitions=partitions)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100114
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200115 # TODO partitions
116 ret["changes"].update(disk_partition_present(
117 hostname, name, partition_schema)["changes"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100118
119 if "error" in ret["changes"]:
120 ret["result"] = False
121
122 return ret
123
124
125def disk_partition_present(hostname, disk, partition_schema={}):
126 '''
127 Ensure that the disk has correct partititioning schema
128
129 :param name: The name of the cloud that should not exist
130 '''
131
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200132 # 1. Validate that disk has correct values for size and mount
133 # a. validate count of partitions
134 # b. validate size of partitions
135 # 2. If not delete all partitions on disk and recreate schema
136 # 3. Validate type exists
137 # if should not exits
138 # delete mount and unformat
139 # 4. Validate mount exists
140 # 5. if not enforce umount or mount
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100141
142 ret = {'name': hostname,
143 'changes': {},
144 'result': True,
145 'comment': 'Disk layout {0} presented'.format(disk)}
146
147 machine = __salt__['maasng.get_machine'](hostname)
148 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200149 ret['comment'] = "State execution failed for machine {0}".format(
150 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100151 ret['result'] = False
152 ret['changes'] = machine
153 return ret
154
155 if machine["status_name"] != "Ready":
156 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
157 return ret
158
159 if __opts__['test']:
160 ret['result'] = None
161 ret['comment'] = 'Partition schema will be changed on {0}'.format(disk)
162 return ret
163
164 partitions = __salt__['maasng.list_partitions'](hostname, disk)
165
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200166 # Calculate actual size in bytes from provided data
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100167 for part_name, part in partition_schema.iteritems():
168 size, unit = part["size"][:-1], part["size"][-1]
169 part["calc_size"] = int(size) * SIZE[unit]
170
171 if len(partitions) == len(partition_schema):
172
173 for part_name, part in partition_schema.iteritems():
174 LOG.info('validated {0}'.format(part["calc_size"]))
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200175 LOG.info('validated {0}'.format(
176 int(partitions[disk+"-"+part_name.split("-")[-1]]["size"])))
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100177 if part["calc_size"] == int(partitions[disk+"-"+part_name.split("-")[-1]]["size"]):
178 LOG.info('validated')
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200179 # TODO validate size (size from maas is not same as calculate?)
180 # TODO validate mount
181 # TODO validate fs type
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100182 else:
183 LOG.info('breaking')
184 break
185 return ret
186
187 #DELETE and RECREATE
188 LOG.info('delete')
189 for partition_name, partition in partitions.iteritems():
190 LOG.info(partition)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200191 # TODO IF LVM create ERROR
192 ret["changes"] = __salt__['maasng.delete_partition_by_id'](
193 hostname, disk, partition["id"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100194
195 LOG.info('recreating')
196 for part_name, part in partition_schema.iteritems():
197 LOG.info("partitition for creation")
198 LOG.info(part)
199 if "mount" not in part:
200 part["mount"] = None
201 if "type" not in part:
202 part["type"] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200203 ret["changes"] = __salt__['maasng.create_partition'](
204 hostname, disk, part["size"], part["type"], part["mount"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100205
206 if "error" in ret["changes"]:
207 ret["result"] = False
208
209 return ret
210
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200211
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100212def volume_group_present(hostname, name, devices=[], partitions=[]):
213 '''
214 Ensure that the disk layout does exist
215
216 :param name: The name of the cloud that should not exist
217 '''
218 ret = {'name': hostname,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200219 'changes': {},
220 'result': True,
221 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100222
223 machine = __salt__['maasng.get_machine'](hostname)
224 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200225 ret['comment'] = "State execution failed for machine {0}".format(
226 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100227 ret['result'] = False
228 ret['changes'] = machine
229 return ret
230
231 if machine["status_name"] != "Ready":
232 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
233 return ret
234
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200235 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100236 vgs = __salt__['maasng.list_volume_groups'](hostname)
237
238 if name in vgs:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200239 # TODO validation for devices and partitions
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100240 return ret
241
242 if __opts__['test']:
243 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200244 ret['comment'] = 'LVM group {0} will be updated on {1}'.format(
245 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100246 return ret
247
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200248 ret["changes"] = __salt__['maasng.create_volume_group'](
249 hostname, name, devices, partitions)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100250
251 if "error" in ret["changes"]:
252 ret["result"] = False
253
254 return ret
255
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200256
Ondrej Smola47b56752018-03-06 15:38:27 +0100257def volume_present(hostname, name, volume_group_name, size, type=None, mount=None):
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100258 '''
259 Ensure that the disk layout does exist
260
261 :param name: The name of the cloud that should not exist
262 '''
263
264 ret = {'name': hostname,
265 'changes': {},
266 'result': True,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200267 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100268
269 machine = __salt__['maasng.get_machine'](hostname)
270 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200271 ret['comment'] = "State execution failed for machine {0}".format(
272 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100273 ret['result'] = False
274 ret['changes'] = machine
275 return ret
276
277 if machine["status_name"] != "Ready":
278 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
279 return ret
280
281 if __opts__['test']:
282 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200283 ret['comment'] = 'LVM volume {0} will be updated on {1}'.format(
284 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100285
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200286 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100287
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200288 ret["changes"] = __salt__['maasng.create_volume'](
289 hostname, name, volume_group_name, size, type, mount)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100290
291 return ret
292
293
294def select_boot_disk(hostname, name):
295 '''
296 Select disk that will be used to boot partition
297
298 :param name: The name of disk on machine
299 :param hostname: The hostname of machine
300 '''
301
302 ret = {'name': hostname,
303 'changes': {},
304 'result': True,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200305 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100306
307 machine = __salt__['maasng.get_machine'](hostname)
308 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200309 ret['comment'] = "State execution failed for machine {0}".format(
310 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100311 ret['result'] = False
312 ret['changes'] = machine
313 return ret
314
315 if machine["status_name"] != "Ready":
316 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
317 return ret
318
319 if __opts__['test']:
320 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200321 ret['comment'] = 'LVM volume {0} will be updated on {1}'.format(
322 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100323
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200324 # TODO disk validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100325
326 ret["changes"] = __salt__['maasng.set_boot_disk'](hostname, name)
327
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200328 return ret
329
330
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200331def update_vlan(name, fabric, vid, description, primary_rack, dhcp_on=False):
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200332 '''
333
334 :param name: Name of vlan
335 :param fabric: Name of fabric
336 :param vid: Vlan id
337 :param description: Description of vlan
338 :param dhcp_on: State of dhcp
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200339 :param primary_rack: primary_rack
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200340
341 '''
342
343 ret = {'name': fabric,
344 'changes': {},
345 'result': True,
346 'comment': 'Module function maasng.update_vlan executed'}
347
348 ret["changes"] = __salt__['maasng.update_vlan'](
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200349 name=name, fabric=fabric, vid=vid, description=description, primary_rack=primary_rack, dhcp_on=dhcp_on)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200350
351 if "error" in fabric:
352 ret['comment'] = "State execution failed for fabric {0}".format(fabric)
353 ret['result'] = False
354 ret['changes'] = fabric
355 return ret
356
357 if __opts__['test']:
358 ret['result'] = None
359 ret['comment'] = 'Vlan {0} will be updated for {1}'.format(vid, fabric)
360 return ret
361
362 return ret