132
def get_holders(devname):
133
# Look up any block device holders.
134
# Handle devices and partitions as devnames (vdb, md0, vdb7)
135
devname_sysfs = block.sys_block_path(devname)
137
holders = os.listdir(os.path.join(devname_sysfs, 'holders'))
138
LOG.debug("devname '%s' had holders: %s", devname, ','.join(holders))
141
LOG.debug('get_holders: did not find sysfs path for %s', devname)
145
def clear_holders(sys_block_path):
146
holders = os.listdir(os.path.join(sys_block_path, "holders"))
147
LOG.info("clear_holders running on '%s', with holders '%s'" %
148
(sys_block_path, holders))
149
for holder in holders:
150
# get path to holder in /sys/block, then clear it
152
holder_realpath = os.path.realpath(
153
os.path.join(sys_block_path, "holders", holder))
154
clear_holders(holder_realpath)
156
# something might have already caused the holder to go away
157
if util.is_file_not_found_exc(e):
161
# detect what type of holder is using this volume and shut it down, need to
162
# find more robust name of doing detection
163
if "bcache" in sys_block_path:
166
for part_dev in glob.glob(os.path.join(sys_block_path,
167
"slaves", "*", "dev")):
168
with open(part_dev, "r") as fp:
169
part_dev_id = fp.read().rstrip()
171
os.path.split(os.path.realpath(os.path.join("/dev/block",
173
for cache_dev in glob.glob("/sys/fs/bcache/*/bdev*"):
174
for part_dev in part_devs:
175
if part_dev in os.path.realpath(cache_dev):
176
# This is our bcache device, stop it, wait for udev to
178
with open(os.path.join(os.path.split(cache_dev)[0],
180
LOG.info("stopping: %s" % fp)
184
for part_dev in part_devs:
185
block.wipe_volume(os.path.join("/dev", part_dev),
188
if os.path.exists(os.path.join(sys_block_path, "bcache")):
189
# bcache device that isn't running, if it were, we would have found it
190
# when we looked for holders
192
with open(os.path.join(sys_block_path, "bcache", "set", "stop"),
194
LOG.info("stopping: %s" % fp)
197
if not util.is_file_not_found_exc(e):
199
with open(os.path.join(sys_block_path, "bcache", "stop"),
201
LOG.info("stopping: %s" % fp)
205
if os.path.exists(os.path.join(sys_block_path, "md")):
207
block_dev_kname = block.path_to_kname(sys_block_path)
208
block_dev = block.kname_to_path(block_dev_kname)
209
mdadm.mdadm_stop(block_dev)
210
mdadm.mdadm_remove(block_dev)
212
elif os.path.exists(os.path.join(sys_block_path, "dm")):
213
# Shut down any volgroups
214
with open(os.path.join(sys_block_path, "dm", "name"), "r") as fp:
215
name = fp.read().split('-')
216
util.subp(["lvremove", "--force", name[0].rstrip(), name[1].rstrip()],
218
util.subp(["vgremove", name[0].rstrip()], rcs=[0, 5, 6])
221
131
def devsync(devpath):
222
132
LOG.debug('devsync for %s', devpath)
223
133
util.subp(['partprobe', devpath], rcs=[0, 1])
430
340
def disk_handler(info, storage_config):
341
_dos_names = ['dos', 'msdos']
431
342
ptable = info.get('ptable')
433
343
disk = get_path_to_storage_volume(info.get('id'), storage_config)
435
# Handle preserve flag
436
if info.get('preserve'):
438
# Don't need to check state, return
441
# Check state of current ptable, try to do this using blkid, but if
442
# blkid fails then try to fall back to using parted.
443
_possible_errors = (util.ProcessExecutionError, StopIteration,
444
IndexError, AttributeError)
446
(out, _err) = util.subp(["blkid", "-o", "export", disk],
448
current_ptable = next(l.split('=')[1] for l in out.splitlines()
450
except _possible_errors:
452
(out, _err) = util.subp(["parted", disk, "--script", "print"],
454
current_ptable = next(l.split()[-1] for l in out.splitlines()
455
if "Partition Table" in l)
456
except _possible_errors:
457
raise ValueError("disk '%s' has no readable partition table "
458
"or cannot be accessed, but preserve is set "
459
"to true, so cannot continue" % disk)
460
if not (current_ptable == ptable or
461
(current_ptable == "dos" and ptable == "msdos")):
462
raise ValueError("disk '%s' does not have correct "
463
"partition table, but preserve is "
464
"set to true, so not creating table."
345
if config.value_as_boolean(info.get('preserve')):
346
# Handle preserve flag, verifying if ptable specified in config
347
if config.value_as_boolean(ptable):
348
current_ptable = block.get_part_table_type(disk)
349
if not ((ptable in _dos_names and current_ptable in _dos_names) or
350
(ptable == 'gpt' and current_ptable == 'gpt')):
352
"disk '%s' does not have correct partition table or "
353
"cannot be read, but preserve is set to true. "
354
"cannot continue installation." % info.get('id'))
466
355
LOG.info("disk '%s' marked to be preserved, so keeping partition "
471
if info.get('wipe') and info.get('wipe') != "none":
472
# The disk has a lable, clear all partitions
473
mdadm.mdadm_assemble(scan=True)
474
disk_sysfs_path = block.sys_block_path(disk)
475
sysfs_partitions = list(
476
os.path.split(prt)[0] for prt in
477
glob.glob(os.path.join(disk_sysfs_path, '*', 'partition')))
478
for partition in sysfs_partitions:
479
clear_holders(partition)
480
with open(os.path.join(partition, "dev"), "r") as fp:
481
block_no = fp.read().rstrip()
482
partition_path = os.path.realpath(
483
os.path.join("/dev/block", block_no))
484
block.wipe_volume(partition_path, mode=info.get('wipe'))
486
clear_holders(disk_sysfs_path)
487
block.wipe_volume(disk, mode=info.get('wipe'))
489
# Create partition table on disk
490
if info.get('ptable'):
491
LOG.info("labeling device: '%s' with '%s' partition table", disk,
494
util.subp(["sgdisk", "--clear", disk])
495
elif ptable == "msdos":
496
util.subp(["parted", disk, "--script", "mklabel", "msdos"])
358
# wipe the disk and create the partition table if instructed to do so
359
if config.value_as_boolean(info.get('wipe')):
360
block.wipe_volume(disk, mode=info.get('wipe'))
361
if config.value_as_boolean(ptable):
362
LOG.info("labeling device: '%s' with '%s' partition table", disk,
365
util.subp(["sgdisk", "--clear", disk])
366
elif ptable in _dos_names:
367
util.subp(["parted", disk, "--script", "mklabel", "msdos"])
369
raise ValueError('invalid partition table type: %s', ptable)
498
371
# Make the name if needed
499
372
if info.get('name'):
667
540
raise ValueError("parent partition has invalid partition table")
669
# Wipe the partition if told to do so
670
if info.get('wipe') and info.get('wipe') != "none":
672
get_path_to_storage_volume(info.get('id'), storage_config),
673
mode=info.get('wipe'))
542
# Wipe the partition if told to do so, do not wipe dos extended partitions
543
# as this may damage the extended partition table
544
if config.value_as_boolean(info.get('wipe')):
545
if info.get('flag') == "extended":
546
LOG.warn("extended partitions do not need wiping, so skipping: "
547
"'%s'" % info.get('id'))
550
get_path_to_storage_volume(info.get('id'), storage_config),
551
mode=info.get('wipe'))
674
552
# Make the name if needed
675
553
if storage_config.get(device).get('name') and partition_type != 'extended':
676
554
make_dname(info.get('id'), storage_config)
770
648
# Handle preserve flag
771
if info.get('preserve'):
649
if config.value_as_boolean(info.get('preserve')):
772
650
# LVM will probably be offline, so start it
773
651
util.subp(["vgchange", "-a", "y"])
774
652
# Verify that volgroup exists and contains all specified devices
776
(out, _err) = util.subp(["pvdisplay", "-C", "--separator", "=", "-o",
777
"vg_name,pv_name", "--noheadings"],
779
for line in out.splitlines():
781
current_paths.append(line.split("=")[-1])
782
if set(current_paths) != set(device_paths):
783
raise ValueError("volgroup '%s' marked to be preserved, but does \
784
not exist or does not contain the right physical \
785
volumes" % info.get('id'))
653
if set(lvm.get_pvols_in_volgroup(name)) != set(device_paths):
654
raise ValueError("volgroup '%s' marked to be preserved, but does "
655
"not exist or does not contain the right "
656
"physical volumes" % info.get('id'))
787
658
# Create vgrcreate command and run
788
cmd = ["vgcreate", name]
789
cmd.extend(device_paths)
659
# capture output to avoid printing it to log
660
util.subp(['vgcreate', name] + device_paths, capture=True)
793
666
def lvm_partition_handler(info, storage_config):
797
670
raise ValueError("lvm volgroup for lvm partition must be specified")
799
672
raise ValueError("lvm partition name must be specified")
673
if info.get('ptable'):
674
raise ValueError("Partition tables on top of lvm logical volumes is "
801
677
# Handle preserve flag
802
if info.get('preserve'):
803
(out, _err) = util.subp(["lvdisplay", "-C", "--separator", "=", "-o",
804
"lv_name,vg_name", "--noheadings"],
807
for line in out.splitlines():
809
if volgroup == line.split("=")[-1]:
813
raise ValueError("lvm partition '%s' marked to be preserved, but \
814
does not exist or does not mach storage \
815
configuration" % info.get('id'))
678
if config.value_as_boolean(info.get('preserve')):
679
if name not in lvm.get_lvols_in_volgroup(volgroup):
680
raise ValueError("lvm partition '%s' marked to be preserved, but "
681
"does not exist or does not mach storage "
682
"configuration" % info.get('id'))
816
683
elif storage_config.get(info.get('volgroup')).get('preserve'):
817
raise NotImplementedError("Lvm Partition '%s' is not marked to be \
818
preserved, but volgroup '%s' is. At this time, preserving \
819
volgroups but not also the lvm partitions on the volgroup is \
820
not supported, because of the possibility of damaging lvm \
821
partitions intended to be preserved." % (info.get('id'), volgroup))
684
raise NotImplementedError(
685
"Lvm Partition '%s' is not marked to be preserved, but volgroup "
686
"'%s' is. At this time, preserving volgroups but not also the lvm "
687
"partitions on the volgroup is not supported, because of the "
688
"possibility of damaging lvm partitions intended to be "
689
"preserved." % (info.get('id'), volgroup))
823
691
cmd = ["lvcreate", volgroup, "-n", name]
824
692
if info.get('size'):
1150
1014
# set up reportstack
1151
1015
stack_prefix = state.get('report_stack_prefix', '')
1017
# shut down any already existing storage layers above any disks used in
1018
# config that have 'wipe' set
1019
with events.ReportEventStack(
1020
name=stack_prefix, reporting_enabled=True, level='INFO',
1021
description="removing previous storage devices"):
1022
clear_holders.start_clear_holders_deps()
1023
disk_paths = [get_path_to_storage_volume(k, storage_config_dict)
1024
for (k, v) in storage_config_dict.items()
1025
if v.get('type') == 'disk' and
1026
config.value_as_boolean(v.get('wipe')) and
1027
not config.value_as_boolean(v.get('preserve'))]
1028
clear_holders.clear_holders(disk_paths)
1029
# if anything was not properly shut down, stop installation
1030
clear_holders.assert_clear(disk_paths)
1153
1032
for item_id, command in storage_config_dict.items():
1154
1033
handler = command_handlers.get(command['type'])
1155
1034
if not handler: