]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/mgr/volumes/fs/operations/versions/__init__.py
import ceph 15.2.10
[ceph.git] / ceph / src / pybind / mgr / volumes / fs / operations / versions / __init__.py
index f79631b04990b51c858bb493dedc4dfcfd161a85..3dcdd7c10ab1001af4929a2314bca860cd84bf31 100644 (file)
@@ -5,7 +5,12 @@ import importlib
 import cephfs
 
 from .subvolume_base import SubvolumeBase
-from ..op_sm import OpSm
+from .subvolume_attrs import SubvolumeTypes
+from .subvolume_v1 import SubvolumeV1
+from .subvolume_v2 import SubvolumeV2
+from .metadata_manager import MetadataManager
+from .op_sm import SubvolumeOpSm
+from ..template import SubvolumeOpType
 from ...exception import MetadataMgrException, OpSmException, VolumeException
 
 log = logging.getLogger(__name__)
@@ -13,7 +18,7 @@ log = logging.getLogger(__name__)
 class SubvolumeLoader(object):
     INVALID_VERSION = -1
 
-    SUPPORTED_MODULES = ['subvolume_v1.SubvolumeV1']
+    SUPPORTED_MODULES = ['subvolume_v1.SubvolumeV1', 'subvolume_v2.SubvolumeV2']
 
     def __init__(self):
         self.max_version = SubvolumeLoader.INVALID_VERSION
@@ -41,8 +46,33 @@ class SubvolumeLoader(object):
         except KeyError:
             raise VolumeException(-errno.EINVAL, "subvolume class v{0} does not exist".format(version))
 
-    def get_subvolume_object_max(self, fs, vol_spec, group, subvolname):
-        return self._get_subvolume_version(self.max_version)(fs, vol_spec, group, subvolname)
+    def get_subvolume_object_max(self, mgr, fs, vol_spec, group, subvolname):
+        return self._get_subvolume_version(self.max_version)(mgr, fs, vol_spec, group, subvolname)
+
+    def upgrade_to_v2_subvolume(self, subvolume):
+        # legacy mode subvolumes cannot be upgraded to v2
+        if subvolume.legacy_mode:
+            return
+
+        version = int(subvolume.metadata_mgr.get_global_option('version'))
+        if version >= SubvolumeV2.version():
+            return
+
+        v1_subvolume = self._get_subvolume_version(version)(subvolume.mgr, subvolume.fs, subvolume.vol_spec, subvolume.group, subvolume.subvolname)
+        try:
+            v1_subvolume.open(SubvolumeOpType.SNAP_LIST)
+        except VolumeException as ve:
+            # if volume is not ready for snapshot listing, do not upgrade at present
+            if ve.errno == -errno.EAGAIN:
+                return
+            raise
+
+        # v1 subvolumes with snapshots cannot be upgraded to v2
+        if v1_subvolume.list_snapshots():
+            return
+
+        subvolume.metadata_mgr.update_global_section(MetadataManager.GLOBAL_META_KEY_VERSION, SubvolumeV2.version())
+        subvolume.metadata_mgr.flush()
 
     def upgrade_legacy_subvolume(self, fs, subvolume):
         assert subvolume.legacy_mode
@@ -50,24 +80,26 @@ class SubvolumeLoader(object):
             fs.mkdirs(subvolume.legacy_dir, 0o700)
         except cephfs.Error as e:
             raise VolumeException(-e.args[0], "error accessing subvolume")
-        subvolume_type = SubvolumeBase.SUBVOLUME_TYPE_NORMAL
+        subvolume_type = SubvolumeTypes.TYPE_NORMAL
         try:
-            initial_state = OpSm.get_init_state(subvolume_type)
+            initial_state = SubvolumeOpSm.get_init_state(subvolume_type)
         except OpSmException as oe:
             raise VolumeException(-errno.EINVAL, "subvolume creation failed: internal error")
         qpath = subvolume.base_path.decode('utf-8')
-        subvolume.init_config(self.max_version, subvolume_type, qpath, initial_state)
+        # legacy is only upgradable to v1
+        subvolume.init_config(SubvolumeV1.version(), subvolume_type, qpath, initial_state)
 
-    def get_subvolume_object(self, fs, vol_spec, group, subvolname, upgrade=True):
-        subvolume = SubvolumeBase(fs, vol_spec, group, subvolname)
+    def get_subvolume_object(self, mgr, fs, vol_spec, group, subvolname, upgrade=True):
+        subvolume = SubvolumeBase(mgr, fs, vol_spec, group, subvolname)
         try:
             subvolume.discover()
+            self.upgrade_to_v2_subvolume(subvolume)
             version = int(subvolume.metadata_mgr.get_global_option('version'))
-            return self._get_subvolume_version(version)(fs, vol_spec, group, subvolname, legacy=subvolume.legacy_mode)
+            return self._get_subvolume_version(version)(mgr, fs, vol_spec, group, subvolname, legacy=subvolume.legacy_mode)
         except MetadataMgrException as me:
             if me.errno == -errno.ENOENT and upgrade:
                 self.upgrade_legacy_subvolume(fs, subvolume)
-                return self.get_subvolume_object(fs, vol_spec, group, subvolname, upgrade=False)
+                return self.get_subvolume_object(mgr, fs, vol_spec, group, subvolname, upgrade=False)
             else:
                 # log the actual error and generalize error string returned to user
                 log.error("error accessing subvolume metadata for '{0}' ({1})".format(subvolname, me))