Statistics
| Branch: | Tag: | Revision:

root / commissioning / api / controller.py @ 9f1a1bd0

History | View | Annotate | Download (7 kB)

1 9f1a1bd0 Georgios D. Tsoukalas
from .exception import CorruptedError
2 9f1a1bd0 Georgios D. Tsoukalas
from .callpoint import Callpoint
3 9f1a1bd0 Georgios D. Tsoukalas
from .physical import Physical
4 9f1a1bd0 Georgios D. Tsoukalas
5 9f1a1bd0 Georgios D. Tsoukalas
class Controller(object):
6 9f1a1bd0 Georgios D. Tsoukalas
7 9f1a1bd0 Georgios D. Tsoukalas
    def __init__(self, quotaholder, physical):
8 9f1a1bd0 Georgios D. Tsoukalas
        self.quotaholder = quotaholder
9 9f1a1bd0 Georgios D. Tsoukalas
        self.physical = physical
10 9f1a1bd0 Georgios D. Tsoukalas
        self.controller_init()
11 9f1a1bd0 Georgios D. Tsoukalas
12 9f1a1bd0 Georgios D. Tsoukalas
    def controller_init(self):
13 9f1a1bd0 Georgios D. Tsoukalas
        pass
14 9f1a1bd0 Georgios D. Tsoukalas
15 9f1a1bd0 Georgios D. Tsoukalas
    def get_commission_issue(self, commission_spec):
16 9f1a1bd0 Georgios D. Tsoukalas
        """Prepare and return the arguments for the
17 9f1a1bd0 Georgios D. Tsoukalas
           quotaholder's issue_commission call,
18 9f1a1bd0 Georgios D. Tsoukalas
           containing the provisions required and
19 9f1a1bd0 Georgios D. Tsoukalas
           the target entity for their allocation.
20 9f1a1bd0 Georgios D. Tsoukalas
        """
21 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
22 9f1a1bd0 Georgios D. Tsoukalas
23 9f1a1bd0 Georgios D. Tsoukalas
    def register_commission(self,   serial,
24 9f1a1bd0 Georgios D. Tsoukalas
                                    clientkey,
25 9f1a1bd0 Georgios D. Tsoukalas
                                    physical_description    ):
26 9f1a1bd0 Georgios D. Tsoukalas
27 9f1a1bd0 Georgios D. Tsoukalas
        """Register a commission to the controller's stable storage,
28 9f1a1bd0 Georgios D. Tsoukalas
           along with the quotaholder serial and clientkey,
29 9f1a1bd0 Georgios D. Tsoukalas
           and the target physical description.
30 9f1a1bd0 Georgios D. Tsoukalas
           This information is needed to co-ordinate the commission
31 9f1a1bd0 Georgios D. Tsoukalas
           execution among the quotaholder server, the controller,
32 9f1a1bd0 Georgios D. Tsoukalas
           and the physical layer implementing the resource.
33 9f1a1bd0 Georgios D. Tsoukalas
        """
34 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
35 9f1a1bd0 Georgios D. Tsoukalas
36 9f1a1bd0 Georgios D. Tsoukalas
    def get_commission(self, serial):
37 9f1a1bd0 Georgios D. Tsoukalas
        """Retrieve the commission registered with serial"""
38 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
39 9f1a1bd0 Georgios D. Tsoukalas
40 9f1a1bd0 Georgios D. Tsoukalas
    def complete_commission(self, serial):
41 9f1a1bd0 Georgios D. Tsoukalas
        """Mark and commit in stable storage the commission identified by
42 9f1a1bd0 Georgios D. Tsoukalas
           a serial as to-be-completed-successfully,
43 9f1a1bd0 Georgios D. Tsoukalas
           i.e that it has succeeded in producing a physical resource
44 9f1a1bd0 Georgios D. Tsoukalas
           and is to be removed from being tracked by the holder server,
45 9f1a1bd0 Georgios D. Tsoukalas
           controller, and physical layers.
46 9f1a1bd0 Georgios D. Tsoukalas
        """
47 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
48 9f1a1bd0 Georgios D. Tsoukalas
49 9f1a1bd0 Georgios D. Tsoukalas
    def is_commission_complete(self, serial):
50 9f1a1bd0 Georgios D. Tsoukalas
        """Return true if the serial is marked as
51 9f1a1bd0 Georgios D. Tsoukalas
           completed by complete_commission()
52 9f1a1bd0 Georgios D. Tsoukalas
        """
53 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
54 9f1a1bd0 Georgios D. Tsoukalas
55 9f1a1bd0 Georgios D. Tsoukalas
    def fail_commission(self, serial):
56 9f1a1bd0 Georgios D. Tsoukalas
        """Mark and commit in stable storage the commission identified by
57 9f1a1bd0 Georgios D. Tsoukalas
           a serial as to-be-completed-unsuccessfully,
58 9f1a1bd0 Georgios D. Tsoukalas
           i.e. that it has failed in producing a physical resource
59 9f1a1bd0 Georgios D. Tsoukalas
           and is to be removed from being tracked by the holder server,
60 9f1a1bd0 Georgios D. Tsoukalas
           controller, and physical layers.
61 9f1a1bd0 Georgios D. Tsoukalas
        """
62 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
63 9f1a1bd0 Georgios D. Tsoukalas
64 9f1a1bd0 Georgios D. Tsoukalas
    def is_commission_failing(self, serial):
65 9f1a1bd0 Georgios D. Tsoukalas
        """Return true if the serial is marked as
66 9f1a1bd0 Georgios D. Tsoukalas
           failing by fail_commission()
67 9f1a1bd0 Georgios D. Tsoukalas
        """
68 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
69 9f1a1bd0 Georgios D. Tsoukalas
70 9f1a1bd0 Georgios D. Tsoukalas
    def retire_commission(self, serial):
71 9f1a1bd0 Georgios D. Tsoukalas
        """Stop tracking the commission identified by a serial"""
72 9f1a1bd0 Georgios D. Tsoukalas
        raise NotImplementedError
73 9f1a1bd0 Georgios D. Tsoukalas
74 9f1a1bd0 Georgios D. Tsoukalas
    def undertake_commission(self, commission_spec):
75 9f1a1bd0 Georgios D. Tsoukalas
        """Initiate and start tracking and co-ordinating a commission
76 9f1a1bd0 Georgios D. Tsoukalas
           from a commission spec.
77 9f1a1bd0 Georgios D. Tsoukalas
        """
78 9f1a1bd0 Georgios D. Tsoukalas
        holder = self.quotaholder
79 9f1a1bd0 Georgios D. Tsoukalas
        physical = self.physical
80 9f1a1bd0 Georgios D. Tsoukalas
81 9f1a1bd0 Georgios D. Tsoukalas
        commission_issue = self.get_commission_issue(commission_spec)
82 9f1a1bd0 Georgios D. Tsoukalas
        entity = commission_issue['entity']
83 9f1a1bd0 Georgios D. Tsoukalas
        clientkey = commission_issue['clientkey']
84 9f1a1bd0 Georgios D. Tsoukalas
        physical_description = self.derive_description(commission_spec)
85 9f1a1bd0 Georgios D. Tsoukalas
86 9f1a1bd0 Georgios D. Tsoukalas
        serial = holder.issue_commission(entity, provisions)
87 9f1a1bd0 Georgios D. Tsoukalas
        self.register_commission(   serial,
88 9f1a1bd0 Georgios D. Tsoukalas
                                    clientkey,
89 9f1a1bd0 Georgios D. Tsoukalas
                                    physical_description    )
90 9f1a1bd0 Georgios D. Tsoukalas
91 9f1a1bd0 Georgios D. Tsoukalas
        self.process_controller(serial)
92 9f1a1bd0 Georgios D. Tsoukalas
        return serial
93 9f1a1bd0 Georgios D. Tsoukalas
94 9f1a1bd0 Georgios D. Tsoukalas
    def process_controller(self, serial):
95 9f1a1bd0 Georgios D. Tsoukalas
        """Consider the current state of a commission in the controller layer,
96 9f1a1bd0 Georgios D. Tsoukalas
           and schedule next actions.
97 9f1a1bd0 Georgios D. Tsoukalas
        """
98 9f1a1bd0 Georgios D. Tsoukalas
        holder = self.quotaholder
99 9f1a1bd0 Georgios D. Tsoukalas
        physical = self.physical
100 9f1a1bd0 Georgios D. Tsoukalas
        controller = self
101 9f1a1bd0 Georgios D. Tsoukalas
102 9f1a1bd0 Georgios D. Tsoukalas
        r = controller.get_commission(serial)
103 9f1a1bd0 Georgios D. Tsoukalas
        if not r:
104 9f1a1bd0 Georgios D. Tsoukalas
            return
105 9f1a1bd0 Georgios D. Tsoukalas
106 9f1a1bd0 Georgios D. Tsoukalas
        serial, clientkey, physical_description, status = r
107 9f1a1bd0 Georgios D. Tsoukalas
108 9f1a1bd0 Georgios D. Tsoukalas
        if controller.is_commission_complete(serial):
109 9f1a1bd0 Georgios D. Tsoukalas
            holder.accept_commission(serial=serial, clientkey=clientkey)
110 9f1a1bd0 Georgios D. Tsoukalas
            physical.end_commission(serial, physical_description)
111 9f1a1bd0 Georgios D. Tsoukalas
            controller.retire_commission(serial)
112 9f1a1bd0 Georgios D. Tsoukalas
113 9f1a1bd0 Georgios D. Tsoukalas
        elif controller.is_commission_failing(serial):
114 9f1a1bd0 Georgios D. Tsoukalas
            holder.recall_commission(serial=serial, clientkey=clientkey)
115 9f1a1bd0 Georgios D. Tsoukalas
            physical.end_commission(serial, physical_description)
116 9f1a1bd0 Georgios D. Tsoukalas
            controller.retire_commission(serial)
117 9f1a1bd0 Georgios D. Tsoukalas
118 9f1a1bd0 Georgios D. Tsoukalas
        else:
119 9f1a1bd0 Georgios D. Tsoukalas
            controller.process_physical(serial)
120 9f1a1bd0 Georgios D. Tsoukalas
121 9f1a1bd0 Georgios D. Tsoukalas
    def process_physical(self, serial):
122 9f1a1bd0 Georgios D. Tsoukalas
        """Consider the current state of a commission in the physical layer,
123 9f1a1bd0 Georgios D. Tsoukalas
           and schedule next actions.
124 9f1a1bd0 Georgios D. Tsoukalas
        """
125 9f1a1bd0 Georgios D. Tsoukalas
        physical = self.physical
126 9f1a1bd0 Georgios D. Tsoukalas
127 9f1a1bd0 Georgios D. Tsoukalas
        r = self.get_commission(serial)
128 9f1a1bd0 Georgios D. Tsoukalas
        if not r:
129 9f1a1bd0 Georgios D. Tsoukalas
            m = "Unknown serial %d in process_physical!" % (serial,)
130 9f1a1bd0 Georgios D. Tsoukalas
            raise CorruptedError(m)
131 9f1a1bd0 Georgios D. Tsoukalas
132 9f1a1bd0 Georgios D. Tsoukalas
        target_description = r[2]
133 9f1a1bd0 Georgios D. Tsoukalas
        current_state = physical.get_current_state(serial, target_description)
134 9f1a1bd0 Georgios D. Tsoukalas
135 9f1a1bd0 Georgios D. Tsoukalas
        if not current_state:
136 9f1a1bd0 Georgios D. Tsoukalas
137 9f1a1bd0 Georgios D. Tsoukalas
            physical.initiate_commission(serial, target_description)
138 9f1a1bd0 Georgios D. Tsoukalas
139 9f1a1bd0 Georgios D. Tsoukalas
        elif physical.complies(current_state, target_description):
140 9f1a1bd0 Georgios D. Tsoukalas
141 9f1a1bd0 Georgios D. Tsoukalas
            self.complete_commission(serial)
142 9f1a1bd0 Georgios D. Tsoukalas
            self.process_controller(serial)
143 9f1a1bd0 Georgios D. Tsoukalas
144 9f1a1bd0 Georgios D. Tsoukalas
        elif physical.attainable(current_state, target_description):
145 9f1a1bd0 Georgios D. Tsoukalas
146 9f1a1bd0 Georgios D. Tsoukalas
            physical.continue_commission(serial, target_description)
147 9f1a1bd0 Georgios D. Tsoukalas
148 9f1a1bd0 Georgios D. Tsoukalas
        else:
149 9f1a1bd0 Georgios D. Tsoukalas
            self.fail_commission(serial)
150 9f1a1bd0 Georgios D. Tsoukalas
            physical.end_commission(serial, target_description)
151 9f1a1bd0 Georgios D. Tsoukalas
            self.process_controller(serial)
152 9f1a1bd0 Georgios D. Tsoukalas
153 9f1a1bd0 Georgios D. Tsoukalas
154 9f1a1bd0 Georgios D. Tsoukalas
class ControlledCallpoint(Callpoint):
155 9f1a1bd0 Georgios D. Tsoukalas
156 9f1a1bd0 Georgios D. Tsoukalas
    controllables = set()
157 9f1a1bd0 Georgios D. Tsoukalas
158 9f1a1bd0 Georgios D. Tsoukalas
    def __init__(self, *args):
159 9f1a1bd0 Georgios D. Tsoukalas
        self.controllables = set()
160 9f1a1bd0 Georgios D. Tsoukalas
        super(ControlledCallpoint, self).__init__(*args)
161 9f1a1bd0 Georgios D. Tsoukalas
162 9f1a1bd0 Georgios D. Tsoukalas
    def commission_from_call(self, call_name, call_data):
163 9f1a1bd0 Georgios D. Tsoukalas
        commission_spec = {}
164 9f1a1bd0 Georgios D. Tsoukalas
        commission_spec['call_name'] = call_name
165 9f1a1bd0 Georgios D. Tsoukalas
        commission_spec['call_data'] = call_data
166 9f1a1bd0 Georgios D. Tsoukalas
        commission_spec['provisions'] = ()
167 9f1a1bd0 Georgios D. Tsoukalas
        return commission_spec, True
168 9f1a1bd0 Georgios D. Tsoukalas
169 9f1a1bd0 Georgios D. Tsoukalas
    def register_controllable(self, call_name):
170 9f1a1bd0 Georgios D. Tsoukalas
        controllable = self.controllables
171 9f1a1bd0 Georgios D. Tsoukalas
        if call_name in controllables:
172 9f1a1bd0 Georgios D. Tsoukalas
            return
173 9f1a1bd0 Georgios D. Tsoukalas
174 9f1a1bd0 Georgios D. Tsoukalas
        try:
175 9f1a1bd0 Georgios D. Tsoukalas
            canonify_output = self.api_spec.canonify_output
176 9f1a1bd0 Georgios D. Tsoukalas
            s = canonify_output(None) is None
177 9f1a1bd0 Georgios D. Tsoukalas
            s += isinstance(canonify_output(1), int)
178 9f1a1bd0 Georgios D. Tsoukalas
            s += isinstance(canonify_output(2**63), int)
179 9f1a1bd0 Georgios D. Tsoukalas
            if s != 3:
180 9f1a1bd0 Georgios D. Tsoukalas
                raise CanonifyException
181 9f1a1bd0 Georgios D. Tsoukalas
        except CanonifyException, e:
182 9f1a1bd0 Georgios D. Tsoukalas
            m = ("Attempt to register controllable call '%s', but"
183 9f1a1bd0 Georgios D. Tsoukalas
                 "the api spec does not define a nullable int (serial) output!"
184 9f1a1bd0 Georgios D. Tsoukalas
                                                                % (call_name,))
185 9f1a1bd0 Georgios D. Tsoukalas
            raise CanonifyException(m, e)
186 9f1a1bd0 Georgios D. Tsoukalas
187 9f1a1bd0 Georgios D. Tsoukalas
        controllables.add(call_name)
188 9f1a1bd0 Georgios D. Tsoukalas
189 9f1a1bd0 Georgios D. Tsoukalas
    def do_make_call(self, call_name, call_data):
190 9f1a1bd0 Georgios D. Tsoukalas
        r = self.commission_from_call(call_name, call_data)
191 9f1a1bd0 Georgios D. Tsoukalas
        commission_spec, controllable = r
192 9f1a1bd0 Georgios D. Tsoukalas
        controller = self.controller
193 9f1a1bd0 Georgios D. Tsoukalas
194 9f1a1bd0 Georgios D. Tsoukalas
        if not controllable:
195 9f1a1bd0 Georgios D. Tsoukalas
            return controller.forward_commission(commission_spec)
196 9f1a1bd0 Georgios D. Tsoukalas
197 9f1a1bd0 Georgios D. Tsoukalas
        if call_name not in self.controllables:
198 9f1a1bd0 Georgios D. Tsoukalas
            self.register_controllable(call_name)
199 9f1a1bd0 Georgios D. Tsoukalas
200 9f1a1bd0 Georgios D. Tsoukalas
        serial = controller.undertake_commission(commission_spec)
201 9f1a1bd0 Georgios D. Tsoukalas
        return serial