summaryrefslogtreecommitdiffstats
path: root/src/pybind/mgr/volumes/fs/operations/versions/op_sm.py
blob: 1142600cbb20fcafd78f08276fd537be697cdfee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import errno

from typing import Dict

from ...exception import OpSmException
from .subvolume_attrs import SubvolumeTypes, SubvolumeStates, SubvolumeActions

class TransitionKey(object):
    def __init__(self, subvol_type, state, action_type):
        self.transition_key = [subvol_type, state, action_type]

    def __hash__(self):
        return hash(tuple(self.transition_key))

    def __eq__(self, other):
        return self.transition_key == other.transition_key

    def __neq__(self, other):
        return not(self == other)

class SubvolumeOpSm(object):
    transition_table = {} # type: Dict

    @staticmethod
    def is_complete_state(state):
        if not isinstance(state, SubvolumeStates):
            raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(state))
        return state == SubvolumeStates.STATE_COMPLETE

    @staticmethod
    def is_failed_state(state):
        if not isinstance(state, SubvolumeStates):
            raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(state))
        return state == SubvolumeStates.STATE_FAILED or state == SubvolumeStates.STATE_CANCELED

    @staticmethod
    def is_init_state(stm_type, state):
        if not isinstance(state, SubvolumeStates):
            raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(state))
        return state == SubvolumeOpSm.get_init_state(stm_type)

    @staticmethod
    def get_init_state(stm_type):
        if not isinstance(stm_type, SubvolumeTypes):
            raise OpSmException(-errno.EINVAL, "unknown state machine '{0}'".format(stm_type))
        init_state =  SubvolumeOpSm.transition_table[TransitionKey(stm_type,
                                                     SubvolumeStates.STATE_INIT,
                                                     SubvolumeActions.ACTION_NONE)]
        if not init_state:
            raise OpSmException(-errno.ENOENT, "initial state for state machine '{0}' not found".format(stm_type))
        return init_state

    @staticmethod
    def transition(stm_type, current_state, action):
        if not isinstance(stm_type, SubvolumeTypes):
            raise OpSmException(-errno.EINVAL, "unknown state machine '{0}'".format(stm_type))
        if not isinstance(current_state, SubvolumeStates):
            raise OpSmException(-errno.EINVAL, "unknown state '{0}'".format(current_state))
        if not isinstance(action, SubvolumeActions):
            raise OpSmException(-errno.EINVAL, "unknown action '{0}'".format(action))

        transition = SubvolumeOpSm.transition_table[TransitionKey(stm_type, current_state, action)]
        if not transition:
            raise OpSmException(-errno.EINVAL, "invalid action '{0}' on current state {1} for state machine '{2}'".format(action, current_state, stm_type))

        return transition

SubvolumeOpSm.transition_table = {
    # state transitions for state machine type TYPE_NORMAL
    TransitionKey(SubvolumeTypes.TYPE_NORMAL,
                  SubvolumeStates.STATE_INIT,
                  SubvolumeActions.ACTION_NONE) : SubvolumeStates.STATE_COMPLETE,

    TransitionKey(SubvolumeTypes.TYPE_NORMAL,
                  SubvolumeStates.STATE_COMPLETE,
                  SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,

    # state transitions for state machine type TYPE_CLONE
    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_INIT,
                  SubvolumeActions.ACTION_NONE) : SubvolumeStates.STATE_PENDING,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_PENDING,
                  SubvolumeActions.ACTION_SUCCESS) : SubvolumeStates.STATE_INPROGRESS,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_PENDING,
                  SubvolumeActions.ACTION_CANCELLED) : SubvolumeStates.STATE_CANCELED,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_INPROGRESS,
                  SubvolumeActions.ACTION_SUCCESS) : SubvolumeStates.STATE_COMPLETE,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_INPROGRESS,
                  SubvolumeActions.ACTION_CANCELLED) : SubvolumeStates.STATE_CANCELED,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_INPROGRESS,
                  SubvolumeActions.ACTION_FAILED) : SubvolumeStates.STATE_FAILED,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_COMPLETE,
                  SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_CANCELED,
                  SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,

    TransitionKey(SubvolumeTypes.TYPE_CLONE,
                  SubvolumeStates.STATE_FAILED,
                  SubvolumeActions.ACTION_RETAINED) : SubvolumeStates.STATE_RETAINED,
}