%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-\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}
+
+
+
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+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.<minor>-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.<minor>-release}
+ \item A tag will be added to this new branch including the revision number (i.e. \emph{release-3.<minor>.<revision>})
+ \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
%%\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}
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 " % (
cls._register_traces()
@classmethod
- def rtype(cls):
+ def get_rtype(cls):
""" Returns the type of the Resource Manager
"""
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)
@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):
"""
- 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):
@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)
@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 ccnd(self):
- ccnd = self.get_connected(LinuxCCND.rtype())
+ ccnd = self.get_connected(LinuxCCND.get_rtype())
if ccnd: return ccnd[0]
return None
@property
def ccnr(self):
- ccnr = self.get_connected(LinuxCCNR.rtype())
+ ccnr = self.get_connected(LinuxCCNR.get_rtype())
if ccnr: return ccnr[0]
return None
@property
def ccnpingserver(self):
- ccnpingserver = self.get_connected(LinuxCCNPingServer.rtype())
+ ccnpingserver = self.get_connected(LinuxCCNPingServer.get_rtype())
if ccnpingserver: return ccnpingserver[0]
return None
@property
def ccnd(self):
- ccnd = self.get_connected(LinuxCCND.rtype())
+ ccnd = self.get_connected(LinuxCCND.get_rtype())
if ccnd: return ccnd[0]
return None
@property
def ccnd(self):
- ccnd = self.get_connected(LinuxCCND.rtype())
+ ccnd = self.get_connected(LinuxCCND.get_rtype())
if ccnd: return ccnd[0]
return None
@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
# 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):
# 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)
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
# 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
@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
"""
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
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
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)
"""
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
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"
"""
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
@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
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'))
"""
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
@property
def node(self):
- node = self.get_connected(PlanetlabNode.rtype())
+ node = self.get_connected(PlanetlabNode.get_rtype())
if node: return node[0]
return None
# """
# 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
# 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)
@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
# """
# 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):
# 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)
# 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])
@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",
# 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)
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)
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)
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:
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:
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)
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)
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):
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)