Related to rhinstaller/pykickstart/pull/29
From: David Lehman dlehman@redhat.com
Related: rhbz#1113207 --- blivet/autopart.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)
diff --git a/blivet/autopart.py b/blivet/autopart.py index 1359ba0..206e179 100644 --- a/blivet/autopart.py +++ b/blivet/autopart.py @@ -25,8 +25,10 @@
from . import util from .size import Size +from .devices.btrfs import BTRFSSnapShotDevice from .devices.partition import PartitionDevice, FALLBACK_DEFAULT_PART_SIZE from .devices.luks import LUKSDevice +from .devices.lvm import LVMThinSnapShotDevice from .errors import NoDisksError, NotEnoughFreeSpaceError from .formats import getFormat from .partitioning import doPartitioning, getFreeRegions, growLVM @@ -509,3 +511,42 @@ def doAutoPartition(storage, data, min_luks_entropy=0): # only newly added swaps should appear in the fstab new_swaps = (dev for dev in storage.swaps if not dev.format.exists) storage.setFstabSwaps(new_swaps) + +def setUpRootSnapShot(storage): + """ Snapshot the root device and remount with the snapshot as root. """ + log.info("makeRootThinPSnapShot: autopart type is %s", storage.autoPartType) + try: + make_snapshot = (storage.ksdata.autopart.autopart and + storage.ksdata.autopart.snapshot) + except AttributeError: + make_snapshot = False + + if not make_snapshot: + return + + # set up the snapshot + root = storage.rootDevice + parent = getattr(root, "pool", root.container) + name = storage.suggestDeviceName(parent=parent, prefix="rootsnap") + + if storage.ksdata.autopart.type == AUTOPART_TYPE_BTRFS: + snapshot = BTRFSSnapShotDevice(name, parents=[parent], source=root) + elif storage.ksdata.autopart.type == AUTOPART_TYPE_LVM_THINP: + snapshot = LVMThinSnapShotDevice(name, parents=[parent], origin=root) + else: + log.error("invalid autopart type for root snapshot: %s", + storage.ksdata.autopart.type) + return + + # create the snapshot + storage.createDevice(snapshot) + storage.devicetree.processActions() + + # remount the system with the snapshot as the root device + storage.umountFilesystems() + + root.format.mountpoint = "" + snapshot.format.mountpoint = "/" + + storage.write() + storage.mountFilesystems()
From: David Lehman dlehman@redhat.com
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#1113207 --- blivet/devices/lvm.py | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py index 3b94a22..c524a11 100644 --- a/blivet/devices/lvm.py +++ b/blivet/devices/lvm.py @@ -22,6 +22,7 @@ from decimal import Decimal from six import add_metaclass import abc +import copy import pprint import re import os @@ -32,7 +33,6 @@
from .. import errors from .. import util -from ..formats import getFormat from ..storage_log import log_method_call from .. import udev from ..size import Size, KiB, MiB, ROUND_UP, ROUND_DOWN @@ -500,6 +500,9 @@ def __init__(self, name, parents=None, size=None, uuid=None, if not isinstance(container, self._containerClass): raise ValueError("constructor requires a %s instance" % self._containerClass.__name__)
+ # 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) @@ -509,7 +512,6 @@ def __init__(self, name, parents=None, size=None, uuid=None, self.logSize = logSize or Size(0) self.metaDataSize = Size(0) self.segType = segType or "linear" - self.snapshots = []
self.req_grow = None self.req_max_size = Size(0) @@ -580,6 +582,11 @@ def vgSpaceUsed(self): 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. """ @@ -811,8 +818,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. """ _type = "lvmsnapshotbase"
@@ -855,15 +862,33 @@ def _voriginExistenceCheck(self, vorigin, exists): 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.
- def _getFormat(self): - if self.origin is None: - fmt = getFormat(None) + .. note:: + This should only be called for non-existent snapshot devices. + Once a snapshot exists its format is distinct from that of its + origin. + + """ + 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): @@ -1220,7 +1245,7 @@ def __init__(self, name, parents=None, sysfsPath='', origin=None,
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)
From: David Lehman dlehman@redhat.com
Related: rhbz#1113207 --- blivet/devices/lvm.py | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py index c524a11..6ad9408 100644 --- a/blivet/devices/lvm.py +++ b/blivet/devices/lvm.py @@ -1271,6 +1271,11 @@ def _create(self): blockdev.lvm.thsnapshotcreate(self.vg.name, self._name, self.origin.lvname, pool_name=pool_name)
+ def _postCreate(self): + super(LVMThinSnapShotDevice, self)._postCreate() + # A snapshot's format exists as soon as the snapshot has been created. + self.format.exists = True + def dependsOn(self, dep): # once a thin snapshot exists it no longer depends on its origin return ((self.origin == dep and not self.exists) or
From: David Lehman dlehman@redhat.com
Related: rhbz#1113207 --- blivet/devices/lvm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/blivet/devices/lvm.py b/blivet/devices/lvm.py index 6ad9408..af3dd56 100644 --- a/blivet/devices/lvm.py +++ b/blivet/devices/lvm.py @@ -1268,7 +1268,7 @@ def _create(self): # to use pool_name = self.pool.lvname
- blockdev.lvm.thsnapshotcreate(self.vg.name, self._name, self.origin.lvname, + blockdev.lvm.thsnapshotcreate(self.vg.name, self.origin.lvname, self._name, pool_name=pool_name)
def _postCreate(self):
From: David Lehman dlehman@redhat.com
Related: rhbz#1113207 --- blivet/osinstall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/blivet/osinstall.py b/blivet/osinstall.py index 1c63302..20b425c 100644 --- a/blivet/osinstall.py +++ b/blivet/osinstall.py @@ -605,7 +605,7 @@ def umountFilesystems(self, swapoff=True): devices = list(self.mountpoints.values()) + self.swapDevices devices.extend([self.dev, self.devshm, self.devpts, self.sysfs, self.proc, self.usb, self.selinux, self.run]) - devices.sort(key=lambda d: getattr(d.format, "mountpoint", None)) + devices.sort(key=lambda d: getattr(d.format, "mountpoint", "")) devices.reverse() for device in devices: if (not device.format.mountable) or \
anaconda-patches@lists.fedorahosted.org