]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: Create subvolume with isolated rados namespace 35482/head
authorKotresh HR <khiremat@redhat.com>
Mon, 27 Apr 2020 18:31:33 +0000 (00:01 +0530)
committerRamana Raja <rraja@redhat.com>
Mon, 8 Jun 2020 16:50:50 +0000 (22:20 +0530)
1. Add --namespace-isolated option to 'subvolume create' command
   to create subvolume in a separate RADOS namespace
2. Add "pool_namespace" field to 'subvolume info' command
   which displays the rados namespace if set else empty string

Fixes: https://tracker.ceph.com/issues/45289
Signed-off-by: Kotresh HR <khiremat@redhat.com>
(cherry picked from commit 7396880d4096b3a2a813b8ebcdcdf3082ee98b23)

doc/cephfs/fs-volumes.rst
qa/tasks/cephfs/test_volumes.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_base.py
src/pybind/mgr/volumes/fs/volume.py
src/pybind/mgr/volumes/module.py

index 45b236a7aaf8dd057bdbd6be5c71a70e24794cf6..17e6e0c2478b37e5cc46ca314eb1ebba07cda2fd 100644 (file)
@@ -115,15 +115,16 @@ FS Subvolumes
 
 Create a subvolume using::
 
-    $ ceph fs subvolume create <vol_name> <subvol_name> [--size <size_in_bytes> --group_name <subvol_group_name> --pool_layout <data_pool_name> --uid <uid> --gid <gid> --mode <octal_mode>]
+    $ ceph fs subvolume create <vol_name> <subvol_name> [--size <size_in_bytes> --group_name <subvol_group_name> --pool_layout <data_pool_name> --uid <uid> --gid <gid> --mode <octal_mode> --namespace-isolated]
 
 
 The command succeeds even if the subvolume already exists.
 
 When creating a subvolume you can specify its subvolume group, data pool layout,
 uid, gid, file mode in octal numerals, and size in bytes. The size of the subvolume is
-specified by setting a quota on it (see :doc:`/cephfs/quota`). By default a
-subvolume is created within the default subvolume group, and with an octal file
+specified by setting a quota on it (see :doc:`/cephfs/quota`). The subvolume can be
+created in a separate RADOS namespace by specifying --namespace-isolated option. By
+default a subvolume is created within the default subvolume group, and with an octal file
 mode '755', uid of its subvolume group, gid of its subvolume group, data pool layout of
 its parent directory and no size limit.
 
@@ -172,6 +173,7 @@ The output format is json and contains fields as follows.
 * data_pool: data pool the subvolume belongs to
 * path: absolute path of a subvolume
 * type: subvolume type indicating whether it's clone or subvolume
+* pool_namespace: RADOS namespace of the subvolume
 
 List subvolumes using::
 
index eda0c24fceede8f1cab522f70b177df8c7962cb7..a869b79e496d97ee8a1a4b8072d77bb270a93b42 100644 (file)
@@ -584,6 +584,26 @@ class TestVolumes(CephFSTestCase):
         # verify trash dir is clean
         self._wait_for_trash_empty()
 
+    def test_subvolume_create_isolated_namespace(self):
+        """
+        Create subvolume in separate rados namespace
+        """
+
+        # create subvolume
+        subvolume = self._generate_random_subvolume_name()
+        self._fs_cmd("subvolume", "create", self.volname, subvolume, "--namespace-isolated")
+
+        # get subvolume metadata
+        subvol_info = json.loads(self._get_subvolume_info(self.volname, subvolume))
+        self.assertNotEqual(len(subvol_info), 0)
+        self.assertEqual(subvol_info["pool_namespace"], "fsvolumens_" + subvolume)
+
+        # remove subvolumes
+        self._fs_cmd("subvolume", "rm", self.volname, subvolume)
+
+        # verify trash dir is clean
+        self._wait_for_trash_empty()
+
     def test_subvolume_create_with_invalid_data_pool_layout(self):
         subvolume = self._generate_random_subvolume_name()
         data_pool = "invalid_pool"
@@ -763,7 +783,8 @@ class TestVolumes(CephFSTestCase):
         # tests the 'fs subvolume info' command
 
         subvol_md = ["atime", "bytes_pcent", "bytes_quota", "bytes_used", "created_at", "ctime",
-                     "data_pool", "gid", "mode", "mon_addrs", "mtime", "path", "type", "uid"]
+                     "data_pool", "gid", "mode", "mon_addrs", "mtime", "path", "pool_namespace",
+                     "type", "uid"]
 
         # create subvolume
         subvolume = self._generate_random_subvolume_name()
@@ -782,6 +803,7 @@ class TestVolumes(CephFSTestCase):
 
         if subvol_info["bytes_quota"] != "infinite":
             raise RuntimeError("bytes_quota should be set to infinite if quota is not set")
+        self.assertEqual(subvol_info["pool_namespace"], "")
 
         nsize = self.DEFAULT_FILE_SIZE*1024*1024
         try:
@@ -812,7 +834,8 @@ class TestVolumes(CephFSTestCase):
 
         # tests the 'fs subvolume info' command for a clone
         subvol_md = ["atime", "bytes_pcent", "bytes_quota", "bytes_used", "created_at", "ctime",
-                     "data_pool", "gid", "mode", "mon_addrs", "mtime", "path", "type", "uid"]
+                     "data_pool", "gid", "mode", "mon_addrs", "mtime", "path", "pool_namespace",
+                     "type", "uid"]
 
         subvolume = self._generate_random_subvolume_name()
         snapshot = self._generate_random_snapshot_name()
index 856e2f6251cf3b3992fc08d0c2994d1aacc7178f..1837f34041a567701056257b490716b71aa109a6 100644 (file)
@@ -248,6 +248,7 @@ class SubvolumeBase(object):
 
         try:
             data_pool = self.fs.getxattr(subvolpath, 'ceph.dir.layout.pool').decode('utf-8')
+            pool_namespace = self.fs.getxattr(subvolpath, 'ceph.dir.layout.pool_namespace').decode('utf-8')
         except cephfs.Error as e:
             raise VolumeException(-e.args[0], e.args[1])
 
@@ -255,4 +256,5 @@ class SubvolumeBase(object):
             'atime': str(st["atime"]), 'mtime': str(st["mtime"]), 'ctime': str(st["ctime"]),
             'mode': int(st["mode"]), 'data_pool': data_pool, 'created_at': str(st["btime"]),
             'bytes_quota': "infinite" if nsize == 0 else nsize, 'bytes_used': int(usedbytes),
-            'bytes_pcent': "undefined" if nsize == 0 else '{0:.2f}'.format((float(usedbytes) / nsize) * 100.0)}
+            'bytes_pcent': "undefined" if nsize == 0 else '{0:.2f}'.format((float(usedbytes) / nsize) * 100.0),
+            'pool_namespace': pool_namespace}
index ad5aa5bf86077c686719ad37b9b31e5310d22c3a..36a12143c1d55dff7aa70c5822c4e6cff7b2813e 100644 (file)
@@ -116,11 +116,12 @@ class VolumeClient(object):
         uid        = kwargs['uid']
         gid        = kwargs['gid']
         mode       = kwargs['mode']
+        isolate_nspace = kwargs['namespace_isolated']
 
         oct_mode = octal_str_to_decimal_int(mode)
         try:
             create_subvol(
-                fs_handle, self.volspec, group, subvolname, size, False, pool, oct_mode, uid, gid)
+                fs_handle, self.volspec, group, subvolname, size, isolate_nspace, pool, oct_mode, uid, gid)
         except VolumeException as ve:
             # kick the purge threads for async removal -- note that this
             # assumes that the subvolume is moved to trashcan for cleanup on error.
@@ -136,6 +137,7 @@ class VolumeClient(object):
         pool       = kwargs['pool_layout']
         uid        = kwargs['uid']
         gid        = kwargs['gid']
+        isolate_nspace = kwargs['namespace_isolated']
 
         try:
             with open_volume(self, volname) as fs_handle:
@@ -145,7 +147,7 @@ class VolumeClient(object):
                             # idempotent creation -- valid. Attributes set is supported.
                             uid = uid if uid else subvolume.uid
                             gid = gid if gid else subvolume.gid
-                            subvolume.set_attrs(subvolume.path, size, False, pool, uid, gid)
+                            subvolume.set_attrs(subvolume.path, size, isolate_nspace, pool, uid, gid)
                     except VolumeException as ve:
                         if ve.errno == -errno.ENOENT:
                             self._create_subvolume(fs_handle, volname, group, subvolname, **kwargs)
index 8e4c0f71e829b3dcb08d1de979cb925ffb56cb95..e2384d73369f8fc61e4e206c27a90c86ed05d361 100644 (file)
@@ -68,10 +68,12 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                    'name=pool_layout,type=CephString,req=false '
                    'name=uid,type=CephInt,req=false '
                    'name=gid,type=CephInt,req=false '
-                   'name=mode,type=CephString,req=false ',
+                   'name=mode,type=CephString,req=false '
+                   'name=namespace_isolated,type=CephBool,req=false ',
             'desc': "Create a CephFS subvolume in a volume, and optionally, "
                     "with a specific size (in bytes), a specific data pool layout, "
-                    "a specific mode, and in a specific subvolume group",
+                    "a specific mode, in a specific subvolume group and in separate "
+                    "RADOS namespace",
             'perm': 'rw'
         },
         {
@@ -300,7 +302,8 @@ class Module(orchestrator.OrchestratorClientMixin, MgrModule):
                                         pool_layout=cmd.get('pool_layout', None),
                                         uid=cmd.get('uid', None),
                                         gid=cmd.get('gid', None),
-                                        mode=cmd.get('mode', '755'))
+                                        mode=cmd.get('mode', '755'),
+                                        namespace_isolated=cmd.get('namespace_isolated', False))
 
     def _cmd_fs_subvolume_rm(self, inbuf, cmd):
         """