# # NEPI, a framework to manage network experiments # Copyright (C) 2013 INRIA # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as # published by the Free Software Foundation; # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Authors: Alina Quereilhac # Julien Tribino from nepi.execution.attribute import Attribute, Flags, Types from nepi.execution.resource import ResourceManager, clsinit_copy, \ ResourceState #clsinit_copy is used to inherit attributes from the parent class @clsinit_copy class RMClass(ResourceManager): # Name that will be used in the NEPI script to identify the resource type _rtype = "platform::RMType" # User friendly description of the RM _help = "Describes what this RM does" # Name of the platform this RM belongs to _platform = "platform" # list of valid connection for this RM _authorized_connections = ["platform::AnotherRMType1" , "platform::AnotherRMType2"] @classmethod def _register_attributes(cls): """ This method is used to register all the attribute of this RM. Check the file src/execution/attribute.py to see all the fields of this class """ attribute1 = Attribute("nameOfAttribute1", "Description of Attribute 1", flags = Flags.Design) attribute2 = Attribute("nameOfAttribute2", "Description of Attribute 2", flags = Flags.Design) cls._register_attribute(attribute1) cls._register_attribute(attribute2) def __init__(self, ec, guid): """ Declares and initializes variables of the RM that are not Attributes. Attributes represent resource configuration exposed to the user, other class variables can declared here for RM internal use. """ super(RMClass, self).__init__(ec, guid) def log_message(self, msg): """ Prints a log message adding a identification prefix. The log message for the RMClass can be redefined here. It can be used to add information about related resources such as the hostname of the node RM associated to an application RM. """ return " %s guid %d - %s " % (self._rtype, self.guid, msg) def valid_connection(self, guid): """ Checks whether the RMClass instance can be connected to the other RM corresponding to the given guid. """ rm = self.ec.get_resource(guid) if rm.get_rtype() not in self._authorized_connections: msg = ("Connection between %s %s and %s %s refused: " "An Application can be connected only to a Node" ) % \ (self.get_rtype(), self._guid, rm.get_rtype(), guid) return False elif len(self.connections) != 0 : msg = ("Connection between %s %s and %s %s refused: " "This Application is already connected" ) % \ (self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return False return True def do_discover(self): """ Perform actions required to discover resources matching some criteria specified by the user through the configuration of Attributes. """ super(RMClass, self).do_discover() def do_reserve(self): """ Perform actions required to reserve resources matching some criteria specified by the user through the configuration of Attributes. """ super(RMClass, self).do_reserve() def do_provision(self): """ Perform actions required to provision a resource in the platform, matching the criteria specified by the user. """ super(RMClass, self).do_provision() def do_deploy(self): """ Perform actions required to deploy a resource in the platform. Deploying a resource most frequently involves invoking the do_discover and do_provision methods. In order to deploy a resource it might be necessary wait until other associated resource is in a given state, as in the following example: other_rm_list = self.get_connected(OtherRMClass.get_rtype()) other_rm = other_rm_list[0] if other_rm.state < ResourceState.READY: self.ec.schedule(self.reschedule_delay, self.deploy) elif other_rm.state == ResourceState.FAILED: msg = "Failed to deploy resource" self.error(msg) raise RuntimeError(msg) else: self.do_discover() self.do_provision() super(RMClass, self).do_deploy() """ super(RMClass, self).do_deploy() def do_start(self): """ Perform actions required to start a resource in the platform. """ super(RMClass, self).do_start() def do_stop(self): """ Perform actions required to stop a resource in the platform. """ super(RMClass, self).do_stop() def do_release(self): """ Perform actions required to release a resource in the platform. """ super(RMClass, self).do_release() @property def state(self): """ Returns the state of the RM. The state method should never raise an exception, instead if an error occurs it should log the error and invoke the self.do_fail method as follows: self.error(msg, out, err) self.do_fail() """ return super(RMClass, self).state