[PATCH 06/17] Add backend functions for creating and managing snapshots.
Anne Mulhern
amulhern at redhat.com
Thu Jun 5 19:42:33 UTC 2014
----- Original Message -----
> From: "David Lehman" <dlehman at redhat.com>
> To: anaconda-patches at lists.fedorahosted.org
> Sent: Thursday, June 5, 2014 12:47:26 PM
> Subject: [PATCH 06/17] Add backend functions for creating and managing snapshots.
>
> ---
> blivet/devicelibs/btrfs.py | 20 +++++++++++++++-----
> blivet/devicelibs/lvm.py | 35 +++++++++++++++++++++++++++++++++++
> 2 files changed, 50 insertions(+), 5 deletions(-)
>
> diff --git a/blivet/devicelibs/btrfs.py b/blivet/devicelibs/btrfs.py
> index 61697ba..e1d08d0 100644
> --- a/blivet/devicelibs/btrfs.py
> +++ b/blivet/devicelibs/btrfs.py
> @@ -107,20 +107,23 @@ def delete_subvolume(mountpoint, name):
> args = ["subvol", "delete", path]
> return btrfs(args)
>
> -_SUBVOL_REGEX_STR = r'ID (\d+) gen \d+ parent (\d+) top level \d+ path
> (.+)\n'
> +_SUBVOL_REGEX_STR = r'ID (?P<id>\d+) gen \d+ (cgen \d+ )?parent
> (?P<parent>\d+) top level \d+ (otime \d{4}-\d{2}-\d{2} \d\d:\d\d:\d\d )?path
> (?P<path>.+)\n'
> _SUBVOL_REGEX = re.compile(_SUBVOL_REGEX_STR)
>
> # get a list of subvolumes from a mounted btrfs filesystem
> -def list_subvolumes(mountpoint):
> +def list_subvolumes(mountpoint, snapshots_only=False):
> if not os.path.ismount(mountpoint):
> raise ValueError("volume not mounted")
>
> args = ["subvol", "list", "-p", mountpoint]
> + if snapshots_only:
> + args.insert(2, "-s")
> +
> buf = btrfs(args, capture=True)
> vols = []
> - for group in _SUBVOL_REGEX.findall(buf):
> - vols.append({"id": int(group[0]), "parent": int(group[1]),
> - "path": group[2]})
> + for m in _SUBVOL_REGEX.finditer(buf):
> + vols.append({"id": int(m.group('id')), "parent":
> int(m.group('parent')),
> + "path": m.group('path')})
>
> return vols
>
> @@ -138,6 +141,13 @@ def get_default_subvolume(mountpoint):
>
> return default
>
> +def create_snapshot(source, dest):
> + if not os.path.ismount(source):
> + raise ValueError("source is not a mounted subvolume")
> +
> + args = ["subvol", "snapshot", source, dest]
> + return btrfs(args)
> +
> _DEVICE_REGEX_STR = r'devid[ \t]+(\d+)[ \t]+size[ \t]+(\S+)[ \t]+used[
> \t]+(\S+)[ \t]+path[ \t]+(\S+)\n'
> _DEVICE_REGEX = re.compile(_DEVICE_REGEX_STR)
>
> diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
> index f2b85ac..a66f4d6 100644
> --- a/blivet/devicelibs/lvm.py
> +++ b/blivet/devicelibs/lvm.py
> @@ -520,6 +520,32 @@ def lvdeactivate(vg_name, lv_name):
> except LVMError as msg:
> raise LVMError("lvdeactivate failed for %s: %s" % (lv_name, msg))
>
> +def lvsnapshotmerge(vg_name, lv_name):
> + """ Merge(/rollback/revert) a snapshot volume into its origin.
> +
> + .. note::
> +
> + This is an asynchronous procedure. See lvconvert(8) for details
> of
> + how merge is handled by lvm.
> +
> + """
> + args = ["lvconvert", "--merge", "%s/%s" % (vg_name, lv_name)]
> + args += _getConfigArgs() + [lv_name]
> +
> + try:
> + lvm(args)
> + except LVMError as msg:
> + raise LVMError("lvsnapshotmerge failed for %s: %s" % (lv_name, msg))
> +
> +def lvsnapshotcreate(vg_name, lv_name, size, origin):
> + args = ["lvcreate", "-s", "-L", "%dm" % size.convertTo(spec="MiB"),
> + "-n", lv_name] + _getConfigArgs() + ["%s/%s" % (vg_name,
> origin)]
> +
> + try:
> + lvm(args)
> + except LVMError as msg:
> + raise LVMError("lvsnapshotcreate failed for %s/%s: %s" % (vg_name,
> lv_name, msg))
> +
> def thinpoolcreate(vg_name, lv_name, size, metadatasize=None,
> chunksize=None):
> args = ["lvcreate", "--thinpool", "%s/%s" % (vg_name, lv_name),
> "--size", "%dm" % size.convertTo(spec="mib")]
> @@ -550,6 +576,15 @@ def thinlvcreate(vg_name, pool_name, lv_name, size):
> except LVMError as msg:
> raise LVMError("lvcreate failed for %s/%s: %s" % (vg_name, lv_name,
> msg))
>
> +def thinsnapshotcreate(vg_name, lv_name, origin_name, pool_name=None):
> + args = ["lvcreate", "-s", "-n", lv_name, "%s/%s" % (vg_name,
> origin_name)]
> + if pool_name:
> + args.extend(["--thinpool", pool_name])
> + try:
> + lvm(args)
> + except LVMError as msg:
> + raise LVMError("lvcreate (snapshot) failed for %s/%s: %s" %
> (vg_name, lv_name, msg))
> +
> def thinlvpoolname(vg_name, lv_name):
> args = ["lvs", "--noheadings", "-o", "pool_lv"] + \
> _getConfigArgs(read_only_locking=True) + \
> --
> 1.9.0
>
> _______________________________________________
> anaconda-patches mailing list
> anaconda-patches at lists.fedorahosted.org
> https://lists.fedorahosted.org/mailman/listinfo/anaconda-patches
>
For the two *snapshotcreate methods, the name for the third parameter
should probably be the same.
It also might be helpful to have a docstring that documents origin_name.
And, I may be wrong, but would 'snap_name' be a better choice than 'lv_name'
for the second parameter of these two?
- mulhern
More information about the anaconda-patches
mailing list