From 46f29bf3b4fbb86aeefc940d47eadd6634b5a1ec Mon Sep 17 00:00:00 2001 From: Venky Shankar Date: Mon, 2 Dec 2019 01:27:55 -0500 Subject: [PATCH] mgr/volumes: add operation state machine table ... and fetch creation state from state machine table. Signed-off-by: Venky Shankar --- src/pybind/mgr/volumes/fs/exception.py | 8 +++ src/pybind/mgr/volumes/fs/operations/op_sm.py | 50 +++++++++++++++++++ .../fs/operations/versions/__init__.py | 8 ++- .../fs/operations/versions/subvolume_v1.py | 11 +++- 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 src/pybind/mgr/volumes/fs/operations/op_sm.py diff --git a/src/pybind/mgr/volumes/fs/exception.py b/src/pybind/mgr/volumes/fs/exception.py index 18a502f7a74..4493141d0a0 100644 --- a/src/pybind/mgr/volumes/fs/exception.py +++ b/src/pybind/mgr/volumes/fs/exception.py @@ -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 index 00000000000..6650c1c5b3b --- /dev/null +++ b/src/pybind/mgr/volumes/fs/operations/op_sm.py @@ -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] diff --git a/src/pybind/mgr/volumes/fs/operations/versions/__init__.py b/src/pybind/mgr/volumes/fs/operations/versions/__init__.py index f7ff05d5dff..ddf2789a177 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/__init__.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/__init__.py @@ -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) diff --git a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py index 746e67465bc..762ea4a47a8 100644 --- a/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py +++ b/src/pybind/mgr/volumes/fs/operations/versions/subvolume_v1.py @@ -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)) -- 2.39.5