From: Alina Quereilhac Date: Thu, 21 Nov 2013 19:26:47 +0000 (+0100) Subject: Replacing RM.rtype() for RM.get_type() for consistency X-Git-Tag: nepi-3.0.0~13 X-Git-Url: http://git.onelab.eu/?p=nepi.git;a=commitdiff_plain;h=752d0aaffb889011159fef73c02d838e538d7144 Replacing RM.rtype() for RM.get_type() for consistency --- diff --git a/doc/user_manual/ec_api.tex b/doc/user_manual/ec_api.tex index 68599dd3..4c3cd25a 100644 --- a/doc/user_manual/ec_api.tex +++ b/doc/user_manual/ec_api.tex @@ -21,22 +21,205 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{itemize} - \item EC API - \begin{itemize} - \item register resource - \item RM States (State transition DIAGRAM) - \item RM Actions - \item Attributes - \item The critical attribute - \item Traces (how to collect traces to the local repo, talk about the Collector RM) - \item deploy (interactive deployment) - \item workflow - register condition - \end{itemize} - \item Resource Factory - \begin{itemize} - \item Populate factory (happens automatically) - \item How to discover available rm types and their resources - \end{itemize} -\end{itemize} +The ExperimentController (EC) is the entity in charge of turning the +experiment description into a running experiment. +In order to do this the EC needs to know which resources are to be +used, how they should be configured and how resources relate to one another. +To this pourpose the EC exposes methods to register resources, specify their +configuration, and register dependencies between. These methods are part of +the EC design API. +Likewise, in order to deploy and control resources, and collect data, +the EC exposes another set of methods, which form the execution API. +These two APIs are described in detail in the rest of this chapter. + +\section{The experiment script} + +NEPI is a Python-based language and all classes and functions can +be used by importing the \emph{nepi} module from a Python script. + +In particular, the ExperimentController class can be imported as follows: + +\begin{lstlisting}[language=Python] + +from nepi.execution.ec import ExperimentController + +\end{lstlisting} + +Once this is done, an ExperimentController instance must be instantiated +for a particular experiment. The ExperimentController constructor receives +the optional argument \emph{exp\_id}. This argument is important because +it defines the experiment identity and allows to distinguish among different +experiments. If an experiment id is not explicitly given, NEPI will automatically +generate a unique id for the experiment. + +\begin{lstlisting}[language=Python] + +ec = ExperimentController(exp_id = "my-exp-id") + +\end{lstlisting} + +The experiment id can always be retrieved as follows + +\begin{lstlisting}[language=Python] + +exp_id = ec.exp_id + +\end{lstlisting} + +%TODO: What is the run_id ?? + +\section{The design API} + +Once an ExperimentController has been instantiated, it is possible to start +describing the experiment. The design API is the set of methods which +allow to do so. + +\subsection{Registering resources} + +Every resource supported by NEPI is controlled by a specific ResourceManager +(RM). The RM instances are automatically created by the EC, and the user does +not need to interact with them directly. + +Each type of RM is associated with a \emph{type\_id} which uniquely identifies +a concrete kind of resource (e.g PlanetLab node, application that runs in +a Linux machine, etc). +The \emph{type\_ids} are string identifiers, and they are required +to register a resource with the EC. + +To discover all the available RMs and their \emph{type\_ids} we +can make use of the ResourceFactory class. +This class is a \emph{Singleton} that holds the templates and information +of all the RMs supported by NEPI. We can retrieve this information as follows: + +\begin{lstlisting}[language=Python] + +from nepi.execution.resource import ResourceFactory + +for type_id in ResourceFactory.resource_types(): + rm_type = ResourceFactory.get_resource_type(type_id) + print type_id, ":", rm_type.get_help() + +\end{lstlisting} + +Once the \emph{type\_id} of the resource is known, the registration of a +new resource with the EC is simple: + +\begin{lstlisting}[language=Python] + +type_id = "SomeRMType" +guid = ec.register_resources(type_id) + +\end{lstlisting} + +When a resource is registered, the EC instantiates a RM of the +requested \emph{type\_id} and assigns a global unique identifier +(guid) to it. The guid is an incremental integer number and it +is the value returned by the \emph{register\_resource} method. +The EC keeps internal references to all RMs, which the user can +reference using the corresponding guid value. + +\subsection{Attributes} + +ResourceManagers expose the configurable parameters of resources +through a list of attributes. An attribute can be seen as a +\emph{{name:value}} pair, that represents a certain aspect of +the resource (whether information or configuration information). + +It is possible to discover the list of attributes exposed by an +RM type as follows: + +\begin{lstlisting}[language=Python] +from nepi.execution.resource import ResourceFactory + +type_id = "SomeRMType" +rm_type = ResourceFactory.get_resource_type(type_id) + +for attr in rm_type.get_attributes(): + print " ", attr.name, ":", attr.help + +\end{lstlisting} + +To configure or retrieve the value of a certain attribute of +an registered resource we can use the \emph{get} and \emph{set} +methods of the EC. + +\begin{lstlisting}[language=Python] + +old_value = ec.get(guid, "attr_name") +ec.set(guid, "attr_name", new_value) +new_value = ec.get(guid, "attr_name") + +\end{lstlisting} + +% Critical attribute +Since each RM type exposes the characteristics of a particular type +of resource, it is to be expected that different RMs will have different +attributes. However, there a particular attribute that is common to all RMs. +This is the \emph{critical} attribute, and it is meant to indicate to the EC +how it should behave when a failure occurs during the experiment. +The \emph{critical} attribute has a default value of \emph{True}, since +all resources are considered critical by default. +When this attribute is set to \emph{False} the EC will ignore failures on that +resource and carry on with the experiment. Otherwise, the EC will immediately +interrupt the experiment. + +\subsection{Traces} + +A Trace represent a stream of data collected during the experiment and associated +to a single resource. ResourceManagers expose a list of traces, which are identified +by a name. Particular traces might or might not need activation, since some traces +are enabled by default. + +It is possible to discover the list of traces exposed by an +RM type as follows: + +\begin{lstlisting}[language=Python] +from nepi.execution.resource import ResourceFactory + +type_id = "SomeRMType" +rm_type = ResourceFactory.get_resource_type(type_id) + +for trace in rm_type.get_traces(): + print " ", trace.name, ":", trace.enabled + +\end{lstlisting} + +The \emph{enable\_trace} method allows to enable a specific trace for a +RM instance + +\begin{lstlisting}[language=Python] + +ec.enable_trace(guid, "trace-name") + +print ec.trace_enabled(guid, "trace-name") + +\end{lstlisting} + +\subsection{Registering connections} + +\subsection{States and actions} + +\subsection{Registering conditions} + +\section{The execution API} + +\subsection{Deploying an experiment} + +%TODO: Talk about groups +%TODO: Talk about interactive deploymet + +\subsection{Getting attributes} + +\subsection{Quering the state} + +\subsection{Getting traces} + +% TODO: Give examples of Traces (how to collect traces to the local repo, talk about the Collector RM) + +% how to retrieve an application trace when the Node failed? (critical attribute) + +\subsection{The collector RM} + + + diff --git a/doc/user_manual/release_cycle.tex b/doc/user_manual/release_cycle.tex index 7b628d2b..358b03da 100644 --- a/doc/user_manual/release_cycle.tex +++ b/doc/user_manual/release_cycle.tex @@ -20,6 +20,39 @@ % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Releases in NEPI do not occur in strictly regular periods. Usually a new +release will be done every 4 or 5 months. + +\section{The development branch} + +The main development branch for NEPI 3 is \emph{nepi-3-dev}. +There might be other branches to develop new features, but they will +eventually end up being merged into the \emph{nepi-3-dev} branch. + +\section{Versioning} + +Releases are named following the \emph{major.minor.revision} convention. +The \emph{major} number reflects a major change in functionality or architecture. +It is to be expected that this number will remind in 3 for a long period. + +The \emph{minor} number reflects the incorporation of new features into NEPI. +This number is expected to be increased on each release. + +The \emph{revision} number is incremented when a considerable number of +bugs have been fixed. No release will be done when only the \emph{revision} +number is incremented. + +\section{The release process} + +The creation of a new NEPI release will always follow the same sequence of steps. + +\begin{enumerate} + \item A new \emph{nepi-3.-pre-release} branch will be created from the \emph{nepi-3-dev} branch + \item During two to three weeks intensive work on testing will be carried out on the new branch. No new functionality will be added on this branch and only changes that fix bugs will be accepted. + \item At the end of this period, the pre-release branch will be branched again into the release branch, named \emph{nepi-3.-release} + \item A tag will be added to this new branch including the revision number (i.e. \emph{release-3..}) + \item Finally, the pre-release branch will be merged into the development branch, nepi-3-dev, to incorporate to it all the bug fixes. +\end{enumerate} + %%TODO: Explain how to create patch -TODO diff --git a/doc/user_manual/user_manual.pdf b/doc/user_manual/user_manual.pdf index 7a2b5573..44dd84b4 100644 Binary files a/doc/user_manual/user_manual.pdf and b/doc/user_manual/user_manual.pdf differ diff --git a/doc/user_manual/user_manual.tex b/doc/user_manual/user_manual.tex index 7dbf1e9a..bb1da3f4 100644 --- a/doc/user_manual/user_manual.tex +++ b/doc/user_manual/user_manual.tex @@ -184,9 +184,9 @@ %%\label{unit_testing} %%\input{unit_testing.tex} -%%\chapter{Release Cycle} -%%\label{release_cycle} -%%\input{release_cycle.tex} +\chapter{Release Cycle} +\label{release_cycle} +\input{release_cycle.tex} %%\chapter{Coding Style} %%\label{coding_style} diff --git a/src/nepi/execution/ec.py b/src/nepi/execution/ec.py index ec216b76..aa835179 100644 --- a/src/nepi/execution/ec.py +++ b/src/nepi/execution/ec.py @@ -326,7 +326,7 @@ class ExperimentController(object): guids.remove(guid) rm = self.get_resource(guid) self.logger.debug(" %s guid %d DONE - state is %s, required is >= %s " % ( - rm.rtype(), guid, hrrstate, hrstate)) + rm.get_rtype(), guid, hrrstate, hrstate)) else: # Debug... self.logger.debug(" WAITING FOR guid %d - state is %s, required is >= %s " % ( diff --git a/src/nepi/execution/resource.py b/src/nepi/execution/resource.py index 325895ab..a6238b13 100644 --- a/src/nepi/execution/resource.py +++ b/src/nepi/execution/resource.py @@ -248,7 +248,7 @@ class ResourceManager(Logger): cls._register_traces() @classmethod - def rtype(cls): + def get_rtype(cls): """ Returns the type of the Resource Manager """ @@ -284,7 +284,7 @@ class ResourceManager(Logger): return cls._backend def __init__(self, ec, guid): - super(ResourceManager, self).__init__(self.rtype()) + super(ResourceManager, self).__init__(self.get_rtype()) self._guid = guid self._ec = weakref.ref(ec) @@ -1032,7 +1032,7 @@ class ResourceFactory(object): @classmethod def register_type(cls, rclass): """Register a new Ressource Manager""" - cls._resource_types[rclass.rtype()] = rclass + cls._resource_types[rclass.get_rtype()] = rclass @classmethod def create(cls, rtype, ec, guid): diff --git a/src/nepi/execution/trace.py b/src/nepi/execution/trace.py index 19065dbe..4ad57746 100644 --- a/src/nepi/execution/trace.py +++ b/src/nepi/execution/trace.py @@ -37,10 +37,10 @@ class Trace(object): """ - def __init__(self, name, help): + def __init__(self, name, help, enabled = False): self._name = name self._help = help - self.enabled = False + self.enabled = enabled @property def name(self): diff --git a/src/nepi/resources/linux/application.py b/src/nepi/resources/linux/application.py index c1de5432..8cac699a 100644 --- a/src/nepi/resources/linux/application.py +++ b/src/nepi/resources/linux/application.py @@ -163,8 +163,8 @@ class LinuxApplication(ResourceManager): @classmethod def _register_traces(cls): - stdout = Trace("stdout", "Standard output stream") - stderr = Trace("stderr", "Standard error stream") + stdout = Trace("stdout", "Standard output stream", enabled = True) + stderr = Trace("stderr", "Standard error stream", enabled = True) cls._register_trace(stdout) cls._register_trace(stderr) @@ -194,7 +194,7 @@ class LinuxApplication(ResourceManager): @property def node(self): - node = self.get_connected(LinuxNode.rtype()) + node = self.get_connected(LinuxNode.get_rtype()) if node: return node[0] return None diff --git a/src/nepi/resources/linux/ccn/ccnapplication.py b/src/nepi/resources/linux/ccn/ccnapplication.py index ec5312ec..89c949c5 100644 --- a/src/nepi/resources/linux/ccn/ccnapplication.py +++ b/src/nepi/resources/linux/ccn/ccnapplication.py @@ -35,7 +35,7 @@ class LinuxCCNApplication(LinuxApplication): @property def ccnd(self): - ccnd = self.get_connected(LinuxCCND.rtype()) + ccnd = self.get_connected(LinuxCCND.get_rtype()) if ccnd: return ccnd[0] return None diff --git a/src/nepi/resources/linux/ccn/ccncontent.py b/src/nepi/resources/linux/ccn/ccncontent.py index 2595edac..84f61857 100644 --- a/src/nepi/resources/linux/ccn/ccncontent.py +++ b/src/nepi/resources/linux/ccn/ccncontent.py @@ -58,7 +58,7 @@ class LinuxCCNContent(LinuxApplication): @property def ccnr(self): - ccnr = self.get_connected(LinuxCCNR.rtype()) + ccnr = self.get_connected(LinuxCCNR.get_rtype()) if ccnr: return ccnr[0] return None diff --git a/src/nepi/resources/linux/ccn/ccnping.py b/src/nepi/resources/linux/ccn/ccnping.py index 934db3cd..f654a2ab 100644 --- a/src/nepi/resources/linux/ccn/ccnping.py +++ b/src/nepi/resources/linux/ccn/ccnping.py @@ -61,7 +61,7 @@ class LinuxCCNPing(LinuxCCNPingServer): @property def ccnpingserver(self): - ccnpingserver = self.get_connected(LinuxCCNPingServer.rtype()) + ccnpingserver = self.get_connected(LinuxCCNPingServer.get_rtype()) if ccnpingserver: return ccnpingserver[0] return None diff --git a/src/nepi/resources/linux/ccn/ccnr.py b/src/nepi/resources/linux/ccn/ccnr.py index 6213b74e..e65779aa 100644 --- a/src/nepi/resources/linux/ccn/ccnr.py +++ b/src/nepi/resources/linux/ccn/ccnr.py @@ -191,7 +191,7 @@ class LinuxCCNR(LinuxApplication): @property def ccnd(self): - ccnd = self.get_connected(LinuxCCND.rtype()) + ccnd = self.get_connected(LinuxCCND.get_rtype()) if ccnd: return ccnd[0] return None diff --git a/src/nepi/resources/linux/ccn/fibentry.py b/src/nepi/resources/linux/ccn/fibentry.py index 1010f2f4..cebc1054 100644 --- a/src/nepi/resources/linux/ccn/fibentry.py +++ b/src/nepi/resources/linux/ccn/fibentry.py @@ -90,7 +90,7 @@ class LinuxFIBEntry(LinuxApplication): @property def ccnd(self): - ccnd = self.get_connected(LinuxCCND.rtype()) + ccnd = self.get_connected(LinuxCCND.get_rtype()) if ccnd: return ccnd[0] return None diff --git a/src/nepi/resources/linux/interface.py b/src/nepi/resources/linux/interface.py index 59bbe2aa..7b8eadc9 100644 --- a/src/nepi/resources/linux/interface.py +++ b/src/nepi/resources/linux/interface.py @@ -92,13 +92,13 @@ class LinuxInterface(ResourceManager): @property def node(self): - node = self.get_connected(LinuxNode.rtype()) + node = self.get_connected(LinuxNode.get_rtype()) if node: return node[0] return None @property def channel(self): - chan = self.get_connected(LinuxChannel.rtype()) + chan = self.get_connected(LinuxChannel.get_rtype()) if chan: return chan[0] return None diff --git a/src/nepi/resources/linux/node.py b/src/nepi/resources/linux/node.py index b547ce55..cbc0099e 100644 --- a/src/nepi/resources/linux/node.py +++ b/src/nepi/resources/linux/node.py @@ -298,24 +298,16 @@ class LinuxNode(ResourceManager): # To work arround this, repeat the operation N times or # until the result is not empty string out = "" - retrydelay = 1.0 - for i in xrange(2): - try: - (out, err), proc = self.execute("cat /etc/issue", - retry = 5, - with_lock = True, - blocking = True) - - if out.strip() != "": - return out - except: - trace = traceback.format_exc() - msg = "Error detecting OS: %s " % trace - self.error(msg, out, err) - return False - - time.sleep(min(30.0, retrydelay)) - retrydelay *= 1.5 + try: + (out, err), proc = self.execute("cat /etc/issue", + with_lock = True, + blocking = True) + except: + trace = traceback.format_exc() + msg = "Error detecting OS: %s " % trace + self.error(msg, out, err) + + return out @property def use_deb(self): @@ -368,7 +360,7 @@ class LinuxNode(ResourceManager): # Node needs to wait until all associated interfaces are # ready before it can finalize deployment from nepi.resources.linux.interface import LinuxInterface - ifaces = self.get_connected(LinuxInterface.rtype()) + ifaces = self.get_connected(LinuxInterface.get_rtype()) for iface in ifaces: if iface.state < ResourceState.READY: self.ec.schedule(reschedule_delay, self.deploy) @@ -963,35 +955,25 @@ class LinuxNode(ResourceManager): return True out = err = "" + msg = "Unresponsive host. Wrong answer. " + # The underlying SSH layer will sometimes return an empty # output (even if the command was executed without errors). # To work arround this, repeat the operation N times or # until the result is not empty string - retrydelay = 1.0 - for i in xrange(2): - try: - (out, err), proc = self.execute("echo 'ALIVE'", - retry = 5, - blocking = True, - with_lock = True) - - if out.find("ALIVE") > -1: - return True - except: - trace = traceback.format_exc() - msg = "Unresponsive host. Error reaching host: %s " % trace - self.error(msg, out, err) - return False - - time.sleep(min(30.0, retrydelay)) - retrydelay *= 1.5 + try: + (out, err), proc = self.execute("echo 'ALIVE'", + blocking = True, + with_lock = True) + + if out.find("ALIVE") > -1: + return True + except: + trace = traceback.format_exc() + msg = "Unresponsive host. Error reaching host: %s " % trace - if out.find("ALIVE") > -1: - return True - else: - msg = "Unresponsive host. Wrong answer. " - self.error(msg, out, err) - return False + self.error(msg, out, err) + return False def find_home(self): """ Retrieves host home directory @@ -1000,28 +982,19 @@ class LinuxNode(ResourceManager): # output (even if the command was executed without errors). # To work arround this, repeat the operation N times or # until the result is not empty string - retrydelay = 1.0 - for i in xrange(2): - try: - (out, err), proc = self.execute("echo ${HOME}", - retry = 5, - blocking = True, - with_lock = True) - - if out.strip() != "": - self._home_dir = out.strip() - break - except: - trace = traceback.format_exc() - msg = "Impossible to retrieve HOME directory" % trace - self.error(msg, out, err) - return False - - time.sleep(min(30.0, retrydelay)) - retrydelay *= 1.5 + msg = "Impossible to retrieve HOME directory" + try: + (out, err), proc = self.execute("echo ${HOME}", + blocking = True, + with_lock = True) + + if out.strip() != "": + self._home_dir = out.strip() + except: + trace = traceback.format_exc() + msg = "Impossible to retrieve HOME directory" % trace if not self._home_dir: - msg = "Impossible to retrieve HOME directory" self.error(msg, out, err) raise RuntimeError, msg diff --git a/src/nepi/resources/omf/application.py b/src/nepi/resources/omf/application.py index 6ce9923f..65f1f4a2 100644 --- a/src/nepi/resources/omf/application.py +++ b/src/nepi/resources/omf/application.py @@ -102,7 +102,7 @@ class OMFApplication(OMFResource): @property def node(self): - rm_list = self.get_connected(OMFNode.rtype()) + rm_list = self.get_connected(OMFNode.get_rtype()) if rm_list: return rm_list[0] return None @@ -124,10 +124,10 @@ class OMFApplication(OMFResource): """ rm = self.ec.get_resource(guid) - if rm.rtype() not in self._authorized_connections: + 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.rtype(), self._guid, rm.rtype(), guid) + (self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return False @@ -135,14 +135,14 @@ class OMFApplication(OMFResource): elif len(self.connections) != 0 : msg = ("Connection between %s %s and %s %s refused: " "This Application is already connected" ) % \ - (self.rtype(), self._guid, rm.rtype(), guid) + (self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return False else : msg = "Connection between %s %s and %s %s accepted" % ( - self.rtype(), self._guid, rm.rtype(), guid) + self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return True @@ -195,7 +195,7 @@ class OMFApplication(OMFResource): self.set('env', " ") # Some information to check the information in parameter - msg = " " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \ + msg = " " + self.get_rtype() + " ( Guid : " + str(self._guid) +") : " + \ self.get('appid') + " : " + self.get('path') + " : " + \ self.get('args') + " : " + self.get('env') self.info(msg) diff --git a/src/nepi/resources/omf/channel.py b/src/nepi/resources/omf/channel.py index 707c95c4..17478fda 100644 --- a/src/nepi/resources/omf/channel.py +++ b/src/nepi/resources/omf/channel.py @@ -85,14 +85,14 @@ class OMFChannel(OMFResource): """ rm = self.ec.get_resource(guid) - if rm.rtype() in self._authorized_connections: + if rm.get_rtype() in self._authorized_connections: msg = "Connection between %s %s and %s %s accepted" % ( - self.rtype(), self._guid, rm.rtype(), guid) + self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return True msg = "Connection between %s %s and %s %s refused" % ( - self.rtype(), self._guid, rm.rtype(), guid) + self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return False @@ -112,7 +112,7 @@ class OMFChannel(OMFResource): rm_iface = self.ec.get_resource(elt) for conn in rm_iface.connections: rm_node = self.ec.get_resource(conn) - if rm_node.rtype() == "OMFNode" and rm_node.get('hostname'): + if rm_node.get_rtype() == "OMFNode" and rm_node.get('hostname'): if rm_iface.state < ResourceState.PROVISIONED or \ rm_node.state < ResourceState.READY: return "reschedule" diff --git a/src/nepi/resources/omf/interface.py b/src/nepi/resources/omf/interface.py index 46d5ea1a..cd2fb9d1 100644 --- a/src/nepi/resources/omf/interface.py +++ b/src/nepi/resources/omf/interface.py @@ -93,15 +93,15 @@ class OMFWifiInterface(OMFResource): """ rm = self.ec.get_resource(guid) - if rm.rtype() in self._authorized_connections: + if rm.get_rtype() in self._authorized_connections: msg = "Connection between %s %s and %s %s accepted" % \ - (self.rtype(), self._guid, rm.rtype(), guid) + (self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return True msg = "Connection between %s %s and %s %s refused" % \ - (self.rtype(), self._guid, rm.rtype(), guid) + (self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return False @@ -112,13 +112,13 @@ class OMFWifiInterface(OMFResource): @property def node(self): - rm_list = self.get_connected(OMFNode.rtype()) + rm_list = self.get_connected(OMFNode.get_rtype()) if rm_list: return rm_list[0] return None @property def channel(self): - rm_list = self.get_connected(OMFChannel.rtype()) + rm_list = self.get_connected(OMFChannel.get_rtype()) if rm_list: return rm_list[0] return None @@ -187,7 +187,7 @@ class OMFWifiInterface(OMFResource): raise RuntimeError, msg # Just for information - self.debug(" " + self.rtype() + " ( Guid : " + str(self._guid) +") : " + \ + self.debug(" " + self.get_rtype() + " ( Guid : " + str(self._guid) +") : " + \ self.get('mode') + " : " + self.get('type') + " : " + \ self.get('essid') + " : " + self.get('ip')) diff --git a/src/nepi/resources/omf/node.py b/src/nepi/resources/omf/node.py index daa87435..a028d7bb 100644 --- a/src/nepi/resources/omf/node.py +++ b/src/nepi/resources/omf/node.py @@ -83,15 +83,15 @@ class OMFNode(OMFResource): """ rm = self.ec.get_resource(guid) - if rm.rtype() in self._authorized_connections: + if rm.get_rtype() in self._authorized_connections: msg = "Connection between %s %s and %s %s accepted" % ( - self.rtype(), self._guid, rm.rtype(), guid) + self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return True msg = "Connection between %s %s and %s %s refused" % ( - self.rtype(), self._guid, rm.rtype(), guid) + self.get_rtype(), self._guid, rm.get_rtype(), guid) self.debug(msg) return False diff --git a/src/nepi/resources/planetlab/openvswitch/ovs.py b/src/nepi/resources/planetlab/openvswitch/ovs.py index 32552e0a..a201329e 100644 --- a/src/nepi/resources/planetlab/openvswitch/ovs.py +++ b/src/nepi/resources/planetlab/openvswitch/ovs.py @@ -72,7 +72,7 @@ class OVSWitch(LinuxApplication): @property def node(self): - node = self.get_connected(PlanetlabNode.rtype()) + node = self.get_connected(PlanetlabNode.get_rtype()) if node: return node[0] return None @@ -101,13 +101,13 @@ class OVSWitch(LinuxApplication): # """ # rm = self.ec.get_resource(guid) -# if rm.rtype() in self._authorized_connections: +# if rm.get_rtype() in self._authorized_connections: # msg = "Connection between %s %s and %s %s accepted" % \ -# (self.rtype(), self._guid, rm.rtype(), guid) +# (self.get_rtype(), self._guid, rm.get_rtype(), guid) # self.debug(msg) # return True # msg = "Connection between %s %s and %s %s refused" % \ -# (self.rtype(), self._guid, rm.rtype(), guid) +# (self.get_rtype(), self._guid, rm.get_rtype(), guid) # self.debug(msg) # return False @@ -291,7 +291,7 @@ class OVSWitch(LinuxApplication): # Node needs to wait until all associated RMs are released # to be released from nepi.resources.planetlab.openvswitch.ovsport import OVSPort - rm = self.get_connected(OVSPort.rtype()) + rm = self.get_connected(OVSPort.get_rtype()) if rm[0].state < ResourceState.FINISHED: self.ec.schedule(reschedule_delay, self.release) diff --git a/src/nepi/resources/planetlab/openvswitch/ovsport.py b/src/nepi/resources/planetlab/openvswitch/ovsport.py index a78c66aa..bb84af62 100644 --- a/src/nepi/resources/planetlab/openvswitch/ovsport.py +++ b/src/nepi/resources/planetlab/openvswitch/ovsport.py @@ -69,16 +69,16 @@ class OVSPort(LinuxApplication): @property def node(self): - rm_list = self.get_connected(OVSWitch.rtype()) + rm_list = self.get_connected(OVSWitch.get_rtype()) if rm_list: for elt in rm_list: - node = elt.get_connected(PlanetlabNode.rtype()) + node = elt.get_connected(PlanetlabNode.get_rtype()) if node: return node[0] return node[0] @property def ovswitch(self): - ovswitch = self.get_connected(OVSWitch.rtype()) + ovswitch = self.get_connected(OVSWitch.get_rtype()) if ovswitch: return ovswitch[0] return None @@ -99,11 +99,11 @@ class OVSPort(LinuxApplication): # """ # rm = self.ec.get_resource(guid) -# if rm.rtype() in self._authorized_connections: -# msg = "Connection between %s %s and %s %s accepted" % (self.rtype(), self._guid, rm.rtype(), guid) +# if rm.get_rtype() in self._authorized_connections: +# msg = "Connection between %s %s and %s %s accepted" % (self.get_rtype(), self._guid, rm.get_rtype(), guid) # self.debug(msg) # return True -# msg = "Connection between %s %s and %s %s refused" % (self.rtype(), self._guid, rm.rtype(), guid) +# msg = "Connection between %s %s and %s %s refused" % (self.get_rtype(), self._guid, rm.get_rtype(), guid) # self.debug(msg) def get_host_ip(self): @@ -207,7 +207,7 @@ class OVSPort(LinuxApplication): # OVS needs to wait until all associated RMs are released # to be released from nepi.resources.planetlab.openvswitch.tunnel import OVSTunnel - rm = self.get_connected(OVSTunnel.rtype()) + rm = self.get_connected(OVSTunnel.get_rtype()) if rm and rm[0].state < ResourceState.FINISHED: self.ec.schedule(reschedule_delay, self.release) diff --git a/src/nepi/resources/planetlab/openvswitch/tunnel.py b/src/nepi/resources/planetlab/openvswitch/tunnel.py index e27a512b..a494212e 100644 --- a/src/nepi/resources/planetlab/openvswitch/tunnel.py +++ b/src/nepi/resources/planetlab/openvswitch/tunnel.py @@ -139,11 +139,11 @@ class OVSTunnel(LinuxApplication): # Get connected to the nodes res = [] if hasattr(endpoint, "create_port"): - rm_list = endpoint.get_connected(OVSWitch.rtype()) + rm_list = endpoint.get_connected(OVSWitch.get_rtype()) if rm_list: - rm = rm_list[0].get_connected(PlanetlabNode.rtype()) + rm = rm_list[0].get_connected(PlanetlabNode.get_rtype()) else: - rm = endpoint.get_connected(PlanetlabNode.rtype()) + rm = endpoint.get_connected(PlanetlabNode.get_rtype()) if rm : res.append(rm[0]) diff --git a/src/nepi/resources/planetlab/tap.py b/src/nepi/resources/planetlab/tap.py index 736c973e..fc15662f 100644 --- a/src/nepi/resources/planetlab/tap.py +++ b/src/nepi/resources/planetlab/tap.py @@ -88,10 +88,55 @@ class PlanetlabTap(LinuxApplication): @property def node(self): - node = self.get_connected(PlanetlabNode.rtype()) + node = self.get_connected(PlanetlabNode.get_rtype()) if node: return node[0] return None + """ + def trace(self, name, attr = TraceAttr.ALL, block = 512, offset = 0): + self.info("Retrieving '%s' trace %s " % (name, attr)) + + path = os.path.join(self.run_home, name) + + command = "(test -f %s && echo 'success') || echo 'error'" % path + (out, err), proc = self.node.execute(command) + + if (err and proc.poll()) or out.find("error") != -1: + msg = " Couldn't find trace %s " % name + self.error(msg, out, err) + return None + + if attr == TraceAttr.PATH: + return path + + if attr == TraceAttr.ALL: + (out, err), proc = self.node.check_output(self.run_home, name) + + if proc.poll(): + msg = " Couldn't read trace %s " % name + self.error(msg, out, err) + return None + + return out + + if attr == TraceAttr.STREAM: + cmd = "dd if=%s bs=%d count=1 skip=%d" % (path, block, offset) + elif attr == TraceAttr.SIZE: + cmd = "stat -c%%s %s " % path + + (out, err), proc = self.node.execute(cmd) + + if proc.poll(): + msg = " Couldn't find trace %s " % name + self.error(msg, out, err) + return None + + if attr == TraceAttr.SIZE: + out = int(out.strip()) + + return out + """ + def upload_sources(self): # upload vif-creation python script pl_vif_create = os.path.join(os.path.dirname(__file__), "scripts", @@ -211,7 +256,7 @@ class PlanetlabTap(LinuxApplication): # Node needs to wait until all associated RMs are released # to be released from nepi.resources.linux.udptunnel import UdpTunnel - rms = self.get_connected(UdpTunnel.rtype()) + rms = self.get_connected(UdpTunnel.get_rtype()) for rm in rms: if rm.state < ResourceState.STOPPED: self.ec.schedule(reschedule_delay, self.release) diff --git a/test/execution/resource.py b/test/execution/resource.py index d6398eb4..fa3277a7 100755 --- a/test/execution/resource.py +++ b/test/execution/resource.py @@ -65,8 +65,8 @@ class Interface(ResourceManager): super(Interface, self).__init__(ec, guid) def do_deploy(self): - node = self.get_connected(Node.rtype())[0] - chan = self.get_connected(Channel.rtype())[0] + node = self.get_connected(Node.get_rtype())[0] + chan = self.get_connected(Channel.get_rtype())[0] if node.state < ResourceState.PROVISIONED: self.ec.schedule("0.5s", self.deploy) @@ -90,7 +90,7 @@ class Node(ResourceManager): self.logger.debug(" -------- PROVISIONED ------- ") self.ec.schedule("1s", self.deploy) elif self.state == ResourceState.PROVISIONED: - ifaces = self.get_connected(Interface.rtype()) + ifaces = self.get_connected(Interface.get_rtype()) for rm in ifaces: if rm.state < ResourceState.READY: self.ec.schedule("0.5s", self.deploy) @@ -106,7 +106,7 @@ class Application(ResourceManager): super(Application, self).__init__(ec, guid) def do_deploy(self): - node = self.get_connected(Node.rtype())[0] + node = self.get_connected(Node.get_rtype())[0] if node.state < ResourceState.READY: self.ec.schedule("0.5s", self.deploy) else: @@ -126,7 +126,7 @@ class ErrorApplication(ResourceManager): super(ErrorApplication, self).__init__(ec, guid) def do_deploy(self): - node = self.get_connected(Node.rtype())[0] + node = self.get_connected(Node.get_rtype())[0] if node.state < ResourceState.READY: self.ec.schedule("0.5s", self.deploy) else: @@ -141,13 +141,13 @@ class ResourceFactoryTestCase(unittest.TestCase): ResourceFactory.register_type(MyResource) ResourceFactory.register_type(AnotherResource) - self.assertEquals(MyResource.rtype(), "MyResource") + self.assertEquals(MyResource.get_rtype(), "MyResource") self.assertEquals(len(MyResource._attributes), 2) - self.assertEquals(ResourceManager.rtype(), "Resource") + self.assertEquals(ResourceManager.get_rtype(), "Resource") self.assertEquals(len(ResourceManager._attributes), 1) - self.assertEquals(AnotherResource.rtype(), "AnotherResource") + self.assertEquals(AnotherResource.get_rtype(), "AnotherResource") self.assertEquals(len(AnotherResource._attributes), 1) self.assertEquals(len(ResourceFactory.resource_types()), 2) diff --git a/test/resources/linux/application.py b/test/resources/linux/application.py index 6b02d201..934081c1 100755 --- a/test/resources/linux/application.py +++ b/test/resources/linux/application.py @@ -238,8 +238,8 @@ main (void) ec.set(node, "cleanHome", True) ec.set(node, "cleanProcesses", True) - sources = "http://nepi.inria.fr/code/nef/archive/tip.tar.gz " \ - " http://nepi.inria.fr/code/nef/raw-file/8ace577d4079/src/nef/images/menu/connect.png" + sources = "http://yans.pl.sophia.inria.fr/code/nef/archive/tip.tar.gz " \ + " http://yans.pl.sophia.inria.fr/code/nef/raw-file/8ace577d4079/src/nef/images/menu/connect.png" app = ec.register_resource("LinuxApplication") ec.set(app, "sources", sources) diff --git a/test/resources/omf/vlc_normal_case.py b/test/resources/omf/vlc_normal_case.py index 5d9dfde1..184a79d7 100755 --- a/test/resources/omf/vlc_normal_case.py +++ b/test/resources/omf/vlc_normal_case.py @@ -36,16 +36,16 @@ import unittest class OMFResourceFactoryTestCase(unittest.TestCase): def test_creation_phase(self): - self.assertEquals(OMFNode.rtype(), "OMFNode") + self.assertEquals(OMFNode.get_rtype(), "OMFNode") self.assertEquals(len(OMFNode._attributes), 6) - self.assertEquals(OMFWifiInterface.rtype(), "OMFWifiInterface") + self.assertEquals(OMFWifiInterface.get_rtype(), "OMFWifiInterface") self.assertEquals(len(OMFWifiInterface._attributes), 10) - self.assertEquals(OMFChannel.rtype(), "OMFChannel") + self.assertEquals(OMFChannel.get_rtype(), "OMFChannel") self.assertEquals(len(OMFChannel._attributes), 6) - self.assertEquals(OMFApplication.rtype(), "OMFApplication") + self.assertEquals(OMFApplication.get_rtype(), "OMFApplication") self.assertEquals(len(OMFApplication._attributes), 13) class OMFEachTestCase(unittest.TestCase): diff --git a/test/resources/planetlab/node.py b/test/resources/planetlab/node.py index 982192bb..b177a961 100755 --- a/test/resources/planetlab/node.py +++ b/test/resources/planetlab/node.py @@ -59,7 +59,7 @@ def create_node(ec, username, pl_user, pl_password, hostname = None, class PLNodeFactoryTestCase(unittest.TestCase): def test_creation_phase(self): - self.assertEquals(PlanetlabNode.rtype(), "PlanetlabNode") + self.assertEquals(PlanetlabNode.get_rtype(), "PlanetlabNode") self.assertEquals(len(PlanetlabNode._attributes), 29)