|
12 | 12 |
|
13 | 13 | import copy
|
14 | 14 | import re
|
| 15 | +import shlex |
15 | 16 |
|
16 | 17 | from ironic_lib import disk_utils
|
17 | 18 | from ironic_lib import utils as il_utils
|
@@ -302,50 +303,58 @@ def prepare_boot_partitions_for_softraid(device, holders, efi_part,
|
302 | 303 | if efi_part:
|
303 | 304 | efi_part = '{}p{}'.format(device, efi_part['number'])
|
304 | 305 |
|
305 |
| - LOG.info("Creating EFI partitions on software RAID holder disks") |
306 |
| - # We know that we kept this space when configuring raid,see |
307 |
| - # hardware.GenericHardwareManager.create_configuration. |
308 |
| - # We could also directly get the EFI partition size. |
309 |
| - partsize_mib = ESP_SIZE_MIB |
310 |
| - partlabel_prefix = 'uefi-holder-' |
311 |
| - efi_partitions = [] |
312 |
| - for number, holder in enumerate(holders): |
313 |
| - # NOTE: see utils.get_partition_table_type_from_specs |
314 |
| - # for uefi we know that we have setup a gpt partition table, |
315 |
| - # sgdisk can be used to edit table, more user friendly |
316 |
| - # for alignment and relative offsets |
317 |
| - partlabel = '{}{}'.format(partlabel_prefix, number) |
318 |
| - out, _u = utils.execute('sgdisk', '-F', holder) |
319 |
| - start_sector = '{}s'.format(out.splitlines()[-1].strip()) |
320 |
| - out, _u = utils.execute( |
321 |
| - 'sgdisk', '-n', '0:{}:+{}MiB'.format(start_sector, |
322 |
| - partsize_mib), |
323 |
| - '-t', '0:ef00', '-c', '0:{}'.format(partlabel), holder) |
324 |
| - |
325 |
| - # Refresh part table |
326 |
| - utils.execute("partprobe") |
327 |
| - utils.execute("blkid") |
328 |
| - |
329 |
| - target_part, _u = utils.execute( |
330 |
| - "blkid", "-l", "-t", "PARTLABEL={}".format(partlabel), holder) |
331 |
| - |
332 |
| - target_part = target_part.splitlines()[-1].split(':', 1)[0] |
333 |
| - efi_partitions.append(target_part) |
334 |
| - |
335 |
| - LOG.debug("EFI partition %s created on holder disk %s", |
336 |
| - target_part, holder) |
337 |
| - |
338 |
| - # RAID the ESPs, metadata=1.0 is mandatory to be able to boot |
339 |
| - md_device = get_next_free_raid_device() |
340 |
| - LOG.debug("Creating md device %(md_device)s for the ESPs " |
341 |
| - "on %(efi_partitions)s", |
342 |
| - {'md_device': md_device, 'efi_partitions': efi_partitions}) |
343 |
| - utils.execute('mdadm', '--create', md_device, '--force', |
344 |
| - '--run', '--metadata=1.0', '--level', '1', |
345 |
| - '--name', 'esp', '--raid-devices', len(efi_partitions), |
346 |
| - *efi_partitions) |
347 |
| - |
348 |
| - disk_utils.trigger_device_rescan(md_device) |
| 306 | + # check if we have a RAIDed ESP already |
| 307 | + md_device = find_esp_raid() |
| 308 | + if md_device: |
| 309 | + LOG.info("Found RAIDed ESP %s, skip creation", md_device) |
| 310 | + else: |
| 311 | + LOG.info("Creating EFI partitions on software RAID holder disks") |
| 312 | + # We know that we kept this space when configuring raid,see |
| 313 | + # hardware.GenericHardwareManager.create_configuration. |
| 314 | + # We could also directly get the EFI partition size. |
| 315 | + partsize_mib = ESP_SIZE_MIB |
| 316 | + partlabel_prefix = 'uefi-holder-' |
| 317 | + efi_partitions = [] |
| 318 | + for number, holder in enumerate(holders): |
| 319 | + # NOTE: see utils.get_partition_table_type_from_specs |
| 320 | + # for uefi we know that we have setup a gpt partition table, |
| 321 | + # sgdisk can be used to edit table, more user friendly |
| 322 | + # for alignment and relative offsets |
| 323 | + partlabel = '{}{}'.format(partlabel_prefix, number) |
| 324 | + out, _u = utils.execute('sgdisk', '-F', holder) |
| 325 | + start_sector = '{}s'.format(out.splitlines()[-1].strip()) |
| 326 | + out, _u = utils.execute( |
| 327 | + 'sgdisk', '-n', '0:{}:+{}MiB'.format(start_sector, |
| 328 | + partsize_mib), |
| 329 | + '-t', '0:ef00', '-c', '0:{}'.format(partlabel), holder) |
| 330 | + |
| 331 | + # Refresh part table |
| 332 | + utils.execute("partprobe") |
| 333 | + utils.execute("blkid") |
| 334 | + |
| 335 | + target_part, _u = utils.execute( |
| 336 | + "blkid", "-l", "-t", "PARTLABEL={}".format(partlabel), |
| 337 | + holder) |
| 338 | + |
| 339 | + target_part = target_part.splitlines()[-1].split(':', 1)[0] |
| 340 | + efi_partitions.append(target_part) |
| 341 | + |
| 342 | + LOG.debug("EFI partition %s created on holder disk %s", |
| 343 | + target_part, holder) |
| 344 | + |
| 345 | + # RAID the ESPs, metadata=1.0 is mandatory to be able to boot |
| 346 | + md_device = get_next_free_raid_device() |
| 347 | + LOG.debug("Creating md device %(md_device)s for the ESPs " |
| 348 | + "on %(efi_partitions)s", |
| 349 | + {'md_device': md_device, |
| 350 | + 'efi_partitions': efi_partitions}) |
| 351 | + utils.execute('mdadm', '--create', md_device, '--force', |
| 352 | + '--run', '--metadata=1.0', '--level', '1', |
| 353 | + '--name', 'esp', '--raid-devices', |
| 354 | + len(efi_partitions), |
| 355 | + *efi_partitions) |
| 356 | + |
| 357 | + disk_utils.trigger_device_rescan(md_device) |
349 | 358 |
|
350 | 359 | if efi_part:
|
351 | 360 | # Blockdev copy the source ESP and erase it
|
@@ -380,3 +389,18 @@ def prepare_boot_partitions_for_softraid(device, holders, efi_part,
|
380 | 389 | # disk, as in virtual disk, where to load the data from.
|
381 | 390 | # Since there is a structural difference, this means it will
|
382 | 391 | # fail.
|
| 392 | + |
| 393 | + |
| 394 | +def find_esp_raid(): |
| 395 | + """Find the ESP md device in case of a rebuild.""" |
| 396 | + |
| 397 | + # find devices of type 'RAID1' and fstype 'VFAT' |
| 398 | + lsblk = utils.execute('lsblk', '-PbioNAME,TYPE,FSTYPE') |
| 399 | + report = lsblk[0] |
| 400 | + for line in report.split('\n'): |
| 401 | + dev = {} |
| 402 | + vals = shlex.split(line) |
| 403 | + for key, val in (v.split('=', 1) for v in vals): |
| 404 | + dev[key] = val.strip() |
| 405 | + if dev.get('TYPE') == 'raid1' and dev.get('FSTYPE') == 'vfat': |
| 406 | + return '/dev/' + dev.get('NAME') |
0 commit comments