]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: allow creation/deletion of snapshots of FS subvolumes
authorRamana Raja <rraja@redhat.com>
Fri, 19 Apr 2019 16:56:38 +0000 (22:26 +0530)
committerRamana Raja <rraja@redhat.com>
Thu, 6 Jun 2019 15:24:34 +0000 (20:54 +0530)
... using `ceph fs subvolume snapshot create/rm` commands.

Signed-off-by: Ramana Raja <rraja@redhat.com>
(cherry picked from commit a02b58e0a927049aa06b1b08217af021275d77b7)

src/pybind/mgr/volumes/fs/subvolume.py
src/pybind/mgr/volumes/module.py

index 272358ed5ca2b6c77e4008149f72b51a5a499191..fe849e2ce52fbdb9a7a3181419bb0081ae979eca 100644 (file)
@@ -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)
index df4ddba6b14c739cb27bf6ca7ae9ed711fbad3bf..d634164e516f0fe144c315778ddf6a2e4a8235a2 100644 (file)
@@ -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 <volume>
@@ -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, "", ""