Fixing wrong license
[nepi.git] / doc / user_manual / ec_api.tex
index 68599dd..40b73ef 100644 (file)
@@ -1,12 +1,11 @@
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
 %    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 as published by
-%    the Free Software Foundation, either version 3 of the License, or
-%    (at your option) any later version.
+%    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
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 
-\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 purpose 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 must be instantiated for
+the 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}
+
+Since a same experiment can be ran more than one time, and this is 
+often desirable to obtain statistical data, the EC identifies 
+different runs of an experiment with a same \emph{exp\_id} with  
+another attribute, the \emph{run\_id}. The \emph{run\_id} is
+a timestamp string value, and in combination with the \emph{exp\_id},
+it allows to uniquely identify an experiment instance.
+
+\begin{lstlisting}[language=Python]
+
+run_id = ec.run_id 
+
+\end{lstlisting}
+
+
+
+\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}
+
+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}
+
+In order to describe the experiment set-up, a resources need to be 
+associated at least to one another. Through the process of connecting resources
+the \emph{topology graph} is constructed. A certain application might
+need to be configured and executed on a certain node, and this
+must be indicated to the EC by connecting the application RM to the node
+RM.
+
+Connections are registered using the \emph{register\_connection} method,
+which receives the guids of the two RM.
+
+\begin{lstlisting}[language=Python]
+
+ec.register_connection(node_guid, app_guid)
+
+\end{lstlisting}
+
+The order in which the guids are given is not important, since the
+\emph{topology\_graph} is not directed, and the corresponding 
+RMs \emph{`know'} internally how to interpret the connection 
+relationship.
+
+
+\subsection{Registering conditions}
+
+All ResourceMangers must go through the same sequence of state transitions.
+Associated to those states are the actions that trigger the transitions.
+As an example, a RM will initially be in the state NEW. When the DEPLOY action
+is invoked, it will transition to the DISCOVERED, then PROVISIONED, then READY
+states. Likewise, the action START will make a RM pass from state READY to 
+STARTED, and the action STOP will change a RM from state STARTED to STOPPED.
+
+Using these states and actions, it is possible to specify workflow dependencies 
+between resources. For instance, it would be possible to indicate that
+one application should start after another application by registering a 
+condition with the EC.
+
+\begin{lstlisting}[language=Python]
+
+from nepi.execution.resource import ResourceState, ResourceActions
+
+ec.register_condition(app1_guid, ResourceAction.START, app2_guid, ResourceState.STARTED)
+
+\end{lstlisting}
+
+The above invocation should be read "Application 1 should START after application 2 
+has STARTED". It is also possible to indicate a relative time from the moment a state
+change occurs to the moment the action should be taken as follows:
+
+\begin{lstlisting}[language=Python]
+
+from nepi.execution.resource import ResourceState, ResourceActions
+
+ec.register_condition(app1_guid, ResourceAction.START, app2_guid, ResourceState.STARTED, time = "5s")
+
+\end{lstlisting}
+
+This line should be read "Application 1 should START at least 5 seconds after 
+application 2 has STARTED". \\
+
+Allowed actions are: DEPLOY, START and STOP. \\
+
+Existing states are: NEW, DISCOVERED, PROVISIONED, READY, STARTED, STOPPED, 
+FAILED and RELEASED. \\
+
+
+
+\section{The execution API}
+
+After registering all the resources and connections and setting attributes and
+traces, once the experiment we want to conduct has been described, we can
+proceed to run it. To this purpose we make use of the \emph{execution} methods
+exposed by the EC.
+
+
+\subsection{Deploying an experiment}
+
+Deploying an experiment is very easy, it only requires to invoke the 
+\emph{deploy} method of the EC.
+
+\begin{lstlisting}[language=Python]
+
+ec.deploy()
+
+\end{lstlisting}
+
+Given the experiment description provided earlier, the EC will take care
+of automatically performing all necessary actions to discover, provision,
+configure and start all resources registered in the experiment. 
+
+Furthermore, NEPI does not restrict deployment to only one time, it allows
+to continue to register, connect and configure resources and deploy them
+at any moment. We call this feature \emph{interactive} or \emph{dynamic}
+deployment. 
+
+The \emph{deploy} method can receive other optional arguments to customize
+deployment. By default, the EC will deploy all registered RMs that are in
+state NEW. However, it is possible to specify a subset of resources to be
+deployed using the \emph{guids} argument.
+
+\begin{lstlisting}[language=Python]
+
+ec.deploy(guids=[guid1, guid2, guid3])
+
+\end{lstlisting}
+
+Another useful argument of the \emph{deploy} method is \emph{wait\_all\_ready}.
+This argument has a default value of \emph{True}, and it is used as a barrier
+to force the START action to be invoked on all RMs being deploy only after
+they have all reached the state READY.
+
+\begin{lstlisting}[language=Python]
+
+ec.deploy(wait_all_ready=False)
+
+\end{lstlisting}
+
+
+\subsection{Getting attributes}
+
+Attribute values can be retrieved at any moment during the experiment run, 
+using the \emph{get} method. 
+However, not all attributes can be modified after a resource has
+been deployed. The possibility of changing the value of a certain attribute 
+depends strongly on the RM and on the attribute itself. 
+As an example, once a \emph{hostname} has been specified for a certain Node 
+RM, it might not be possible to change it after deployment.
+
+\begin{lstlisting}[language=Python]
+
+attr_value = ec.get(guid, "attr-name")
+
+\end{lstlisting}
+
+Attributes have flags that indicate whether their values can be changed
+and when it is possible to change them (e.g. before or after deployment, 
+or both). These flags are \emph{NoFlags} (the attribute value can be 
+modified always), \emph{ReadOnly} (the attribute value can never be
+modified), \emph{ExecReadOnly} (the attribute value can only be modified
+before deployment). The flags of a certain attribute can be validated 
+as shown in the example below, and the value of the attribute can be
+changed using the \emph{set} method.  
+
+\begin{lstlisting}[language=Python]
+
+from nepi.execution.attribute import Flags
+
+attr = ec.get_attribute(guid, "attr-name")
+
+if not attr.has_flag(Flags.ReadOnly):
+    ec.set(guid, "attr-name", attr_value)
+
+\end{lstlisting}
+
+\subsection{Quering the state}
+
+It is possible to query the state of any resource at any moment.
+The state of a resource is requested using the \emph{state} method.
+This method receives the optional parameter \emph{hr} to output the
+state in a \emph{human readable} string format instead of an integer
+state code.
+
+\begin{lstlisting}[language=Python]
+
+state_id = ec.state(guid)
+
+# Human readable state
+state = ec.state(guid, hr = True)
+
+\end{lstlisting}
+
+\subsection{Getting traces}
+
+After a ResourceManager has been deployed it is possible to get information
+about the active traces and the trace streams of the generated data using
+the \emph{trace} method.
+
+Most traces are collected to a file in the host where they are generated, 
+the total trace size and the file path in the (remote) host can be 
+retrieved as follows.
+
+\begin{lstlisting}[language=Python]
+
+from nepi.execution.trace import TraceAttr
+
+path = ec.trace(guid, "trace-name", TraceAttr.PATH)
+size = ec.trace(guid, "trace-name", TraceAttr.SIZE)
+
+\end{lstlisting}
+
+The trace content can be retrieved in a stream, block by block.
+
+\begin{lstlisting}[language=Python]
+
+trace_block = ec.trace(guid, "trace-name", TraceAttr.STREAM, block=1, offset=0)
+
+\end{lstlisting}
+
+It is also possible to directly retrieve the complete trace content.
+
+\begin{lstlisting}[language=Python]
+
+trace_stream = ec.trace(guid, "trace-name")
+
+\end{lstlisting}
+
+Using the \emph{trace} method it is easy to collect all traces 
+to the local user machine. 
+
+\begin{lstlisting}[language=Python]
+
+for trace in ec.get_traces(guid):
+    trace_stream = ec.trace(guid, "trace-name")
+    f = open("trace-name", "w")
+    f.write(trace_stream)
+    f.close()
+
+\end{lstlisting}
+
+
+% TODO: how to retrieve an application trace when the Node failed? (critical attribute)
+
+
+% \subsection{The collector RM}
+
+%%%%%%%%%%
+%% TODO
+%%%%%%%%%%%
+
+\subsection{API reference}
+
+Further information about classes and method signatures
+can be found using the Python \emph{help} method.
+For this inspection work, we recommend to instantiate an
+ExperimentController from an IPython console. This is an
+interactive console that allows to dynamically send input
+to the python interpreter. 
+
+If NEPI is not installed in the system, you will need to add the
+NEPI sources path to the PYTHONPATH environmental variable 
+before invoking \emph{ipython}.
+
+\begin{lstlisting}[language=Python]
+
+$ PYTHONPATH=$PYTHONPATH:src ipython
+Python 2.7.3 (default, Jan  2 2013, 13:56:14) 
+Type "copyright", "credits" or "license" for more information.
+
+
+IPython 0.13.1 -- An enhanced Interactive Python.
+?         -> Introduction and overview of IPython's features.
+%quickref -> Quick reference.
+help      -> Python's own help system.
+object?   -> Details about 'object', use 'object??' for extra details.
+
+In [1]: from nepi.execution.ec import ExperimentController
+
+In [2]: ec = ExperimentController(exp_id = "test-tap")
+
+In [3]: help(ec.set)
+
+\end{lstlisting}
+
+The example above will show the following information related to the
+\emph{set} method of the EC API.
+
+\begin{lstlisting}[language=Python]
+
+Help on method set in module nepi.execution.ec:
+
+set(self, guid, name, value) method of nepi.execution.ec.ExperimentController instance
+    Modifies the value of the attribute with name 'name' on the RM with guid 'guid'.
+    
+    :param guid: Guid of the RM
+    :type guid: int
+    
+    :param name: Name of the attribute
+    :type name: str
+    
+    :param value: Value of the attribute
+
+\end{lstlisting}
+