2 from neco.util.timefuncs import strfnow, strfdiff, strfvalid
9 _reschedule_delay = "1s"
27 # Decorator to invoke class initialization method
29 class ResourceManager(object):
35 def _register_filter(cls, attr):
36 """ Resource subclasses will invoke this method to add a
38 cls._filters[attr.name] = attr
41 def _register_attribute(cls, attr):
42 """ Resource subclasses will invoke this method to add a
44 cls._attributes[attr.name] = attr
47 def _register_filters(cls):
48 """ Resource subclasses will invoke this method to add a
53 def _register_attributes(cls):
54 """ Resource subclasses will invoke this method to add a
60 # static template for resource filters
62 cls._register_filters()
64 # static template for resource attributes
65 cls._attributes = dict()
66 cls._register_attributes()
74 return copy.deepcopy(cls._filters.values())
77 def get_attributes(cls):
78 return copy.deepcopy(cls._attributes.values())
80 def __init__(self, ec, guid):
82 self._ec = weakref.ref(ec)
83 self._connections = set()
84 self._conditions = dict()
86 # the resource instance gets a copy of all attributes
88 self._attrs = copy.deepcopy(self._attributes)
90 self._state = ResourceState.NEW
92 self._start_time = None
93 self._stop_time = None
96 self._logger = logging.getLogger("neco.execution.resource.Resource.%s" %
112 def connections(self):
113 return self._connections
117 return self._conditions
120 def start_time(self):
121 """ timestamp with """
122 return self._start_time
126 return self._stop_time
132 def connect(self, guid):
133 if (self._validate_connection(guid)):
134 self._connections.add(guid)
136 def discover(self, filters = None):
139 def provision(self, filters = None):
143 if not self._state in [ResourceState.DEPLOYED, ResourceState.STOPPED]:
144 self.logger.error("Wrong state %s for start" % self.state)
146 self._start_time = strfnow()
147 self._state = ResourceState.STARTED
150 if not self._state in [ResourceState.STARTED]:
151 self.logger.error("Wrong state %s for stop" % self.state)
153 self._stop_time = strfnow()
154 self._state = ResourceState.STOPPED
156 def set(self, name, value):
157 attr = self._attrs[name]
161 attr = self._attrs[name]
164 def register_condition(self, action, group, state,
166 if action not in self.conditions:
167 self._conditions[action] = set()
169 self.conditions.get(action).add((group, state, time))
171 def _needs_reschedule(self, group, state, time):
173 delay = _reschedule_delay
175 # check state and time elapsed on all RMs
177 rm = self.ec.get_resource(guid)
178 # If the RMs is lower than the requested state we must
179 # reschedule (e.g. if RM is DEPLOYED but we required STARTED)
185 if state == ResourceAction.START:
187 elif state == ResourceAction.STOP:
190 # Only keep time information for START and STOP
193 delay = strfdiff(t, strnow())
198 return reschedule, delay
200 def set_with_conditions(self, name, value, group, state, time):
202 delay = _reschedule_delay
204 ## evaluate if set conditions are met
206 # only can set with conditions after the RM is started
207 if self.status != ResourceStatus.STARTED:
210 reschedule, delay = self._needs_reschedule(group, state, time)
213 callback = functools.partial(self.set_with_conditions,
214 name, value, group, state, time)
215 self.ec.schedule(delay, callback)
217 self.set(name, value)
219 def start_with_conditions(self):
221 delay = _reschedule_delay
223 ## evaluate if set conditions are met
225 # only can start when RM is either STOPPED or DEPLOYED
226 if self.status not in [ResourceStatus.STOPPED, ResourceStatus.DEPLOYED]:
229 for action, (group, state, time) in self.conditions.iteritems():
230 if action == ResourceAction.START:
231 reschedule, delay = self._needs_reschedule(group, state, time)
236 callback = functools.partial(self.start_with_conditions,
238 self.ec.schedule(delay, callback)
242 def stop_with_conditions(self):
244 delay = _reschedule_delay
246 ## evaluate if set conditions are met
248 # only can start when RM is either STOPPED or DEPLOYED
249 if self.status != ResourceStatus.STARTED:
252 for action, (group, state, time) in self.conditions.iteritems():
253 if action == ResourceAction.STOP:
254 reschedule, delay = self._needs_reschedule(group, state, time)
259 callback = functools.partial(self.stop_with_conditions,
261 self.ec.schedule(delay, callback)
268 self._state = ResourceState.DEPLOYED
271 self._state = ResourceState.RELEASED
273 def _validate_connection(self, guid):
277 class ResourceFactory(object):
278 _resource_types = dict()
281 def resource_types(cls):
282 return cls._resource_types
285 def register_type(cls, rclass):
286 cls._resource_types[rclass.rtype()] = rclass
289 def create(cls, rtype, ec, guid):
290 rclass = cls._resource_types[rtype]
291 return rclass(ec, guid)