Patch 4 adds the factory code for the container size policies used by the container size management patch to anaconda I'll send in a few minutes.
- Get wwid from a valid source - Use addUdevDMDevice for multipath partitions - Trim 'p' delimiter when converting dm partition name to dm disk name --- blivet/devicetree.py | 10 ++++++++-- blivet/udev.py | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/blivet/devicetree.py b/blivet/devicetree.py index eaeff58..691f1b2 100644 --- a/blivet/devicetree.py +++ b/blivet/devicetree.py @@ -690,7 +690,12 @@ class DeviceTree(object): slave_devs.append(slave_dev)
if slave_devs: - serial = info.get("ID_SERIAL_RAW", info.get("ID_SERIAL_SHORT")) + try: + serial = info["DM_UUID"].split("-", 1)[1] + except (IndexError, AttributeError): + log.error("multipath device %s has no DM_UUID" % name) + raise DeviceTreeError("multipath %s has no DM_UUID" % name) + device = MultipathDevice(name, parents=slave_devs, serial=serial) self._addDevice(device) @@ -1014,7 +1019,8 @@ class DeviceTree(object): elif udev_device_is_loop(info): log.info("%s is a loop device" % name) device = self.addUdevLoopDevice(info) - elif udev_device_is_dm_mpath(info): + elif udev_device_is_dm_mpath(info) and \ + not udev_device_is_dm_partition(info): log.info("%s is a multipath device" % name) device = self.addUdevMultiPathDevice(info) elif udev_device_is_dm_lvm(info): diff --git a/blivet/udev.py b/blivet/udev.py index b944cb2..bdb7ffe 100644 --- a/blivet/udev.py +++ b/blivet/udev.py @@ -528,7 +528,7 @@ def udev_device_is_biosraid_member(info): return False
def udev_device_get_dm_partition_disk(info): - return re.sub(r'\d*$', '', udev_device_get_name(info)) + return re.sub(r'p?\d*$', '', udev_device_get_name(info))
def udev_device_is_dm_partition(info): return (udev_device_is_dm(info) and
--- blivet/devices.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/blivet/devices.py b/blivet/devices.py index c5000d2..aa96d3d 100644 --- a/blivet/devices.py +++ b/blivet/devices.py @@ -4005,7 +4005,8 @@ class BTRFSVolumeDevice(BTRFSDevice): exists=self.exists, label=label, volUUID=self.uuid, - device=self.path) + device=self.path, + mountopts="subvolid=0") self.originalFormat = copy.copy(self.format)
def _setFormat(self, format):
They are unused and dangerous given that the container is specified by name instead of by passing in a StorageDevice instance. --- blivet/devicefactory.py | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-)
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py index a16bb92..edca449 100644 --- a/blivet/devicefactory.py +++ b/blivet/devicefactory.py @@ -418,9 +418,11 @@ class DeviceFactory(object):
def _reconfigure_container(self): """ Reconfigure a defined container required by this factory device. """ + if getattr(self.container, "exists", False): + return + self._set_container_members() self._set_container_raid_level() - self._set_container_name()
def _set_container_members(self): if not self.child_factory: @@ -440,9 +442,6 @@ class DeviceFactory(object): def _set_container_raid_level(self): pass
- def _set_container_name(self): - pass - # # properties and methods related to the factory device # @@ -1092,22 +1091,6 @@ class LVMFactory(DeviceFactory): def _get_new_container(self, *args, **kwargs): return self.storage.newVG(*args, **kwargs)
- def _set_container_name(self): - if self.container_name is None: - return - - # TODO: write a StorageDevice.name setter - safe_new_name = self.storage.safeDeviceName(self.container_name) - if self.container.name != safe_new_name: - if safe_new_name in self.storage.names: - log.error("not renaming '%s' to in-use name '%s'" - % (self.container._name, safe_new_name)) - return - - log.debug("renaming container '%s' to '%s'" - % (self.container._name, safe_new_name)) - self.container._name = safe_new_name - # # methods to configure the factory's device # @@ -1274,20 +1257,6 @@ class BTRFSFactory(DeviceFactory): parents=parents) self.storage.createDevice(self.container)
- def _set_container_name(self): - if self.container_name is None: - return - - # TODO: write a StorageDevice.name setter - safe_new_name = self.storage.safeDeviceName(self.container_name) - if self.container.name != safe_new_name: - # we don't need to check for in-use names since btrfs volumes have - # no device node of their own - log.debug("renaming container '%s' to '%s'" - % (self.container._name, safe_new_name)) - self.container._name = safe_new_name - self.container.format.label = self.container_name - def _set_container_raid_level(self): # TODO: write BTRFSVolumeDevice.setRAIDLevel # make sure the member count is adequate for the new level
--- blivet/devicefactory.py | 131 ++++++++++++++++++++++++++++++++++-------------- blivet/devices.py | 6 ++- 2 files changed, 99 insertions(+), 38 deletions(-)
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py index edca449..938a48c 100644 --- a/blivet/devicefactory.py +++ b/blivet/devicefactory.py @@ -40,6 +40,9 @@ _ = lambda x: gettext.ldgettext("blivet", x) import logging log = logging.getLogger("blivet")
+SIZE_POLICY_MAX = -1 +SIZE_POLICY_AUTO = 0 + DEVICE_TYPE_LVM = 0 DEVICE_TYPE_MD = 1 DEVICE_TYPE_PARTITION = 2 @@ -211,7 +214,7 @@ class DeviceFactory(object): def __init__(self, storage, size, disks, fstype=None, mountpoint=None, label=None, raid_level=None, encrypted=False, container_encrypted=False, container_name=None, - container_raid_level=None, + container_raid_level=None, container_size=SIZE_POLICY_AUTO, name=None, device=None): """ Create a new DeviceFactory instance.
@@ -228,16 +231,16 @@ class DeviceFactory(object): label filesystem label text
raid_level raid level string, eg: "raid1" - container_raid_level - encrypted whether to encrypt (boolean) - container_encrypted whether to encrypt the entire container - - container_name name of requested container name name of requested device
device an already-defined but non-existent device to adjust instead of creating a new device + + container_name name of requested container + container_raid_level + container_encrypted whether to encrypt the entire container + container_size requested container size """ self.storage = storage # a Blivet instance self.size = size # the requested size for this device @@ -259,6 +262,8 @@ class DeviceFactory(object): self.container_name = container_name self.device_name = name
+ self.container_size = container_size + self.container = None self.device = device
@@ -278,20 +283,30 @@ class DeviceFactory(object): # # methods related to device size and disk space requirements # + def _get_free_disk_space(self): + free_info = self.storage.getFreeSpace(disks=self.disks) + free = sum(d[0] for d in free_info.values()) + return int(free.convertTo(spec="mb")) + def _handle_no_size(self): """ Set device size so that it grows to the largest size possible. """ if self.size is not None: return
- free_info = self.storage.getFreeSpace(disks=self.disks) - free = sum(d[0] for d in free_info.values()) - self.size = int(free.convertTo(spec="mb")) + self.size = self._get_free_disk_space()
if self.device: self.size += self.device.size
+ if self.container_size > 0: + self.size = min(self.container_size, self.size) + def _get_total_space(self): - """ Return the total space need for this factory's device/container. """ + """ Return the total space need for this factory's device/container. + + This is used for the size argument to the child factory constructor + and also to construct the size set in PartitionSetFactory.configure. + """ size = self._get_device_space() if self.container: size += container.size @@ -648,8 +663,12 @@ class DeviceFactory(object): if self.child_factory or not self.child_factory_class: return
- factory = self.child_factory_class(*self._get_child_factory_args(), - **self._get_child_factory_kwargs()) + args = self._get_child_factory_args() + kwargs = self._get_child_factory_kwargs() + log.debug("child factory class: %s" % self.child_factory_class) + log.debug("child factory args: %s" % args) + log.debug("child factory kwargs: %s" % kwargs) + factory = self.child_factory_class(*args, **kwargs) self.child_factory = factory factory.parent_factory = self
@@ -714,6 +733,10 @@ class DeviceFactory(object): else: self._create_container()
+ if self.container and hasattr(self.container, "size_policy") and \ + not self.container.exists: + self.container.size_policy = self.container_size + # Configure this factory's leaf device, eg, for LVMFactory: the LV. if self.device: self._reconfigure_device() @@ -859,6 +882,10 @@ class PartitionSetFactory(PartitionFactory): container = self.parent_factory.container log.debug("parent factory container: %s" % self.parent_factory.container) if container: + if container.exists: + log.info("parent factory container exists -- nothing to do") + return + # update our device list from the parent factory's container members members = container.parents[:] self._devices = members @@ -1021,7 +1048,8 @@ class LVMFactory(DeviceFactory): if self.size is not None: return
- if self.container and self.container.exists: + if self.container and (self.container.exists or + self.container_size > 0): self.size = self.container.freeSpace
if self.device: @@ -1067,17 +1095,38 @@ class LVMFactory(DeviceFactory): def _get_total_space(self): """ Total disk space requirement for this device and its container. """ size = 0 - if self.container: - size += sum([p.size for p in self.container.parents]) - size -= self.container.freeSpace - - size += self._get_device_space() - if self.device: - # The member count here uses the container's current member set - # since that's the basis for the current device's disk space usage. - size -= get_pv_space(self.device.size, - len(self.container.parents), - **self.size_func_kwargs) + if self.container and self.container.exists: + return size + + if self.container_size == 0: + # automatic container size management + if self.container: + size += sum([p.size for p in self.container.parents]) + size -= self.container.freeSpace + elif self.container_size == SIZE_POLICY_MAX: + # grow the container as large as possible + if self.container: + size += sum(p.size for p in self.container.parents) + log.debug("size bumped to %d to include container parents" % size) + + size += self._get_free_disk_space() + log.debug("size bumped to %d to include free disk space" % size) + else: + # container_size is a request for a fixed size for the container + size += get_pv_space(self.container_size, len(self.disks)) + + # this does not apply if a specific container size was requested + if self.container_size in [SIZE_POLICY_AUTO, SIZE_POLICY_MAX]: + size += self._get_device_space() + log.debug("size bumped to %d to include new device space" % size) + if self.device and self.container_size == SIZE_POLICY_AUTO: + # The member count here uses the container's current member set + # since that's the basis for the current device's disk space + # usage. + size -= get_pv_space(self.device.size, + len(self.container.parents), + **self.size_func_kwargs) + log.debug("size cut to %d to omit old device space" % size)
return size
@@ -1127,12 +1176,12 @@ class MDFactory(DeviceFactory): size_set_class = SameSizeSet
def _get_device_space(self): - return self._get_total_space() - - def _get_total_space(self): return get_member_space(self.size, len(self._get_member_devices()), level=self.raid_level)
+ def _get_total_space(self): + return self._get_device_space() + def _set_raid_level(self): # TODO: write MDRaidArrayDevice.setRAIDLevel # make sure the member count is adequate for the new level @@ -1220,18 +1269,26 @@ class BTRFSFactory(DeviceFactory):
def _get_total_space(self): """ Return the total space needed for the specified container. """ - if not self.container: - container_size = 0 - elif self.container.exists: - container_size = self.container.size - else: - container_size = sum(s.req_size for s in self.container.subvolumes) + size = 0 + if self.container and self.container.exists: + return size
- size = self._get_device_space() + if self.container_size == SIZE_POLICY_AUTO: + # automatic + if self.container and not self.device: + # For new subvols the size is in addition to the volume's size. + size += sum(s.req_size for s in self.container.subvolumes)
- if not self.device: - # For new subvols the size is in addition to the volume's size. - size += container_size + size += self._get_device_space() + elif self.container_size == SIZE_POLICY_MAX: + # as large as possible + if self.container: + size += self.container.size + + size += self._get_free_disk_space() + else: + # fixed-size request + size = self.container_size
return size
diff --git a/blivet/devices.py b/blivet/devices.py index aa96d3d..450dac0 100644 --- a/blivet/devices.py +++ b/blivet/devices.py @@ -1,7 +1,7 @@ # devices.py # Device classes for anaconda's storage configuration module. # -# Copyright (C) 2009 Red Hat, Inc. +# Copyright (C) 2009-2013 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of @@ -2022,6 +2022,9 @@ class LVMVolumeGroupDevice(DMDevice): # They still occupy space in the VG. self.voriginSnapshots = {}
+ # >0 is fixed + self.size_policy = self.size + def __repr__(self): s = DMDevice.__repr__(self) s += (" free = %(free)s PE Size = %(peSize)s PE Count = %(peCount)s\n" @@ -3988,6 +3991,7 @@ class BTRFSVolumeDevice(BTRFSDevice): super(BTRFSVolumeDevice, self).__init__(*args, **kwargs)
self.subvolumes = [] + self.size_policy = self.size
for parent in self.parents: if parent.format.type != "btrfs":
On Thu, 2013-05-02 at 12:58 -0500, David Lehman wrote:
blivet/devicefactory.py | 131 ++++++++++++++++++++++++++++++++++-------------- blivet/devices.py | 6 ++- 2 files changed, 99 insertions(+), 38 deletions(-)
# >0 is fixed
I think this comment should go also above the SIZE_POLICY_* constants definitions.
We were adding in the vg name, eg: test-old -> test-test-new --- blivet/devicefactory.py | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py index 938a48c..a2be2e5 100644 --- a/blivet/devicefactory.py +++ b/blivet/devicefactory.py @@ -1165,6 +1165,12 @@ class LVMFactory(DeviceFactory): % (self.device._name, safe_new_name)) return
+ if not safe_new_name.startswith(self.container.name): + log.error("device rename failure (%s)" % safe_new_name) + return + + # strip off the vg name before setting + safe_new_name = safe_new_name[len(self.container.name)+1:] log.debug("renaming device '%s' to '%s'" % (self.device._name, safe_new_name)) self.device._name = safe_new_name
Apart from the minor comment to PATCH 4/5, these all look good to me.
anaconda-patches@lists.fedorahosted.org