Non-existent lvm snapshots have a copy of the origin's format as their format. When an origin's format changes, all non-existent snapshots of that origin must have their formats updated as well.
Related: rhbz#1236988
(cherry picked from commit 1c2d8a0b3633145b0528c4a0734e4ac7a7bffed8)
Signed-off-by: Vojtech Trefny vtrefny@redhat.com --- blivet/devices.py | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-)
diff --git a/blivet/devices.py b/blivet/devices.py index c576a19..b389e31 100644 --- a/blivet/devices.py +++ b/blivet/devices.py @@ -3027,6 +3027,10 @@ class LVMLogicalVolumeDevice(DMDevice): raise ValueError("constructor requires a LVMVolumeGroupDevice instance") elif not isinstance(parents, LVMVolumeGroupDevice): raise ValueError("constructor requires a LVMVolumeGroupDevice instance") + + # When this device's format is set in the superclass constructor it will + # try to access self.snapshots. + self.snapshots = [] DMDevice.__init__(self, name, size=size, fmt=fmt, sysfsPath=sysfsPath, parents=parents, exists=exists) @@ -3036,7 +3040,6 @@ class LVMLogicalVolumeDevice(DMDevice): self.logSize = logSize self.metaDataSize = 0 self.segType = segType or "linear" - self.snapshots = []
self.req_grow = None self.req_max_size = Size(0) @@ -3107,6 +3110,11 @@ class LVMLogicalVolumeDevice(DMDevice): return (self.vg.align(self.size, roundup=True) * self.copies + self.logSize + self.metaDataSize)
+ def _setFormat(self, fmt): + super(LVMLogicalVolumeDevice, self)._setFormat(fmt) + for snapshot in (s for s in self.snapshots if not s.exists): + snapshot._updateFormatFromOrigin() + @property def vg(self): """ This Logical Volume's Volume Group. """ @@ -3337,8 +3345,8 @@ class LVMSnapShotBase(object): Normal/old snapshots must be removed with their origin, while thin snapshots can remain after their origin is removed.
- It is also impossible to set the format for a snapshot explicitly as it - always has the same format as its origin. + It is also impossible to set the format for a non-existent snapshot + explicitly as it always has the same format as its origin. """ __metaclass__ = abc.ABCMeta
@@ -3383,15 +3391,32 @@ class LVMSnapShotBase(object): if vorigin and not exists: raise ValueError("only existing vorigin snapshots are supported")
- def _setFormat(self, fmt): - pass + def _updateFormatFromOrigin(self): + """ Update the snapshot's format to reflect the origin's. + .. note:: + This should only be called for non-existent snapshot devices. + Once a snapshot exists its format is distinct from that of its + origin.
- def _getFormat(self): - if self.origin is None: - fmt = getFormat(None) + """ + fmt = copy.deepcopy(self.origin.format) + fmt.exists = False + if hasattr(fmt, "mountpoint"): + fmt.mountpoint = "" + fmt._chrootedMountpoint = None + fmt.device = self.path # pylint: disable=no-member + + super(LVMSnapShotBase, self)._setFormat(fmt) + + def _setFormat(self, fmt): + # If a snapshot exists it can have a format that is distinct from its + # origin's. If it does not exist its format must be a copy of its + # origin's. + if self.exists: # pylint: disable=no-member + super(LVMSnapShotBase, self)._setFormat(fmt) else: - fmt = self.origin.format - return fmt + log.info("copying %s origin's format", self.name) # pylint: disable=no-member + self._updateFormatFromOrigin()
@abc.abstractmethod def _create(self): @@ -3736,7 +3761,7 @@ class LVMThinSnapShotDevice(LVMSnapShotBase, LVMThinLogicalVolumeDevice):
LVMSnapShotBase.__init__(self, origin=origin, exists=exists) LVMThinLogicalVolumeDevice.__init__(self, name, parents=parents, - sysfsPath=sysfsPath,fmt=None, + sysfsPath=sysfsPath,fmt=fmt, segType=segType, uuid=uuid, size=size, exists=exists)
On Thu, 2015-07-09 at 12:56 +0200, Vojtech Trefny wrote:
Non-existent lvm snapshots have a copy of the origin's format as their format. When an origin's format changes, all non-existent snapshots of that origin must have their formats updated as well.
Related: rhbz#1236988
Ack.
anaconda-patches@lists.fedorahosted.org