]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/volumes: add operation state machine table
authorVenky Shankar <vshankar@redhat.com>
Mon, 2 Dec 2019 06:27:55 +0000 (01:27 -0500)
committerVenky Shankar <vshankar@redhat.com>
Fri, 31 Jan 2020 10:09:14 +0000 (05:09 -0500)
... and fetch creation state from state machine table.

Signed-off-by: Venky Shankar <vshankar@redhat.com>
src/pybind/mgr/volumes/fs/exception.py
src/pybind/mgr/volumes/fs/operations/op_sm.py [new file with mode: 0644]
src/pybind/mgr/volumes/fs/operations/versions/__init__.py
src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py

index 18a502f7a74bccb2f641ec621bc58b4a62653cfe..4493141d0a0b21ff8f3c3eb776212179bc48a7b2 100644 (file)
@@ -16,3 +16,11 @@ class MetadataMgrException(Exception):
 
     def __str__(self):
         return "{0} ({1})".format(self.errno, self.error_str)
+
+class OpSmException(Exception):
+    def __init__(self, error_code, error_message):
+        self.errno = error_code
+        self.error_str = error_message
+
+    def __str__(self):
+        return "{0} ({1})".format(self.errno, self.error_str)
diff --git a/src/pybind/mgr/volumes/fs/operations/op_sm.py b/src/pybind/mgr/volumes/fs/operations/op_sm.py
new file mode 100644 (file)
index 0000000..6650c1c
--- /dev/null
@@ -0,0 +1,50 @@
+from ..exception import OpSmException
+
+class OpSm(object):
+    INIT_STATE_KEY = 'init'
+
+    FAILED_STATE = 'failed'
+    FINAL_STATE  = 'complete'
+
+    OP_SM_SUBVOLUME = {
+        INIT_STATE_KEY : FINAL_STATE,
+    }
+
+    OP_SM_CLONE = {
+        INIT_STATE_KEY : 'pending',
+        'pending'           : ('in-progress', FAILED_STATE),
+        'in-progress'       : (FINAL_STATE, FAILED_STATE),
+    }
+
+    STATE_MACHINES_TYPES = {
+        "subvolume" : OP_SM_SUBVOLUME,
+        "clone"     : OP_SM_CLONE,
+    }
+
+    @staticmethod
+    def is_final_state(state):
+        return state == OpSm.FINAL_STATE
+
+    @staticmethod
+    def is_failed_state(state):
+        return state == OpSm.FAILED_STATE
+
+    @staticmethod
+    def get_init_state(stm_type):
+        stm = OpSm.STATE_MACHINES_TYPES.get(stm_type, None)
+        if not stm:
+            raise OpSmException(-errno.ENOENT, "state machine type '{0}' not found".format(stm_type))
+        init_state = stm.get(OpSm.INIT_STATE_KEY, None)
+        if not init_state:
+            raise OpSmException(-errno.ENOENT, "initial state unavailable for state machine '{0}'".format(stm_type))
+        return init_state
+
+    @staticmethod
+    def get_next_state(stm_type, current_state, ret):
+        stm = OpSm.STATE_MACHINES_TYPES.get(stm_type, None)
+        if not stm:
+            raise OpSmException(-errno.ENOENT, "state machine type '{0}' not found".format(stm_type))
+        next_state = stm.get(current_state, None)
+        if not next_state:
+            raise OpSmException(-errno.EINVAL, "invalid current state '{0}'".format(current_state))
+        return next_state[0] if ret == 0 else next_state[1]
index f7ff05d5dff6cdba1a13fbfe65da7d2d40db5c3a..ddf2789a1770c70a0814bfd88ab1ba4a2138e466 100644 (file)
@@ -5,6 +5,7 @@ import importlib
 import cephfs
 
 from .subvolume_base import SubvolumeBase
+from ..op_sm import OpSm
 from ...exception import VolumeException, MetadataMgrException
 
 log = logging.getLogger(__name__)
@@ -49,8 +50,13 @@ 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
+        try:
+            initial_state = OpSm.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, SubvolumeBase.SUBVOLUME_TYPE_NORMAL, qpath, "complete")
+        subvolume.init_config(self.max_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)
index 746e67465bc6b655f395a54cfc6b1015653149e6..762ea4a47a8aaec1b4740aaf59d8cbaebdfe80aa 100644 (file)
@@ -6,9 +6,10 @@ import logging
 import cephfs
 
 from .subvolume_base import SubvolumeBase
+from ..op_sm import OpSm
 from ..template import SubvolumeTemplate
 from ..snapshot_util import mksnap, rmsnap
-from ...exception import VolumeException, MetadataMgrException
+from ...exception import OpSmException, VolumeException, MetadataMgrException
 from ...fs_util import listdir
 
 log = logging.getLogger(__name__)
@@ -29,6 +30,12 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
             raise VolumeException(-errno.EINVAL, "error fetching subvolume metadata")
 
     def create(self, size, isolate_nspace, pool, mode, uid, gid):
+        subvolume_type = SubvolumeBase.SUBVOLUME_TYPE_NORMAL
+        try:
+            initial_state = OpSm.get_init_state(subvolume_type)
+        except OpSmException as oe:
+            raise VolumeException(-errno.EINVAL, "subvolume creation failed: internal error")
+
         subvol_path = os.path.join(self.base_path, str(uuid.uuid4()).encode('utf-8'))
         try:
             # create directory and set attributes
@@ -37,7 +44,7 @@ class SubvolumeV1(SubvolumeBase, SubvolumeTemplate):
 
             # persist subvolume metadata
             qpath = subvol_path.decode('utf-8')
-            self.init_config(SubvolumeV1.VERSION, "subvolume", qpath, "complete")
+            self.init_config(SubvolumeV1.VERSION, subvolume_type, qpath, initial_state)
         except (VolumeException, MetadataMgrException, cephfs.Error) as e:
             try:
                 log.info("cleaning up subvolume with path: {0}".format(self.subvolname))