1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % NEPI, a framework to manage network experiments
4 % Copyright (C) 2013 INRIA
6 % This program is free software: you can redistribute it and/or modify
7 % it under the terms of the GNU General Public License version 2 as
8 % published by the Free Software Foundation;
10 % This program is distributed in the hope that it will be useful,
11 % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 % GNU General Public License for more details.
15 % You should have received a copy of the GNU General Public License
16 % along with this program. If not, see <http://www.gnu.org/licenses/>.
18 % Author: Alina Quereilhac <alina.quereilhac@inria.fr>
20 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
22 NEPI is written in Python, so you will need to install Python before
23 being able to run experiments with NEPI.
24 NEPI is known to work on Linux (Fedore, Debian, Ubuntu) and Mac (OS X).
26 \section{Dependencies}
28 Dependencies for NEPI vary according to the features you want to enable.
29 Make sure the following dependencies are correctly installed in your system
32 Mandatory dependencies:
38 \item python-pygraphviz
39 \item python-matplotlib
42 Optional dependencies:
44 \item SleekXMPP - Required to run experiments on OMF testbeds
47 \subsection{Install dependencies on Debian/Ubuntu}
50 \fontsize{10pt}{12pt}\selectfont
53 $ sudo apt-get -y install python mercurial python-ipaddr python-networkx python-pygraphviz python-matplotlib
58 \subsection{Install dependencies on Fedora}
61 \fontsize{10pt}{12pt}\selectfont
64 $ sudo yum -y install python mercurial python-ipaddr python-networkx graphviz-python python-matplotlib
69 \subsection{Install dependencies on Mac}
71 First install homebrew (\url{http://mxcl.github.io/homebrew/}),
72 then you can install Python and the rest of the dependencies as follows:
75 \fontsize{10pt}{12pt}\selectfont
79 $ sudo port install mercurial
80 $ sudo easy_install pip
81 $ sudo pip install ipaddr
82 $ sudo pip install networkx
83 $ sudo pip install pygraphviz
84 $ sudo pip install matplotlib
89 To use Python you will need to set the PATH environmen variable as:
92 \fontsize{10pt}{12pt}\selectfont
95 $ export PATH=$PATH:/usr/local/share/python
100 \subsection{Install SleekXMPP}
102 You will need \textit{git} to get the SleekXMPP sources.
105 \fontsize{10pt}{12pt}\selectfont
108 $ git clone -b develop git://github.com/fritzy/SleekXMPP.git
110 $ sudo python setup.py install
115 \section{The source code}
117 To get NEPI's source code you will need Mercurial version
118 control system. The Mercurial NEPI repo can also be browsed online at: \\
120 \url{http://nepi.inria.fr/code/nepi/}
122 \subsection{Clone the repo}
125 \fontsize{10pt}{12pt}\selectfont
128 $ hg clone http://nepi.inria.fr/code/nepi -r nepi-3.2.0
133 \section{Install NEPI in your system}
135 You don't need to install NEPI in your system to be able to run
136 experiments. However this might be convenient if you don't
137 plan to modify or extend the sources.
139 To install NEPI, just run \emph{make install} in the NEPI source
143 \fontsize{10pt}{12pt}\selectfont
152 If you are developing your own NEPI extensions, the installed
153 NEPI version might interfere with your work.
154 In this case it is probably more convenient to tell
155 Python where to find the NEPI sources, using the PYTHONPATH
156 environmental variable, when you run a NEPI script.
159 \fontsize{10pt}{12pt}\selectfont
162 $ export PYTHONPATH=$PYTHONPATH:<path-to-nepi>/src
167 \section{Run experiments}
169 There are two ways you can use NEPI to run your experiments.
170 The first one is writing a Python script, which will import
171 NEPI libraries, and run it.
172 The second one is in interactive mode by using Python console.
174 \subsection{Run from script}
176 Writing a simple NEPI expeiment script is easy.
177 Take a look at the example in the FAQ section \ref{faq:ping_example}.
178 Once you have written down the script, you can run it using
179 Python. If NEPI is not installed in your system,
180 you will need to export the path to NEPI's source code to
181 the PYTHONPATH environment variable, so that Python can find
185 \fontsize{10pt}{12pt}\selectfont
188 $ export PYTHONPATH=<path-to-nepi>/src:$PYTHONPATH
190 $ python examples/linux/ping.py -a localhost
195 \subsection{Run NEPI interactively}
197 The IPython console can be used as an interactive interpreter to
198 execute Python instructions. We can take advantage of this feature,
199 to interactively run NEPI experiments.
200 We will use the IPython console for the example below.
202 You can easily install IPython on Debian, Ubuntu, Fedora or Mac as follows:\\
204 \textbf{Debian/Ubuntu}
207 \fontsize{10pt}{12pt}\selectfont
210 $ sudo apt-get install ipython
218 \fontsize{10pt}{12pt}\selectfont
221 $ sudo yum install ipython
229 \fontsize{10pt}{12pt}\selectfont
232 $ pip install ipython
237 Before starting, make sure to add Python and IPython source directory
238 path to the PYTHONPATH environment variable
241 \fontsize{10pt}{12pt}\selectfont
244 $ export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python:/usr/local/share/python/ipython
249 Then you can start IPython as follows:
252 $ export PYTHONPATH=<path-to-nepi>/src:$PYTHONPATH
254 Python 2.7.3 (default, Jan 2 2013, 13:56:14)
255 Type "copyright", "credits" or "license" for more information.
257 IPython 0.13.1 -- An enhanced Interactive Python.
258 ? -> Introduction and overview of IPython's features.
259 %quickref -> Quick reference.
260 help -> Python's own help system.
261 object? -> Details about 'object', use 'object??' for extra details.
265 If you want to paste many lines at once in IPython, you will need
266 to type \emph{\%cpaste} and finish the paste block with \emph{\-\-}.
268 The first thing we need to do to describe an experiment with NEPI
269 is to import the NEPI Python modules.
270 In particular we need to import the ExperimentController class.
271 To do this type the following in the Python console:
273 \begin{lstlisting}[language=Python]
275 from nepi.execution.ec import ExperimentController
279 After importing the ExperimentController class, it is possible to
280 create a new instance of an the ExperimentController (EC) for
282 The <exp-id> argument is the name you want to give the experiment
283 to identify it and distinguish it from other experiments.
285 \begin{lstlisting}[language=Python]
287 ec = ExperimentController(exp_id = "<your-exp-id>")
291 Next we will define two Python functions: \emph{add\_node} and \emph{add\_app}.
292 The first one to register linux::Node resources and the second one to
293 register linux::Application resources.
295 \begin{lstlisting}[language=Python]
298 def add_node(ec, hostname, username, ssh_key):
299 node = ec.register_resource("linux::Node")
300 ec.set(node, "hostname", hostname)
301 ec.set(node, "username", username)
302 ec.set(node, "identity", ssh_key)
303 ec.set(node, "cleanExperiment", True)
304 ec.set(node, "cleanProcesses", True)
307 def add_app(ec, command, node):
308 app = ec.register_resource("linux::Application")
309 ec.set(app, "command", command)
310 ec.register_connection(app, node)
316 The method \textit{register\_resource} registers a resource instance with the
317 ExperimentController. The method \textit{register\_connection} indicates
318 that two resources will interact during the experiment.
319 Note that invoking \textit{add\_node} or \textit{add\_app} has no effect other
320 than informing the EC about the resources that will be used during the experiment.
321 The actual deployment of the experiment requires the method \textit{deploy} to
324 The linux::Node resource exposes the hostname, username and identity
325 attributes. This attributes provide information about the SSH credentials
326 needed to log in to the Linux host.
327 The \textit{hostname} is the one that identifies the physical host you want
328 to access during the experiment. The \textit{username} must correspond to a
329 valid account on that host, and the \textit{identity} attribute is the
330 'absolute' path to the SSH private key in your local computer that allows you
331 to log in to the host.
333 The \textit{command} attribute of the linux::Application resource
334 expects a BASH command line string to be executed in the remote host.
335 Apart from the \emph{command} attribute, the linux::Application
336 resource exposes several other attributes that allow to upload,
337 compile and install arbitrary sources.
338 The add\_app function registers a connection between a linux::Node and a
341 Lets now use these functions to describe a simple experiment.
342 Choose a host where you have an account, and can access using SSH
345 \begin{lstlisting}[language=Python]
347 hostname = <the-hostname>
348 username = <my-username>
349 identity = </home/myuser/.ssh/id_rsa>
351 node = add_node(ec, hostname, username, ssh_key)
352 app = add_app(ec, "ping -c3 nepi.inria.fr", node)
356 The values returned by the functions add\_node and add\_app are global
357 unique identifiers (guid) of the resources that were registered with the EC.
358 The guid is used to reference the ResourceManager associated to a registered
359 resource (for instance to retrieve results or change attribute values).
361 Now that we have registered some resources, we can ask the ExperimentController
363 Invoking the \emph{deploy} command will not only configure the
364 resource but also automatically launch the applications.
366 \begin{lstlisting}[language=Python]
372 After some seconds, we should see some output messages informing us about the
373 progress in the host deployment.
374 If you now open another terminal and you connect to the host using
375 SSH (as indicated below), you should see that a directory for your experiment
376 has been created in the host. In the remote host you will see that two NEPI
377 directories were created in the \$HOME directory: \emph{nepi-src} and \emph{nepi-exp}.
378 The first one is where NEPI will store files that might be re used by many
379 experiments (e.g. source code, input files) . The second directory \emph{nepi-exp},
380 is where experiment specific files (e.g. results, deployment scripts) will be stored.
383 \fontsize{10pt}{12pt}\selectfont
387 $ ssh -i identity username@hostname
393 Inside the \emph{nepi-exp} directory, you will find another directory with
394 the <exp-id> assigned to your EC, and inside that directory you should find
395 one directory named node-1 which will contain the files (e.g. result traces)
396 associated to the LinuxNode reosurce you just deployed.
397 In fact for every resource deployed associated to that host (e.g. each
398 linux::Application), NEPI will create a directory to place files related to it.
399 The name of the directory identifies the type of resources (e.g. 'node',
400 'app', etc) and it is followed by the global unique identifier (guid).
402 We can see if a resource finished deploying by querying its state through the EC
404 \begin{lstlisting}[language=Python]
406 ec.state(app, hr=True)
410 Once a linux::Application has reached the state 'STARTED',
411 we can retrieve the 'stdout' trace, which should contain the output
414 \begin{lstlisting}[language=Python]
416 ec.trace(app, "stdout")
420 That is it. We can terminate the experiment by invoking the method \emph{shutdown}.
422 \begin{lstlisting}[language=Python]
428 \subsection{Define a workflow}
430 Now that we have introduced to the basics of NEPI, we will register
431 two more applications and define a workflow where one application
432 will start after the other one has finished executing.
433 For this we will use the EC \textit{register\_condition} method described below:
435 \begin{lstlisting}[language=Python]
437 register_condition(self, guids1, action, guids2, state, time=None):
438 Registers an action START, STOP or DEPLOY for all RM on list
439 guids1 to occur at time 'time' after all elements in list guids2
440 have reached state 'state'.
442 :param guids1: List of guids of RMs subjected to action
445 :param action: Action to perform (either START, STOP or DEPLOY)
446 :type action: ResourceAction
448 :param guids2: List of guids of RMs to we waited for
451 :param state: State to wait for on RMs of list guids2 (STARTED,
453 :type state: ResourceState
455 :param time: Time to wait after guids2 has reached status
460 To use the \textit{register\_condition} method we will need to import the
461 ResourceState and the ResourceAction classes
463 \begin{lstlisting}[language=Python]
465 from nepi.execution.resource import ResourceState, ResourceAction
469 Then, we register the two applications. The first application will
470 wait for 5 seconds and the create a file in the host called "greetings"
471 with the content "HELLO WORLD".
472 The second application will read the content of the file and output it
473 to standard output. If the file doesn't exist il will instead output the
476 \begin{lstlisting}[language=Python]
478 app1 = add_app(ec, "sleep 5; echo 'HELLO WORLD!' > ~/greetings", node)
479 app2 = add_app(ec, "cat ~/greetings || echo 'FAILED'", node)
483 In order to guarantee that the second application is successful, we need to
484 make sure that the first application is executed first. For this we register
487 \begin{lstlisting}[language=Python]
489 ec.register_condition (app2, ResourceAction.START, app1, ResourceState.STOPPED)
493 We then deploy the two application:
495 \begin{lstlisting}[language=Python]
497 ec.deploy(guids=[app1,app2])
501 Finally, we retrieve the standard output of the second application,
502 which should return the string "HELLO WORLD!".
504 \begin{lstlisting}[language=Python]
506 ec.trace(app2, "stdout")