... and fetch creation state from state machine table.
Signed-off-by: Venky Shankar <vshankar@redhat.com>
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)
--- /dev/null
+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]
import cephfs
from .subvolume_base import SubvolumeBase
+from ..op_sm import OpSm
from ...exception import VolumeException, MetadataMgrException
log = logging.getLogger(__name__)
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)
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__)
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
# 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))