LGPL2.1. See file COPYING.
"""
-import errno
import logging
import os
import cephfs
-import rados
+from .subvolspec import SubvolumeSpec
log = logging.getLogger(__name__)
-# Reserved subvolume group name which we use in paths for subvolumes
-# that are not assigned to a group (i.e. created with group=None)
-NO_GROUP_NAME = "_nogroup"
-
-
-class SubvolumePath(object):
- """
- Identify a subvolume's path as group->subvolume
- The Subvolume ID is a unique identifier, but this is a much more
- helpful thing to pass around.
- """
- def __init__(self, group_id, subvolume_id):
- self.group_id = group_id
- self.subvolume_id = subvolume_id
- assert self.group_id != NO_GROUP_NAME
- assert self.subvolume_id != "" and self.subvolume_id is not None
-
- def __str__(self):
- return "{0}/{1}".format(self.group_id, self.subvolume_id)
-
-
-class SubvolumeClient(object):
+class SubVolume(object):
"""
Combine libcephfs and librados interfaces to implement a
'Subvolume' concept implemented as a cephfs directory.
or cephfs.Error exceptions in unexpected situations.
"""
- # Where shall we create our subvolumes?
- DEFAULT_SUBVOL_PREFIX = "/volumes"
- DEFAULT_NS_PREFIX = "fsvolumens_"
- def __init__(self, mgr, subvolume_prefix=None, pool_ns_prefix=None, fs_name=None):
+ def __init__(self, mgr, fs_name=None):
self.fs = None
self.fs_name = fs_name
self.connected = False
self.rados = mgr.rados
- self.subvolume_prefix = subvolume_prefix if subvolume_prefix else self.DEFAULT_SUBVOL_PREFIX
- self.pool_ns_prefix = pool_ns_prefix if pool_ns_prefix else self.DEFAULT_NS_PREFIX
-
- def _subvolume_path(self, subvolume_path):
- """
- Determine the path within CephFS where this subvolume will live
- :return: absolute path (string)
- """
- return os.path.join(
- self.subvolume_prefix,
- subvolume_path.group_id if subvolume_path.group_id is not None else NO_GROUP_NAME,
- subvolume_path.subvolume_id)
-
- def _group_path(self, group_id):
- """
- Determine the path within CephFS where this subvolume group will live
- :return: absolute path (string)
- """
- if group_id is None:
- raise ValueError("group_id may not be None")
-
- return os.path.join(
- self.subvolume_prefix,
- group_id
- )
-
- def connect(self):
- log.debug("Connecting to cephfs...")
- self.fs = cephfs.LibCephFS(rados_inst=self.rados)
- log.debug("CephFS initializing...")
- self.fs.init()
- log.debug("CephFS mounting...")
- self.fs.mount(filesystem_name=self.fs_name.encode('utf-8'))
- log.debug("Connection to cephfs complete")
-
- def disconnect(self):
- log.info("disconnect")
- if self.fs:
- log.debug("Disconnecting cephfs...")
- self.fs.shutdown()
- self.fs = None
- log.debug("Disconnecting cephfs complete")
-
- def __enter__(self):
- self.connect()
- return self
-
- def __exit__(self, exc_type, exc_val, exc_tb):
- self.disconnect()
-
- def __del__(self):
- self.disconnect()
-
def _mkdir_p(self, path, mode=0o755):
try:
self.fs.stat(path)
except cephfs.ObjectNotFound:
self.fs.mkdir(subpath, mode)
- def create_group(self, group_id, mode=0o755):
- path = self._group_path(group_id)
- self._mkdir_p(path, mode)
+ ### basic subvolume operations
- def delete_group(self, group_id):
- path = self._group_path(group_id)
- self.fs.rmdir(path)
-
- def create_subvolume(self, subvolume_path, size=None, namespace_isolated=True, mode=0o755):
+ def create_subvolume(self, spec, size=None, namespace_isolated=True, 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 subvolume_path: SubvolumePath instance
+ :param spec: subvolume path specification
:param size: In bytes, or None for no size limit
:param namespace_isolated: If true, use separate RADOS namespace for this subvolume
:return: None
"""
- path = self._subvolume_path(subvolume_path)
- log.info("creating subvolume with path: {0}".format(path))
+ subvolpath = spec.subvolume_path
+ log.info("creating subvolume with path: {0}".format(subvolpath))
- self._mkdir_p(path, mode)
+ self._mkdir_p(subvolpath, mode)
if size is not None:
- self.fs.setxattr(path, 'ceph.quota.max_bytes', str(size).encode('utf-8'), 0)
+ self.fs.setxattr(subvolpath, 'ceph.quota.max_bytes', str(size).encode('utf-8'), 0)
- # enforce security isolation, use separate namespace for this subvolume
+ xattr_key = xattr_val = None
if namespace_isolated:
- namespace = "{0}{1}".format(self.pool_ns_prefix, subvolume_path.subvolume_id)
- log.info("creating subvolume with path: {0}, using rados namespace {1} to isolate data.".format(subvolume_path, namespace))
- self.fs.setxattr(path, 'ceph.dir.layout.pool_namespace',
- namespace.encode('utf-8'), 0)
+ # enforce security isolation, use separate namespace for this subvolume
+ xattr_key = 'ceph.dir.layout.pool_namespace'
+ xattr_val = spec.fs_namespace
else:
# 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.
- pool_name = self._get_ancestor_xattr(path, "ceph.dir.layout.pool")
- self.fs.setxattr(path, 'ceph.dir.layout.pool',
- pool_name.encode('utf-8'), 0)
+ 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)
- def delete_subvolume(self, subvolume_path):
+ def remove_subvolume(self, spec):
"""
Make a subvolume inaccessible to guests. This function is idempotent.
This is the fast part of tearing down a subvolume: you must also later
call purge_subvolume, which is the slow part.
- :param subvolume_path: Same identifier used in create_subvolume
+ :param spec: subvolume path specification
:return: None
"""
- path = self._subvolume_path(subvolume_path)
- log.info("deleting subvolume with path: {0}".format(path))
-
- # Create the trash folder if it doesn't already exist
- trash = os.path.join(self.subvolume_prefix, "_deleting")
- self._mkdir_p(trash)
+ subvolpath = spec.subvolume_path
+ log.info("deleting subvolume with path: {0}".format(subvolpath))
- # We'll move it to here
- trashed_subvolume = os.path.join(trash, subvolume_path.subvolume_id)
+ # Create the trash directory if it doesn't already exist
+ trashdir = spec.trash_dir
+ self._mkdir_p(trashdir)
- # Move the subvolume to the trash folder
- self.fs.rename(path, trashed_subvolume)
+ trashpath = spec.trash_path
+ self.fs.rename(subvolpath, trashpath)
- def purge_subvolume(self, subvolume_path):
+ def purge_subvolume(self, spec):
"""
Finish clearing up a subvolume that was previously passed to delete_subvolume. This
function is idempotent.
"""
- trash = os.path.join(self.subvolume_prefix, "_deleting")
- trashed_subvolume = os.path.join(trash, subvolume_path.subvolume_id)
-
def rmtree(root_path):
log.debug("rmtree {0}".format(root_path))
try:
d = self.fs.readdir(dir_handle)
self.fs.closedir(dir_handle)
-
self.fs.rmdir(root_path)
- rmtree(trashed_subvolume)
+ trashpath = spec.trash_path
+ rmtree(trashpath)
+
+ def get_subvolume_path(self, spec):
+ path = spec.subvolume_path
+ try:
+ self.fs.stat(path)
+ except cephfs.ObjectNotFound:
+ return None
+ return path
+
+ ### group operations
+
+ def create_group(self, spec, mode=0o755):
+ path = spec.group_path
+ self._mkdir_p(path, mode)
+
+ def remove_group(self, spec):
+ path = spec.group_path
+ self.fs.rmdir(path)
+ 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):
"""
else:
return self._get_ancestor_xattr(os.path.split(path)[0], attr)
- def get_group_path(self, group_id):
- path = self._group_path(group_id)
- try:
- self.fs.stat(path)
- except cephfs.ObjectNotFound:
- return None
- return path
+ ### snapshot operations
- def get_subvolume_path(self, subvolume_path):
- path = self._subvolume_path(subvolume_path)
- try:
- self.fs.stat(path)
- except cephfs.ObjectNotFound:
- return None
- return path
-
- def _snapshot_path(self, dir_path, snapshot_name):
- return os.path.join(
- dir_path, self.rados.conf_get('client_snapdir'), snapshot_name
- )
-
- def _snapshot_create(self, dir_path, snapshot_name, mode=0o755):
+ def _snapshot_create(self, snappath, mode=0o755):
"""
Create a snapshot, or do nothing if it already exists.
"""
- snapshot_path = self._snapshot_path(dir_path, snapshot_name)
try:
- self.fs.stat(snapshot_path)
+ self.fs.stat(snappath)
except cephfs.ObjectNotFound:
- self.fs.mkdir(snapshot_path, mode)
+ self.fs.mkdir(snappath, mode)
else:
- log.warn("Snapshot '{0}' already exists".format(snapshot_name))
+ log.warn("Snapshot '{0}' already exists".format(snappath))
-
- def _snapshot_delete(self, dir_path, snapshot_name):
+ def _snapshot_delete(self, snappath):
"""
Remove a snapshot, or do nothing if it doesn't exist.
"""
- snapshot_path = self._snapshot_path(dir_path, snapshot_name)
- self.fs.stat(snapshot_path)
- self.fs.rmdir(snapshot_path)
+ self.fs.stat(snappath)
+ self.fs.rmdir(snappath)
+
+ 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):
+ snappath = spec.make_subvol_snap_path(self.rados.conf_get('client_snapdir'), snapname)
+ self._snapshot_delete(snappath)
- def create_subvolume_snapshot(self, subvolume_path, snapshot_name, mode=0o755):
- return self._snapshot_create(self._subvolume_path(subvolume_path), snapshot_name, mode)
+ 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 delete_subvolume_snapshot(self, subvolume_path, snapshot_name):
- return self._snapshot_delete(self._subvolume_path(subvolume_path), snapshot_name)
+ def remove_group_snapshot(self, spec, snapname):
+ snappath = spec.make_group_snap_path(self.rados.conf_get('client_snapdir'), snapname)
+ return self._snapshot_delete(snappath)
- def create_group_snapshot(self, group_id, snapshot_name, mode=0o755):
- return self._snapshot_create(self._group_path(group_id), snapshot_name, mode)
+ ### context manager routines
- def delete_group_snapshot(self, group_id, snapshot_name):
- return self._snapshot_delete(self._group_path(group_id), snapshot_name)
+ def connect(self):
+ log.debug("Connecting to cephfs...")
+ self.fs = cephfs.LibCephFS(rados_inst=self.rados)
+ log.debug("CephFS initializing...")
+ self.fs.init()
+ log.debug("CephFS mounting...")
+ self.fs.mount(filesystem_name=self.fs_name.encode('utf-8'))
+ log.debug("Connection to cephfs complete")
+
+ def disconnect(self):
+ log.info("disconnect")
+ if self.fs:
+ log.debug("Disconnecting cephfs...")
+ self.fs.shutdown()
+ self.fs = None
+ log.debug("Disconnecting cephfs complete")
+
+ def __enter__(self):
+ self.connect()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.disconnect()
+
+ def __del__(self):
+ self.disconnect()
import errno
import logging
+import cephfs
import orchestrator
+from .subvolspec import SubvolumeSpec
+from .subvolume import SubVolume
+
log = logging.getLogger(__name__)
class VolumeClient(object):
for f in fs_map['filesystems']:
result.append({'name': f['mdsmap']['fs_name']})
return 0, json.dumps(result, indent=2), ""
+
+ def group_exists(self, sv, spec):
+ # default group need not be explicitly created (as it gets created
+ # at the time of subvolume, snapshot and other create operations).
+ return spec.is_default_group() or sv.get_group_path(spec)
+
+ ### subvolume operations
+
+ def create_subvolume(self, volname, subvolname, groupname, size):
+ if not self.volume_exists(volname):
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, create it with `ceph fs volume create` " \
+ "before trying to create subvolumes".format(volname)
+
+ # TODO: validate that subvol size fits in volume size
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec(subvolname, groupname)
+ if not self.group_exists(sv, spec):
+ return -errno.ENOENT, "", \
+ "Subvolume group '{0}' not found, create it with `ceph fs subvolumegroup create` " \
+ "before creating subvolumes".format(groupname)
+ return sv.create_subvolume(spec, size)
+
+ def remove_subvolume(self, volname, subvolname, groupname, force):
+ fs = self.get_fs(volname)
+ if not fs:
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, cannot remove subvolume '{1}'".format(volname, subvolname)
+
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec(subvolname, groupname)
+ if not self.group_exists(sv, spec):
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume group '{0}' not found, cannot remove subvolume '{1}'".format(groupname, subvolname)
+ try:
+ sv.remove_subvolume(spec)
+ except cephfs.ObjectNotFound:
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume '{0}' not found, cannot remove it".format(subvolname)
+ sv.purge_subvolume(spec)
+ return 0, "", ""
+
+ def subvolume_getpath(self, volname, subvolname, groupname):
+ if not self.volume_exists(volname):
+ return -errno.ENOENT, "", "Volume '{0}' not found".format(volname)
+
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec(subvolname, groupname)
+ if not self.group_exists(sv, spec):
+ return -errno.ENOENT, "", "Subvolume group '{0}' not found".format(groupname)
+ path = sv.get_subvolume_path(spec)
+ if not path:
+ return -errno.ENOENT, "", "Subvolume '{0}' not found".format(groupname)
+ return 0, path, ""
+
+ ### subvolume snapshot
+
+ def create_subvolume_snapshot(self, volname, subvolname, snapname, groupname):
+ if not self.volume_exists(volname):
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, cannot create snapshot '{1}'".format(volname, snapname)
+
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec(subvolname, groupname)
+ if not self.group_exists(sv, spec):
+ return -errno.ENOENT, "", \
+ "Subvolume group '{0}' not found, cannot create snapshot '{1}'".format(groupname, snapname)
+ if not sv.get_subvolume_path(spec):
+ return -errno.ENOENT, "", \
+ "Subvolume '{0}' not found, cannot create snapshot '{1}'".format(subvolname, snapname)
+ sv.create_subvolume_snapshot(spec, snapname)
+ return 0, "", ""
+
+ def remove_subvolume_snapshot(self, volname, subvolname, snapname, groupname, force):
+ if not self.volume_exists(volname):
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, cannot remove subvolumegroup snapshot '{1}'".format(volname, snapname)
+
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec(subvolname, groupname)
+ if not self.group_exists(sv, spec):
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume group '{0}' already removed, cannot remove subvolume snapshot '{1}'".format(groupname, snapname)
+ if not sv.get_subvolume_path(spec):
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume '{0}' not found, cannot remove subvolume snapshot '{1}'".format(subvolname, snapname)
+ try:
+ sv.remove_subvolume_snapshot(spec, snapname)
+ except cephfs.ObjectNotFound:
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume snapshot '{0}' not found, cannot remove it".format(snapname)
+ return 0, "", ""
+
+ ### group operations
+
+ def create_subvolume_group(self, volname, groupname):
+ if not self.volume_exists(volname):
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, create it with `ceph fs volume create` " \
+ "before trying to create subvolume groups".format(volname)
+
+ # TODO: validate that subvol size fits in volume size
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec("", groupname)
+ sv.create_group(spec)
+ return 0, "", ""
+
+ def remove_subvolume_group(self, volname, groupname, force):
+ if not self.volume_exists(volname):
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, cannot remove subvolume group '{0}'".format(volname, groupname)
+
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ # TODO: check whether there are no subvolumes in the group
+ spec = SubvolumeSpec("", groupname)
+ try:
+ sv.remove_group(spec)
+ except cephfs.ObjectNotFound:
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume group '{0}' not found".format(groupname)
+ return 0, "", ""
+
+ ### group snapshot
+
+ def create_subvolume_group_snapshot(self, volname, groupname, snapname):
+ if not self.volume_exists(volname):
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, cannot create snapshot '{1}'".format(volname, snapname)
+
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec("", groupname)
+ if not self.group_exists(sv, spec):
+ return -errno.ENOENT, "", \
+ "Subvolume group '{0}' not found, cannot create snapshot '{1}'".format(groupname, snapname)
+ sv.create_group_snapshot(spec, snapname)
+ return 0, "", ""
+
+ def remove_subvolume_group_snapshot(self, volname, groupname, snapname, force):
+ if not self.volume_exists(volname):
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Volume '{0}' not found, cannot remove subvolumegroup snapshot '{1}'".format(volname, snapname)
+
+ with SubVolume(self.mgr, fs_name=volname) as sv:
+ spec = SubvolumeSpec("", groupname)
+ if not self.group_exists(sv, spec):
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume group '{0}' not found, cannot remove it".format(groupname)
+ try:
+ sv.remove_group_snapshot(spec, snapname)
+ except:
+ if force:
+ return 0, "", ""
+ else:
+ return -errno.ENOENT, "", \
+ "Subvolume group snapshot '{0}' not found, cannot remove it".format(snapname)
+ return 0, "", ""
from mgr_module import MgrModule
import orchestrator
-from .fs.subvolume import SubvolumePath, SubvolumeClient
from .fs.volume import VolumeClient
class PurgeJob(object):
self.fscid = volume_fscid
self.subvolume_path = subvolume_path
-
class Module(orchestrator.OrchestratorClientMixin, MgrModule):
COMMANDS = [
{
vol_name = cmd['vol_name']
group_name = cmd['group_name']
- if not self._volume_exists(vol_name):
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, create it with `ceph fs volume create` " \
- "before trying to create subvolume groups".format(vol_name)
-
- # TODO: validate that subvol size fits in volume size
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- svc.create_group(group_name)
-
- return 0, "", ""
+ return self.vc.create_subvolume_group(vol_name, group_name)
def _cmd_fs_subvolumegroup_rm(self, inbuf, cmd):
"""
"""
vol_name = cmd['vol_name']
group_name = cmd['group_name']
-
force = cmd.get('force', False)
- if not self._volume_exists(vol_name):
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, cannot remove subvolume group '{0}'".format(vol_name, group_name)
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- # TODO: check whether there are no subvolumes in the group
- try:
- svc.delete_group(group_name)
- except cephfs.ObjectNotFound:
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found, cannot remove it".format(group_name)
-
-
- return 0, "", ""
+ return self.vc.remove_subvolume_group(vol_name, group_name, force)
def _cmd_fs_subvolume_create(self, inbuf, cmd):
"""
"""
vol_name = cmd['vol_name']
sub_name = cmd['sub_name']
-
size = cmd.get('size', None)
group_name = cmd.get('group_name', None)
- if not self._volume_exists(vol_name):
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, create it with `ceph fs volume create` " \
- "before trying to create subvolumes".format(vol_name)
-
- # TODO: validate that subvol size fits in volume size
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- if group_name and not svc.get_group_path(group_name):
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found, create it with `ceph fs subvolumegroup create` " \
- "before trying to create subvolumes".format(group_name)
- svp = SubvolumePath(group_name, sub_name)
- svc.create_subvolume(svp, size)
-
- return 0, "", ""
+ return self.vc.create_subvolume(vol_name, sub_name, group_name, size)
def _cmd_fs_subvolume_rm(self, inbuf, cmd):
"""
"""
vol_name = cmd['vol_name']
sub_name = cmd['sub_name']
-
force = cmd.get('force', False)
group_name = cmd.get('group_name', None)
- fs = self._volume_get_fs(vol_name)
- if fs is None:
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, cannot remove subvolume '{1}'".format(vol_name, sub_name)
-
- vol_fscid = fs['id']
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- if group_name and not svc.get_group_path(group_name):
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found, cannot remove subvolume '{1}'".format(group_name, sub_name)
- svp = SubvolumePath(group_name, sub_name)
- try:
- svc.delete_subvolume(svp)
- except cephfs.ObjectNotFound:
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume '{0}' not found, cannot remove it".format(sub_name)
- svc.purge_subvolume(svp)
-
- # TODO: purge subvolume asynchronously
- # self._background_jobs.put(PurgeJob(vol_fscid, svp))
-
- return 0, "", ""
+ return self.vc.remove_subvolume(vol_name, sub_name, group_name, force)
def _cmd_fs_subvolume_getpath(self, inbuf, cmd):
vol_name = cmd['vol_name']
sub_name = cmd['sub_name']
-
group_name = cmd.get('group_name', None)
- if not self._volume_exists(vol_name):
- return -errno.ENOENT, "", "Volume '{0}' not found".format(vol_name)
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- if group_name and not svc.get_group_path(group_name):
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found".format(group_name)
- svp = SubvolumePath(group_name, sub_name)
- path = svc.get_subvolume_path(svp)
- if not path:
- return -errno.ENOENT, "", \
- "Subvolume '{0}' not found".format(sub_name)
- return 0, path, ""
+ return self.vc.subvolume_getpath(vol_name, sub_name, group_name)
def _cmd_fs_subvolumegroup_snapshot_create(self, inbuf, cmd):
vol_name = cmd['vol_name']
group_name = cmd['group_name']
snap_name = cmd['snap_name']
- if not self._volume_exists(vol_name):
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, cannot create snapshot '{1}'".format(vol_name, snap_name)
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- if group_name and not svc.get_group_path(group_name):
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found, cannot create snapshot '{1}'".format(group_name, snap_name)
- svc.create_group_snapshot(group_name, snap_name)
-
- return 0, "", ""
+ return self.vc.create_subvolume_group_snapshot(vol_name, group_name, snap_name)
def _cmd_fs_subvolumegroup_snapshot_rm(self, inbuf, cmd):
vol_name = cmd['vol_name']
group_name = cmd['group_name']
snap_name = cmd['snap_name']
-
force = cmd.get('force', False)
- if not self._volume_exists(vol_name):
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, cannot remove subvolumegroup snapshot '{1}'".format(vol_name, snap_name)
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- if group_name and not svc.get_group_path(group_name):
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found, cannot remove subvolumegroup snapshot '{1}'".format(group_name, snap_name)
- try:
- svc.delete_group_snapshot(group_name, snap_name)
- except cephfs.ObjectNotFound:
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume group snapshot '{0}' not found, cannot remove it".format(snap_name)
-
- return 0, "", ""
+ return self.vc.remove_subvolume_group_snapshot(vol_name, group_name, snap_name, force)
def _cmd_fs_subvolume_snapshot_create(self, inbuf, cmd):
vol_name = cmd['vol_name']
sub_name = cmd['sub_name']
snap_name = cmd['snap_name']
-
group_name = cmd.get('group_name', None)
- if not self._volume_exists(vol_name):
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, cannot create snapshot '{1}'".format(vol_name, snap_name)
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- if group_name and not svc.get_group_path(group_name):
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found, cannot create snapshot '{1}'".format(group_name, snap_name)
- svp = SubvolumePath(group_name, sub_name)
- if not svc.get_subvolume_path(svp):
- return -errno.ENOENT, "", \
- "Subvolume '{0}' not found, cannot create snapshot '{1}'".format(sub_name, snap_name)
- svc.create_subvolume_snapshot(svp, snap_name)
-
- return 0, "", ""
+ return self.vc.create_subvolume_snapshot(vol_name, sub_name, snap_name, group_name)
def _cmd_fs_subvolume_snapshot_rm(self, inbuf, cmd):
vol_name = cmd['vol_name']
sub_name = cmd['sub_name']
snap_name = cmd['snap_name']
-
force = cmd.get('force', False)
group_name = cmd.get('group_name', None)
- if not self._volume_exists(vol_name):
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Volume '{0}' not found, cannot remove subvolume snapshot '{1}'".format(vol_name, snap_name)
-
- with SubvolumeClient(self, fs_name=vol_name) as svc:
- if group_name and not svc.get_group_path(group_name):
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume group '{0}' not found, cannot remove subvolume snapshot '{1}'".format(group_name, snap_name)
- svp = SubvolumePath(group_name, sub_name)
- if not svc.get_subvolume_path(svp):
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume '{0}' not found, cannot remove subvolume snapshot '{1}'".format(sub_name, snap_name)
- try:
- svc.delete_subvolume_snapshot(svp, snap_name)
- except cephfs.ObjectNotFound:
- if force:
- return 0, "", ""
- else:
- return -errno.ENOENT, "", \
- "Subvolume snapshot '{0}' not found, cannot remove it".format(snap_name)
-
- return 0, "", ""
+ return self.vc.remove_subvolume_snapshot(vol_name, sub_name, snap_name, group_name, force)