]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: remove stale subvolume module
authorVenky Shankar <vshankar@redhat.com>
Wed, 15 Jan 2020 04:46:09 +0000 (23:46 -0500)
committerRamana Raja <rraja@redhat.com>
Wed, 12 Feb 2020 10:11:59 +0000 (05:11 -0500)
this was lying around post versioning changes.

Signed-off-by: Venky Shankar <vshankar@redhat.com>
(cherry picked from commit 5595476af7fe4dc2dfdeae17d5507d1d8eeeb3f5)

src/pybind/mgr/volumes/fs/subvolume.py [deleted file]

diff --git a/src/pybind/mgr/volumes/fs/subvolume.py b/src/pybind/mgr/volumes/fs/subvolume.py
deleted file mode 100644 (file)
index 6b88da2..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-"""
-Copyright (C) 2019 Red Hat, Inc.
-
-LGPL2.1.  See file COPYING.
-"""
-
-import logging
-import os
-import errno
-
-import cephfs
-
-from .subvolspec import SubvolumeSpec
-from .exception import VolumeException
-
-log = logging.getLogger(__name__)
-
-class SubVolume(object):
-    """
-    Combine libcephfs and librados interfaces to implement a
-    'Subvolume' concept implemented as a cephfs directory.
-
-    Additionally, subvolumes may be in a 'Group'.  Conveniently,
-    subvolumes are a lot like manila shares, and groups are a lot
-    like manila consistency groups.
-
-    Refer to subvolumes with SubvolumePath, which specifies the
-    subvolume and group IDs (both strings).  The group ID may
-    be None.
-
-    In general, functions in this class are allowed raise rados.Error
-    or cephfs.Error exceptions in unexpected situations.
-    """
-
-
-    def __init__(self, mgr, fs_handle):
-        self.fs = fs_handle
-        self.rados = mgr.rados
-
-    def _get_single_dir_entry(self, dir_path, exclude=[]):
-        """
-        Return a directory entry in a given directory excluding passed
-        in entries.
-        """
-        exclude.extend((b".", b".."))
-        try:
-            with self.fs.opendir(dir_path) as d:
-                entry = self.fs.readdir(d)
-                while entry:
-                    if entry.d_name not in exclude and entry.is_dir():
-                        return entry.d_name
-                    entry = self.fs.readdir(d)
-            return None
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-
-
-    ### basic subvolume operations
-
-    def create_subvolume(self, spec, size=None,  pool=None, namespace_isolated=True,
-                         uid=None, gid=None, mode=0o755):
-        """
-        Set up metadata, pools and auth for a subvolume.
-
-        This function is idempotent.  It is safe to call this again
-        for an already-created subvolume, even if it is in use.
-
-        :param spec: subvolume path specification
-        :param size: In bytes, or None for no size limit
-        :param pool: the RADOS pool where the data objects of the subvolumes will be stored
-        :param namespace_isolated: If true, use separate RADOS namespace for this subvolume
-        :param uid: the user identifier
-        :param gid: the group identifier
-        :mode: the user permissions
-        :return: None
-        """
-        subvolpath = spec.subvolume_path
-        log.info("creating subvolume with path: {0}".format(subvolpath))
-
-        self.fs.mkdirs(subvolpath, mode)
-
-        try:
-            if size is not None:
-                try:
-                    self.fs.setxattr(subvolpath, 'ceph.quota.max_bytes', str(size).encode('utf-8'), 0)
-                except cephfs.InvalidValue as e:
-                    raise VolumeException(-errno.EINVAL, "Invalid size: '{0}'".format(size))
-            if pool:
-                try:
-                    self.fs.setxattr(subvolpath, 'ceph.dir.layout.pool', pool.encode('utf-8'), 0)
-                except cephfs.InvalidValue:
-                    raise VolumeException(-errno.EINVAL,
-                                          "Invalid pool layout '{0}'. It must be a valid data pool".format(pool))
-
-            xattr_key = xattr_val = None
-            if namespace_isolated:
-                # enforce security isolation, use separate namespace for this subvolume
-                xattr_key = 'ceph.dir.layout.pool_namespace'
-                xattr_val = spec.fs_namespace
-            elif not pool:
-                # If subvolume's namespace layout is not set, then the subvolume's pool
-                # layout remains unset and will undesirably change with ancestor's
-                # pool layout changes.
-                xattr_key = 'ceph.dir.layout.pool'
-                xattr_val = self._get_ancestor_xattr(subvolpath, "ceph.dir.layout.pool")
-            # TODO: handle error...
-            self.fs.setxattr(subvolpath, xattr_key, xattr_val.encode('utf-8'), 0)
-
-            groupstat = self.fs.stat(spec.group_path)
-            if uid is None:
-                uid = int(groupstat.st_uid)
-            else:
-                try:
-                    uid = int(uid)
-                    if uid < 0:
-                        raise ValueError
-                except ValueError:
-                    raise VolumeException(-errno.EINVAL, "Invalid uid")
-
-            if gid is None:
-                gid = int(groupstat.st_gid)
-            else:
-                try:
-                    gid = int(gid)
-                    if gid < 0:
-                        raise ValueError
-                except ValueError:
-                    raise VolumeException(-errno.EINVAL, "Invalid gid")
-
-            try:
-                self.fs.chown(subvolpath, uid, gid)
-            except cephfs.InvalidValue:
-                raise VolumeException(-e.args[0], e.args[1])
-
-        except Exception as e:
-            try:
-                # cleanup subvol path on best effort basis
-                log.debug("cleaning up subvolume with path: {0}".format(subvolpath))
-                self.fs.rmdir(subvolpath)
-            except Exception:
-                log.debug("failed to clean up subvolume with path: {0}".format(subvolpath))
-                pass
-            finally:
-                raise e
-
-    def remove_subvolume(self, spec, force):
-        """
-        Make a subvolume inaccessible to guests.  This function is idempotent.
-        This is the fast part of tearing down a subvolume. The subvolume will
-        get purged in the background.
-
-        :param spec: subvolume path specification
-        :param force: flag to ignore non-existent path (never raise exception)
-        :return: None
-        """
-
-        subvolpath = spec.subvolume_path
-        log.info("deleting subvolume with path: {0}".format(subvolpath))
-
-        # Create the trash directory if it doesn't already exist
-        trashdir = spec.trash_dir
-        self.fs.mkdirs(trashdir, 0o700)
-
-        # mangle the trash directroy entry to a random string so that subsequent
-        # subvolume create and delete with same name moves the subvolume directory
-        # to a unique trash dir (else, rename() could fail if the trash dir exist).
-        trashpath = spec.unique_trash_path
-        try:
-            self.fs.rename(subvolpath, trashpath)
-        except cephfs.ObjectNotFound:
-            if not force:
-                raise VolumeException(
-                    -errno.ENOENT, "Subvolume '{0}' not found, cannot remove it".format(spec.subvolume_id))
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-
-    def resize_subvolume(self, subvolpath, newsize, noshrink):
-        """
-        :param subvolpath: subvolume path
-        :param newsize: new size In bytes
-        :return: new quota size and used bytes as a tuple
-        """
-        if newsize <= 0:
-            raise VolumeException(-errno.EINVAL, "Provide a valid size")
-
-        try:
-            maxbytes = int(self.fs.getxattr(subvolpath, 'ceph.quota.max_bytes').decode('utf-8'))
-        except cephfs.NoData:
-            maxbytes = 0
-
-        subvolstat = self.fs.stat(subvolpath)
-        if newsize > 0 and newsize < subvolstat.st_size:
-            if noshrink:
-                raise VolumeException(-errno.EINVAL, "Can't resize the subvolume. The new size '{0}' would be lesser than the current "
-                                      "used size '{1}'".format(newsize, subvolstat.st_size))
-
-        if newsize == maxbytes:
-            return newsize, subvolstat.st_size
-
-        try:
-            self.fs.setxattr(subvolpath, 'ceph.quota.max_bytes', str(newsize).encode('utf-8'), 0)
-        except Exception as e:
-            raise VolumeException(-e.args[0], "Cannot set new size for the subvolume. '{0}'".format(e.args[1]))
-        return newsize, subvolstat.st_size
-
-    def resize_infinite(self, subvolpath, newsize):
-        """
-        :param subvolpath: the subvolume path
-        :param newsize: the string inf
-        :return: new quota size and used bytes as a tuple
-        """
-
-        if not (newsize == "inf" or newsize == "infinite"):
-            raise VolumeException(-errno.EINVAL, "Invalid parameter '{0}'".format(newsize))
-
-        subvolstat = self.fs.stat(subvolpath)
-        size = 0
-        try:
-            self.fs.setxattr(subvolpath, 'ceph.quota.max_bytes', str(size).encode('utf-8'), 0)
-        except Exception as e:
-            raise VolumeException(-errno.ENOENT, "Cannot resize the subvolume to infinite size. '{0}'".format(e.args[1]))
-        return size, subvolstat.st_size
-
-    def purge_subvolume(self, spec, should_cancel):
-        """
-        Finish clearing up a subvolume from the trash directory.
-        """
-
-        def rmtree(root_path):
-            log.debug("rmtree {0}".format(root_path))
-            try:
-                with self.fs.opendir(root_path) as dir_handle:
-                    d = self.fs.readdir(dir_handle)
-                    while d and not should_cancel():
-                        if d.d_name not in (b".", b".."):
-                            d_full = os.path.join(root_path, d.d_name)
-                            if d.is_dir():
-                                rmtree(d_full)
-                            else:
-                                self.fs.unlink(d_full)
-                        d = self.fs.readdir(dir_handle)
-            except cephfs.ObjectNotFound:
-                return
-            except cephfs.Error as e:
-                raise VolumeException(-e.args[0], e.args[1])
-            # remove the directory only if we were not asked to cancel
-            # (else we would fail to remove this anyway)
-            if not should_cancel():
-                self.fs.rmdir(root_path)
-
-        trashpath = spec.trash_path
-        # catch any unlink errors
-        try:
-            rmtree(trashpath)
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-
-    def get_subvolume_path(self, spec):
-        path = spec.subvolume_path
-        try:
-            self.fs.stat(path)
-        except cephfs.ObjectNotFound:
-            return None
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-        return path
-
-    def get_dir_entries(self, path):
-        """
-        Get the directory names in a given path
-        :param path: the given path
-        :return: the list of directory names
-        """
-        dirs = []
-        try:
-            with self.fs.opendir(path) as dir_handle:
-                d = self.fs.readdir(dir_handle)
-                while d:
-                    if (d.d_name not in (b".", b"..")) and d.is_dir():
-                        dirs.append(d.d_name)
-                    d = self.fs.readdir(dir_handle)
-        except cephfs.ObjectNotFound:
-            # When the given path is not found, we just return an empty list
-            return []
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-        return dirs
-
-    ### group operations
-
-    def create_group(self, spec, pool=None, uid=None, gid=None, mode=0o755):
-        """
-        Create a subvolume group.
-
-        :param spec: subvolume path specification
-        :param pool: the RADOS pool where the data objects of the subvolumes will be stored
-        :param uid: the user identifier
-        :param gid: the group identifier
-        :mode: the user permissions
-        :return: None
-        """
-        path = spec.group_path
-        self.fs.mkdirs(path, mode)
-        try:
-            if not pool:
-                pool = self._get_ancestor_xattr(path, "ceph.dir.layout.pool")
-            try:
-                self.fs.setxattr(path, 'ceph.dir.layout.pool', pool.encode('utf-8'), 0)
-            except cephfs.InvalidValue:
-                raise VolumeException(-errno.EINVAL,
-                                      "Invalid pool layout '{0}'. It must be a valid data pool".format(pool))
-
-            if uid is None:
-                uid = 0
-            else:
-                try:
-                    uid = int(uid)
-                    if uid < 0:
-                        raise ValueError
-                except ValueError:
-                    raise VolumeException(-errno.EINVAL, "Invalid uid")
-
-            if gid is None:
-                gid = 0
-            else:
-                try:
-                    gid = int(gid)
-                    if gid < 0:
-                        raise ValueError
-                except ValueError:
-                    raise VolumeException(-errno.EINVAL, "Invalid gid")
-
-            try:
-                self.fs.chown(path, uid, gid)
-            except cephfs.InvalidValue:
-                raise VolumeException(-e.args[0], e.args[1])
-
-        except Exception as e:
-            try:
-                # cleanup group path on best effort basis
-                log.debug("cleaning up subvolumegroup with path: {0}".format(path))
-                self.fs.rmdir(path)
-            except Exception:
-                log.debug("failed to clean up subvolumegroup with path: {0}".format(path))
-                pass
-            finally:
-                raise e
-
-    def remove_group(self, spec, force):
-        path = spec.group_path
-        try:
-            self.fs.rmdir(path)
-        except cephfs.ObjectNotFound:
-            if not force:
-                raise VolumeException(-errno.ENOENT, "Subvolume group '{0}' not found".format(spec.group_id))
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-
-    def get_group_path(self, spec):
-        path = spec.group_path
-        try:
-            self.fs.stat(path)
-        except cephfs.ObjectNotFound:
-            return None
-        return path
-
-    def _get_ancestor_xattr(self, path, attr):
-        """
-        Helper for reading layout information: if this xattr is missing
-        on the requested path, keep checking parents until we find it.
-        """
-        try:
-            return self.fs.getxattr(path, attr).decode('utf-8')
-        except cephfs.NoData:
-            if path == "/":
-                raise
-            else:
-                return self._get_ancestor_xattr(os.path.split(path)[0], attr)
-
-    ### snapshot operations
-
-    def _snapshot_create(self, snappath, mode=0o755):
-        """
-        Create a snapshot, or do nothing if it already exists.
-        """
-        try:
-            self.fs.stat(snappath)
-        except cephfs.ObjectNotFound:
-            self.fs.mkdir(snappath, mode)
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-        else:
-            log.warn("Snapshot '{0}' already exists".format(snappath))
-
-    def _snapshot_delete(self, snappath, force):
-        """
-        Remove a snapshot, or do nothing if it doesn't exist.
-        """
-        try:
-            self.fs.stat(snappath)
-            self.fs.rmdir(snappath)
-        except cephfs.ObjectNotFound:
-            if not force:
-                raise VolumeException(-errno.ENOENT, "Snapshot '{0}' not found, cannot remove it".format(snappath))
-        except cephfs.Error as e:
-            raise VolumeException(-e.args[0], e.args[1])
-
-    def create_subvolume_snapshot(self, spec, snapname, mode=0o755):
-        snappath = spec.make_subvol_snap_path(self.rados.conf_get('client_snapdir'), snapname)
-        self._snapshot_create(snappath, mode)
-
-    def remove_subvolume_snapshot(self, spec, snapname, force):
-        snappath = spec.make_subvol_snap_path(self.rados.conf_get('client_snapdir'), snapname)
-        self._snapshot_delete(snappath, force)
-
-    def create_group_snapshot(self, spec, snapname, mode=0o755):
-        snappath = spec.make_group_snap_path(self.rados.conf_get('client_snapdir'), snapname)
-        self._snapshot_create(snappath, mode)
-
-    def remove_group_snapshot(self, spec, snapname, force):
-        snappath = spec.make_group_snap_path(self.rados.conf_get('client_snapdir'), snapname)
-        return self._snapshot_delete(snappath, force)
-
-    def get_trash_entry(self, spec, exclude):
-        try:
-            trashdir = spec.trash_dir
-            return self._get_single_dir_entry(trashdir, exclude)
-        except VolumeException as ve:
-            if ve.errno == -errno.ENOENT:
-                # trash dir does not exist yet, signal success
-                return None
-            raise
-
-    ### context manager routines
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        pass