blob: cbe8b5d75b33910b4882d764667bbcdf654ba96c [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
67 else:
68 ret["comment"] = "Not supported layout provided. Choose flat or lvm"
69 ret['result'] = False
70
71 return ret
72
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020073
Ondrej Smolab57a23b2018-01-24 11:18:24 +010074def raid_present(hostname, name, level, devices=[], partitions=[], partition_schema={}):
75 '''
76 Ensure that the raid does exist
77
78 :param name: The name of the cloud that should not exist
79 '''
80
81 ret = {'name': name,
82 'changes': {},
83 'result': True,
84 'comment': 'Raid {0} presented on {1}'.format(name, hostname)}
85
86 machine = __salt__['maasng.get_machine'](hostname)
87 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +020088 ret['comment'] = "State execution failed for machine {0}".format(
89 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +010090 ret['result'] = False
91 ret['changes'] = machine
92 return ret
93
94 if machine["status_name"] != "Ready":
95 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
96 return ret
97
98 if __opts__['test']:
99 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200100 ret['comment'] = 'Raid {0} will be updated on {1}'.format(
101 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100102 return ret
103
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200104 # Validate that raid exists
105 # With correct devices/partition
106 # OR
107 # Create raid
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100108
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200109 ret["changes"] = __salt__['maasng.create_raid'](
110 hostname=hostname, name=name, level=level, disks=devices, partitions=partitions)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100111
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200112 # TODO partitions
113 ret["changes"].update(disk_partition_present(
114 hostname, name, partition_schema)["changes"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100115
116 if "error" in ret["changes"]:
117 ret["result"] = False
118
119 return ret
120
121
122def disk_partition_present(hostname, disk, partition_schema={}):
123 '''
124 Ensure that the disk has correct partititioning schema
125
126 :param name: The name of the cloud that should not exist
127 '''
128
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200129 # 1. Validate that disk has correct values for size and mount
130 # a. validate count of partitions
131 # b. validate size of partitions
132 # 2. If not delete all partitions on disk and recreate schema
133 # 3. Validate type exists
134 # if should not exits
135 # delete mount and unformat
136 # 4. Validate mount exists
137 # 5. if not enforce umount or mount
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100138
139 ret = {'name': hostname,
140 'changes': {},
141 'result': True,
142 'comment': 'Disk layout {0} presented'.format(disk)}
143
144 machine = __salt__['maasng.get_machine'](hostname)
145 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200146 ret['comment'] = "State execution failed for machine {0}".format(
147 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100148 ret['result'] = False
149 ret['changes'] = machine
150 return ret
151
152 if machine["status_name"] != "Ready":
153 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
154 return ret
155
156 if __opts__['test']:
157 ret['result'] = None
158 ret['comment'] = 'Partition schema will be changed on {0}'.format(disk)
159 return ret
160
161 partitions = __salt__['maasng.list_partitions'](hostname, disk)
162
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200163 # Calculate actual size in bytes from provided data
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100164 for part_name, part in partition_schema.iteritems():
165 size, unit = part["size"][:-1], part["size"][-1]
166 part["calc_size"] = int(size) * SIZE[unit]
167
168 if len(partitions) == len(partition_schema):
169
170 for part_name, part in partition_schema.iteritems():
171 LOG.info('validated {0}'.format(part["calc_size"]))
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200172 LOG.info('validated {0}'.format(
173 int(partitions[disk+"-"+part_name.split("-")[-1]]["size"])))
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100174 if part["calc_size"] == int(partitions[disk+"-"+part_name.split("-")[-1]]["size"]):
175 LOG.info('validated')
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200176 # TODO validate size (size from maas is not same as calculate?)
177 # TODO validate mount
178 # TODO validate fs type
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100179 else:
180 LOG.info('breaking')
181 break
182 return ret
183
184 #DELETE and RECREATE
185 LOG.info('delete')
186 for partition_name, partition in partitions.iteritems():
187 LOG.info(partition)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200188 # TODO IF LVM create ERROR
189 ret["changes"] = __salt__['maasng.delete_partition_by_id'](
190 hostname, disk, partition["id"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100191
192 LOG.info('recreating')
193 for part_name, part in partition_schema.iteritems():
194 LOG.info("partitition for creation")
195 LOG.info(part)
196 if "mount" not in part:
197 part["mount"] = None
198 if "type" not in part:
199 part["type"] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200200 ret["changes"] = __salt__['maasng.create_partition'](
201 hostname, disk, part["size"], part["type"], part["mount"])
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100202
203 if "error" in ret["changes"]:
204 ret["result"] = False
205
206 return ret
207
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200208
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100209def volume_group_present(hostname, name, devices=[], partitions=[]):
210 '''
211 Ensure that the disk layout does exist
212
213 :param name: The name of the cloud that should not exist
214 '''
215 ret = {'name': hostname,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200216 'changes': {},
217 'result': True,
218 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100219
220 machine = __salt__['maasng.get_machine'](hostname)
221 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200222 ret['comment'] = "State execution failed for machine {0}".format(
223 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100224 ret['result'] = False
225 ret['changes'] = machine
226 return ret
227
228 if machine["status_name"] != "Ready":
229 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
230 return ret
231
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200232 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100233 vgs = __salt__['maasng.list_volume_groups'](hostname)
234
235 if name in vgs:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200236 # TODO validation for devices and partitions
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100237 return ret
238
239 if __opts__['test']:
240 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200241 ret['comment'] = 'LVM group {0} will be updated on {1}'.format(
242 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100243 return ret
244
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200245 ret["changes"] = __salt__['maasng.create_volume_group'](
246 hostname, name, devices, partitions)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100247
248 if "error" in ret["changes"]:
249 ret["result"] = False
250
251 return ret
252
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200253
Ondrej Smola47b56752018-03-06 15:38:27 +0100254def volume_present(hostname, name, volume_group_name, size, type=None, mount=None):
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100255 '''
256 Ensure that the disk layout does exist
257
258 :param name: The name of the cloud that should not exist
259 '''
260
261 ret = {'name': hostname,
262 'changes': {},
263 'result': True,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200264 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100265
266 machine = __salt__['maasng.get_machine'](hostname)
267 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200268 ret['comment'] = "State execution failed for machine {0}".format(
269 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100270 ret['result'] = False
271 ret['changes'] = machine
272 return ret
273
274 if machine["status_name"] != "Ready":
275 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
276 return ret
277
278 if __opts__['test']:
279 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200280 ret['comment'] = 'LVM volume {0} will be updated on {1}'.format(
281 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100282
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200283 # TODO validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100284
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200285 ret["changes"] = __salt__['maasng.create_volume'](
286 hostname, name, volume_group_name, size, type, mount)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100287
288 return ret
289
290
291def select_boot_disk(hostname, name):
292 '''
293 Select disk that will be used to boot partition
294
295 :param name: The name of disk on machine
296 :param hostname: The hostname of machine
297 '''
298
299 ret = {'name': hostname,
300 'changes': {},
301 'result': True,
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200302 'comment': 'LVM group {0} presented on {1}'.format(name, hostname)}
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100303
304 machine = __salt__['maasng.get_machine'](hostname)
305 if "error" in machine:
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200306 ret['comment'] = "State execution failed for machine {0}".format(
307 hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100308 ret['result'] = False
309 ret['changes'] = machine
310 return ret
311
312 if machine["status_name"] != "Ready":
313 ret['comment'] = 'Machine {0} is not in Ready state.'.format(hostname)
314 return ret
315
316 if __opts__['test']:
317 ret['result'] = None
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200318 ret['comment'] = 'LVM volume {0} will be updated on {1}'.format(
319 name, hostname)
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100320
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200321 # TODO disk validation if exists
Ondrej Smolab57a23b2018-01-24 11:18:24 +0100322
323 ret["changes"] = __salt__['maasng.set_boot_disk'](hostname, name)
324
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200325 return ret
326
327
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200328def update_vlan(name, fabric, vid, description, primary_rack, dhcp_on=False):
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200329 '''
330
331 :param name: Name of vlan
332 :param fabric: Name of fabric
333 :param vid: Vlan id
334 :param description: Description of vlan
335 :param dhcp_on: State of dhcp
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200336 :param primary_rack: primary_rack
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200337
338 '''
339
340 ret = {'name': fabric,
341 'changes': {},
342 'result': True,
343 'comment': 'Module function maasng.update_vlan executed'}
344
345 ret["changes"] = __salt__['maasng.update_vlan'](
Pavel Cizinsky864a3292018-05-25 16:24:48 +0200346 name=name, fabric=fabric, vid=vid, description=description, primary_rack=primary_rack, dhcp_on=dhcp_on)
Pavel Cizinsky0995e8f2018-05-04 17:10:37 +0200347
348 if "error" in fabric:
349 ret['comment'] = "State execution failed for fabric {0}".format(fabric)
350 ret['result'] = False
351 ret['changes'] = fabric
352 return ret
353
354 if __opts__['test']:
355 ret['result'] = None
356 ret['comment'] = 'Vlan {0} will be updated for {1}'.format(vid, fabric)
357 return ret
358
359 return ret