From: Ramana Raja Date: Fri, 19 Apr 2019 16:56:38 +0000 (+0530) Subject: mgr/volumes: allow creation/deletion of snapshots of FS subvolumes X-Git-Tag: v14.2.2~54^2~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0e2081b7ac1e52aebb59fda22aebec99aaa8dd94;p=ceph.git mgr/volumes: allow creation/deletion of snapshots of FS subvolumes ... using `ceph fs subvolume snapshot create/rm` commands. Signed-off-by: Ramana Raja (cherry picked from commit a02b58e0a927049aa06b1b08217af021275d77b7) --- diff --git a/src/pybind/mgr/volumes/fs/subvolume.py b/src/pybind/mgr/volumes/fs/subvolume.py index 272358ed5ca2..fe849e2ce52f 100644 --- a/src/pybind/mgr/volumes/fs/subvolume.py +++ b/src/pybind/mgr/volumes/fs/subvolume.py @@ -238,3 +238,35 @@ class SubvolumeClient(object): 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): + """ + 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) + except cephfs.ObjectNotFound: + self.fs.mkdir(snapshot_path, mode) + else: + log.warn("Snapshot '{0}' already exists".format(snapshot_name)) + + + def _snapshot_delete(self, dir_path, snapshot_name): + """ + 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) + + def create_subvolume_snapshot(self, subvolume_path, snapshot_name, mode=0o755): + return self._snapshot_create(self._subvolume_path(subvolume_path), snapshot_name, mode) + + def delete_subvolume_snapshot(self, subvolume_path, snapshot_name): + return self._snapshot_delete(self._subvolume_path(subvolume_path), snapshot_name) diff --git a/src/pybind/mgr/volumes/module.py b/src/pybind/mgr/volumes/module.py index df4ddba6b14c..d634164e516f 100644 --- a/src/pybind/mgr/volumes/module.py +++ b/src/pybind/mgr/volumes/module.py @@ -68,6 +68,23 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): 'desc': "Get the mountpath of a CephFS subvolume in a volume", 'perm': 'rw' }, + { + 'cmd': 'fs subvolume snapshot create ' + 'name=vol_name,type=CephString ' + 'name=sub_name,type=CephString ' + 'name=snap_name,type=CephString ', + 'desc': "Create a snapshot of a CephFS subvolume in a volume", + 'perm': 'rw' + }, + { + 'cmd': 'fs subvolume snapshot rm ' + 'name=vol_name,type=CephString ' + 'name=sub_name,type=CephString ' + 'name=snap_name,type=CephString ' + 'name=force,type=CephBool,req=false ', + 'desc': "Delete a snapshot of a CephFS subvolume in a volume", + 'perm': 'rw' + }, # volume ls [recursive] # subvolume ls @@ -371,3 +388,54 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule): return -errno.ENOENT, "", \ "Subvolume '{0}' not found".format(sub_name) return 0, path, "" + + def _cmd_fs_subvolume_snapshot_create(self, inbuf, cmd): + vol_name = cmd['vol_name'] + sub_name = cmd['sub_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: + svp = SubvolumePath(sub_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, "", "" + + 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) + + 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: + svp = SubvolumePath(sub_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, "", ""