From 53187795838ccee4b470f3a08aeaf6e474975408 Mon Sep 17 00:00:00 2001 From: Venky Shankar Date: Mon, 2 Dec 2019 01:56:25 -0500 Subject: [PATCH] mgr/volumes: module to track pending clone operations Signed-off-by: Venky Shankar --- src/pybind/mgr/volumes/fs/exception.py | 8 +++ .../mgr/volumes/fs/operations/clone_index.py | 62 +++++++++++++++++++ src/pybind/mgr/volumes/fs/operations/index.py | 21 +++++++ .../fs/operations/versions/subvolume_base.py | 2 +- .../fs/operations/versions/subvolume_v1.py | 2 +- 5 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/pybind/mgr/volumes/fs/operations/clone_index.py create mode 100644 src/pybind/mgr/volumes/fs/operations/index.py diff --git a/src/pybind/mgr/volumes/fs/exception.py b/src/pybind/mgr/volumes/fs/exception.py index 4493141d0a0..841b35202ee 100644 --- a/src/pybind/mgr/volumes/fs/exception.py +++ b/src/pybind/mgr/volumes/fs/exception.py @@ -17,6 +17,14 @@ class MetadataMgrException(Exception): def __str__(self): return "{0} ({1})".format(self.errno, self.error_str) +class IndexException(Exception): + def __init__(self, error_code, error_message): + self.errno = error_code + self.error_str = error_message + + def __str__(self): + return "{0} ({1})".format(self.errno, self.error_str) + class OpSmException(Exception): def __init__(self, error_code, error_message): self.errno = error_code diff --git a/src/pybind/mgr/volumes/fs/operations/clone_index.py b/src/pybind/mgr/volumes/fs/operations/clone_index.py new file mode 100644 index 00000000000..2e25af1763f --- /dev/null +++ b/src/pybind/mgr/volumes/fs/operations/clone_index.py @@ -0,0 +1,62 @@ +import os +import uuid +import stat +import errno +import logging +from contextlib import contextmanager + +import cephfs + +from .index import Index +from ..exception import IndexException, VolumeException + +log = logging.getLogger(__name__) + +class CloneIndex(Index): + SUB_GROUP_NAME = "clone" + + @property + def path(self): + return os.path.join(super(CloneIndex, self).path, CloneIndex.SUB_GROUP_NAME.encode('utf-8')) + + def _track(self, sink_path): + tracking_id = str(uuid.uuid4()) + source_path = os.path.join(self.path, tracking_id.encode('utf-8')) + log.info("tracking-id {0} for path {1}".format(tracking_id, sink_path)) + + self.fs.symlink(sink_path, source_path) + return tracking_id + + def track(self, sink_path): + try: + return self._track(sink_path) + except (VolumeException, cephfs.Error) as e: + if isinstance(e, cephfs.Error): + e = IndexException(-e.args[0], e.args[1]) + elif isinstance(VolumeException, e): + e = IndexException(e.errno, e.error_str) + raise e + + def untrack(self, tracking_id): + log.info("untracking {0}".format(tracking_id)) + source_path = os.path.join(self.path, tracking_id.encode('utf-8')) + try: + self.fs.unlink(source_path) + except cephfs.Error as e: + raise IndexException(-e.args[0], e.args[1]) + +def create_clone_index(fs, vol_spec): + clone_index = CloneIndex(fs, vol_spec) + try: + fs.mkdirs(clone_index.path, 0o700) + except cephfs.Error as e: + raise IndexException(-e.args[0], e.args[1]) + +@contextmanager +def open_clone_index(fs, vol_spec): + clone_index = CloneIndex(fs, vol_spec) + try: + fs.stat(clone_index.path) + except cephfs.Error as e: + raise IndexException(-e.args[0], e.args[1]) + yield clone_index diff --git a/src/pybind/mgr/volumes/fs/operations/index.py b/src/pybind/mgr/volumes/fs/operations/index.py new file mode 100644 index 00000000000..783564c067b --- /dev/null +++ b/src/pybind/mgr/volumes/fs/operations/index.py @@ -0,0 +1,21 @@ +import os + +from .template import GroupTemplate + +class Index(GroupTemplate): + GROUP_NAME = "_index" + + def __init__(self, fs, vol_spec): + self.fs = fs + self.vol_spec = vol_spec + self.groupname = Index.GROUP_NAME + + @property + def path(self): + return os.path.join(self.vol_spec.base_dir.encode('utf-8'), self.groupname.encode('utf-8')) + + def track(self, *args): + raise VolumeException(-errno.EINVAL, "operation not supported.") + + def untrack(self, tracking_id): + raise VolumeException(-errno.EINVAL, "operation not supported.") diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py index d1db4baca0b..d6d91f410f6 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py @@ -63,7 +63,7 @@ class SubvolumeBase(object): else: self.metadata_mgr = MetadataManager(self.fs, self.config_path, 0o640) - def _set_attrs(self, path, size, isolate_namespace, pool, mode, uid, gid): + def _set_attrs(self, path, size, isolate_namespace, pool, uid, gid): # set size if size is not None: try: diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py index 762ea4a47a8..45947eb5743 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py @@ -40,7 +40,7 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate): try: # create directory and set attributes self.fs.mkdirs(subvol_path, mode) - self._set_attrs(subvol_path, size, isolate_nspace, pool, mode, uid, gid) + self._set_attrs(subvol_path, size, isolate_nspace, pool, uid, gid) # persist subvolume metadata qpath = subvol_path.decode('utf-8') -- 2.39.5