]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/volumes: handle transient subvolume states
authorVenky Shankar <vshankar@redhat.com>
Mon, 2 Dec 2019 08:00:30 +0000 (03:00 -0500)
committerRamana Raja <rraja@redhat.com>
Wed, 12 Feb 2020 10:12:00 +0000 (05:12 -0500)
Signed-off-by: Venky Shankar <vshankar@redhat.com>
(cherry picked from commit 461909be2edd2f691263785469e5fc90a82448e8)

src/pybind/mgr/volumes/fs/operations/subvolume.py
src/pybind/mgr/volumes/fs/operations/template.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py

index 8c3db11c42192da7470bb14ee8bceadeb67f6675..bfd9349bb77c4209ad02df7a6491d069b3e3aab4 100644 (file)
@@ -61,7 +61,7 @@ def remove_subvol(fs, vol_spec, group, subvolname):
         subvolume.remove()
 
 @contextmanager
-def open_subvol(fs, vol_spec, group, subvolname):
+def open_subvol(fs, vol_spec, group, subvolname, need_complete=True, expected_types=[]):
     """
     open a subvolume. This API is to be used as a context manager.
 
@@ -69,8 +69,12 @@ def open_subvol(fs, vol_spec, group, subvolname):
     :param vol_spec: volume specification
     :param group: group object for the subvolume
     :param subvolname: subvolume name
+    :param need_complete: check if the subvolume is usable (since cloned subvolumes can
+                          be in transient state). defaults to True.
+    :param expected_types: check if the subvolume is one the provided types. defaults to
+                           all.
     :return: yields a subvolume object (subclass of SubvolumeTemplate)
     """
     subvolume = loaded_subvolumes.get_subvolume_object(fs, vol_spec, group, subvolname)
-    subvolume.open()
+    subvolume.open(need_complete, expected_types)
     yield subvolume
index c5ecf47e7e44009a7d500be8cd3145192daa8b6d..14785e18dba7953bd2bbbc7c9109702187f634f1 100644 (file)
@@ -38,7 +38,7 @@ class SubvolumeTemplate(object):
     def version():
         return SubvolumeTemplate.VERSION
 
-    def open(self):
+    def open(self, need_complete=True, expected_types=[]):
         raise VolumeException(-errno.ENOTSUP, "operation not supported.")
 
     def create(self, size, isolate_nspace, pool, mode, uid, gid):
index 5a28f6292fad35a5e70bcdeef1281a0640bb42a7..026ed32489a6b5ce55fe5a2201cfe3a9fa967069 100644 (file)
@@ -6,6 +6,7 @@ import logging
 
 import cephfs
 
+from .metadata_manager import MetadataManager
 from .subvolume_base import SubvolumeBase
 from ..op_sm import OpSm
 from ..template import SubvolumeTemplate
@@ -107,12 +108,21 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
                 e = VolumeException(-e.args[0], e.args[1])
             raise e
 
-    def open(self):
+    def open(self, need_complete=True, expected_types=[]):
         try:
             self.metadata_mgr.refresh()
             subvol_path = self.path
             log.debug("refreshed metadata, checking subvolume path '{0}'".format(subvol_path))
             st = self.fs.stat(subvol_path)
+            etype = self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_TYPE)
+            if len(expected_types) and not etype in expected_types:
+                raise VolumeException(-errno.ENOTSUP, "subvolume '{0}' is not {1}".format(
+                    self.subvolname, "a {0}".format(expected_types[0]) if len(expected_types) == 1 else \
+                    "one of types ({0})".format(",".join(expected_types))))
+            if need_complete:
+                estate = self.metadata_mgr.get_global_option(MetadataManager.GLOBAL_META_KEY_STATE)
+                if not OpSm.is_final_state(estate):
+                    raise VolumeException(-errno.EAGAIN, "subvolume '{0}' is not ready for use".format(self.subvolname))
             self.uid = int(st.st_uid)
             self.gid = int(st.st_gid)
             self.mode = int(st.st_mode & ~stat.S_IFMT(st.st_mode))