X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fexecution%2Fresource.py;h=5ec0be383d8ed8b57ec3daa7510aa842d3a0984e;hb=f7c6792813947d3707accd690ad7bbe83277798f;hp=e4c4b0c7a406f22e0a5aa7bf4bb384c5ca90f1e2;hpb=04094716c3ff011e697e1e8871328a4a06aab83d;p=nepi.git diff --git a/src/nepi/execution/resource.py b/src/nepi/execution/resource.py index e4c4b0c7..5ec0be38 100644 --- a/src/nepi/execution/resource.py +++ b/src/nepi/execution/resource.py @@ -186,7 +186,6 @@ class ResourceManager(Logger): attributes. """ - critical = Attribute("critical", "Defines whether the resource is critical. " "A failure on a critical resource will interrupt " @@ -194,8 +193,17 @@ class ResourceManager(Logger): type = Types.Bool, default = True, flags = Flags.Design) + hard_release = Attribute("hardRelease", + "Forces removal of all result files and directories associated " + "to the RM upon resource release. After release the RM will " + "be removed from the EC and the results will not longer be " + "accessible", + type = Types.Bool, + default = False, + flags = Flags.Design) cls._register_attribute(critical) + cls._register_attribute(hard_release) @classmethod def _register_traces(cls): @@ -266,7 +274,6 @@ class ResourceManager(Logger): """ return copy.deepcopy(cls._attributes[name]) - @classmethod def get_traces(cls): """ Returns a copy of the traces @@ -289,6 +296,32 @@ class ResourceManager(Logger): """ return cls._backend + @classmethod + def get_global(cls, name): + """ Returns the value of a global attribute + Global attribute meaning an attribute for + all the resources from a rtype + + :param name: Name of the attribute + :type name: str + :rtype: str + """ + global_attr = cls._attributes[name] + return global_attr.value + + @classmethod + def set_global(cls, name, value): + """ Set value for a global attribute + + :param name: Name of the attribute + :type name: str + :param name: Value of the attribute + :type name: str + """ + global_attr = cls._attributes[name] + global_attr.value = value + return value + def __init__(self, ec, guid): super(ResourceManager, self).__init__(self.get_rtype()) @@ -319,7 +352,7 @@ class ResourceManager(Logger): # instance lock to synchronize exclusive state change methods (such # as deploy and release methods), in order to prevent them from being - # executed at the same time + # executed at the same time and corrupt internal resource state self._release_lock = threading.Lock() @property @@ -395,7 +428,7 @@ class ResourceManager(Logger): :rtype: str """ - return " %s guid: %d - %s " % (self._rtype, self.guid, msg) + return " %s guid %d - %s " % (self._rtype, self.guid, msg) def register_connection(self, guid): """ Registers a connection to the RM identified by guid @@ -531,7 +564,7 @@ class ResourceManager(Logger): err = traceback.format_exc() self.error(err) - self.set_released() + self.set_released() def fail(self): """ Sets the RM to state FAILED. @@ -554,6 +587,7 @@ class ResourceManager(Logger): """ attr = self._attrs[name] attr.value = value + return value def get(self, name): """ Returns the value of the attribute @@ -563,6 +597,13 @@ class ResourceManager(Logger): :rtype: str """ attr = self._attrs[name] + + """ + A.Q. Commenting due to performance impact + if attr.has_flag(Flags.Global): + self.warning( "Attribute %s is global. Use get_global instead." % name) + """ + return attr.value def has_changed(self, name): @@ -576,6 +617,23 @@ class ResourceManager(Logger): attr = self._attrs[name] return attr.has_changed() + def has_flag(self, name, flag): + """ Returns true if the attribute has the flag 'flag' + + :param flag: Flag to be checked + :type flag: Flags + """ + attr = self._attrs[name] + return attr.has_flag(flag) + + def has_attribute(self, name): + """ Returns true if the RM has an attribute with name + + :param name: name of the attribute + :type name: string + """ + return name in self._attrs + def enable_trace(self, name): """ Explicitly enable trace generation @@ -687,11 +745,22 @@ class ResourceManager(Logger): rclass = ResourceFactory.get_resource_type(rtype) for guid in self.connections: rm = self.ec.get_resource(guid) - if not rtype or isinstance(rm, rclass): connected.append(rm) return connected + def is_rm_instance(self, rtype): + """ Returns True if the RM is instance of 'rtype' + + :param rtype: Type of the RM we look for + :type rtype: str + :return: True|False + """ + rclass = ResourceFactory.get_resource_type(rtype) + if isinstance(self, rclass): + return True + return False + @failtrap def _needs_reschedule(self, group, state, time): """ Internal method that verify if 'time' has elapsed since @@ -823,12 +892,12 @@ class ResourceManager(Logger): # Verify all start conditions are met for (group, state, time) in start_conditions: # Uncomment for debug - unmet = [] - for guid in group: - rm = self.ec.get_resource(guid) - unmet.append((guid, rm._state)) - - self.debug("---- WAITED STATES ---- %s" % unmet ) + #unmet = [] + #for guid in group: + # rm = self.ec.get_resource(guid) + # unmet.append((guid, rm._state)) + # + #self.debug("---- WAITED STATES ---- %s" % unmet ) reschedule, delay = self._needs_reschedule(group, state, time) if reschedule: @@ -888,6 +957,7 @@ class ResourceManager(Logger): # only can deploy when RM is either NEW, DISCOVERED or PROVISIONED if self.state not in [ResourceState.NEW, ResourceState.DISCOVERED, ResourceState.PROVISIONED]: + #### XXX: A.Q. IT SHOULD FAIL IF DEPLOY IS CALLED IN OTHER STATES! reschedule = True self.debug("---- RESCHEDULING DEPLOY ---- state %s " % self.state ) else: @@ -956,54 +1026,60 @@ class ResourceManager(Logger): self.set_ready() def do_release(self): - pass + self.set_released() def do_fail(self): self.set_failed() + self.ec.inform_failure(self.guid) - def set_started(self): + def set_started(self, time = None): """ Mark ResourceManager as STARTED """ - self.set_state(ResourceState.STARTED, "_start_time") + self.set_state(ResourceState.STARTED, "_start_time", time) self.debug("----- STARTED ---- ") - - def set_stopped(self): + + def set_stopped(self, time = None): """ Mark ResourceManager as STOPPED """ - self.set_state(ResourceState.STOPPED, "_stop_time") + self.set_state(ResourceState.STOPPED, "_stop_time", time) self.debug("----- STOPPED ---- ") - def set_ready(self): + def set_ready(self, time = None): """ Mark ResourceManager as READY """ - self.set_state(ResourceState.READY, "_ready_time") + self.set_state(ResourceState.READY, "_ready_time", time) self.debug("----- READY ---- ") - def set_released(self): + def set_released(self, time = None): """ Mark ResourceManager as REALEASED """ - self.set_state(ResourceState.RELEASED, "_release_time") + self.set_state(ResourceState.RELEASED, "_release_time", time) self.debug("----- RELEASED ---- ") - def set_failed(self): + def set_failed(self, time = None): """ Mark ResourceManager as FAILED """ - self.set_state(ResourceState.FAILED, "_failed_time") + self.set_state(ResourceState.FAILED, "_failed_time", time) self.debug("----- FAILED ---- ") - def set_discovered(self): + def set_discovered(self, time = None): """ Mark ResourceManager as DISCOVERED """ - self.set_state(ResourceState.DISCOVERED, "_discover_time") + self.set_state(ResourceState.DISCOVERED, "_discover_time", time) self.debug("----- DISCOVERED ---- ") - def set_provisioned(self): + def set_provisioned(self, time = None): """ Mark ResourceManager as PROVISIONED """ - self.set_state(ResourceState.PROVISIONED, "_provision_time") + self.set_state(ResourceState.PROVISIONED, "_provision_time", time) self.debug("----- PROVISIONED ---- ") - def set_state(self, state, state_time_attr): + def set_state(self, state, state_time_attr, time = None): """ Set the state of the RM while keeping a trace of the time """ # Ensure that RM state will not change after released if self._state == ResourceState.RELEASED: return - - setattr(self, state_time_attr, tnow()) + + time = time or tnow() + self.set_state_time(state, state_time_attr, time) + + def set_state_time(self, state, state_time_attr, time): + """ Set the time for the RM state change """ + setattr(self, state_time_attr, time) self._state = state class ResourceFactory(object): @@ -1031,7 +1107,7 @@ class ResourceFactory(object): return rclass(ec, guid) def populate_factory(): - """Register all the possible RM that exists in the current version of Nepi. + """Find and rgister all available RMs """ # Once the factory is populated, don't repopulate if not ResourceFactory.resource_types():