replacing assertEquals into assertEqual
[nepi.git] / doc / user_manual / getting_started.tex
1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2 %
3 %    NEPI, a framework to manage network experiments
4 %    Copyright (C) 2013 INRIA
5 %
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;
9 %
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.
14 %
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/>.
17 %
18 % Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 %
20 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
21
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).
25
26 \section{Dependencies}
27
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
30 before using NEPI. \\
31
32 Mandatory dependencies:
33 \begin{itemize}
34     \item Python 2.6+
35     \item Mercurial
36     \item python-ipaddr
37     \item python-networkx
38     \item python-pygraphviz
39     \item python-matplotlib 
40 \end{itemize}
41
42 Optional dependencies:
43 \begin{itemize}
44     \item SleekXMPP - Required to run experiments on OMF testbeds
45 \end{itemize}
46
47 \subsection{Install dependencies on Debian/Ubuntu}
48
49 \begingroup
50     \fontsize{10pt}{12pt}\selectfont
51
52 \begin{verbatim}
53     $ sudo apt-get -y install python mercurial python-ipaddr python-networkx python-pygraphviz python-matplotlib
54 \end{verbatim}
55
56 \endgroup
57
58 \subsection{Install dependencies on Fedora}
59
60 \begingroup
61     \fontsize{10pt}{12pt}\selectfont
62
63 \begin{verbatim}
64     $ sudo yum -y install python mercurial python-ipaddr python-networkx graphviz-python python-matplotlib
65 \end{verbatim}
66
67 \endgroup
68
69 \subsection{Install dependencies on Mac}
70
71 First install homebrew (\url{http://mxcl.github.io/homebrew/}),
72 then you can install Python and the rest of the dependencies as follows:
73
74 \begingroup
75     \fontsize{10pt}{12pt}\selectfont
76
77 \begin{verbatim}
78    $ brew install python
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
85 \end{verbatim}
86
87 \endgroup
88
89 To use Python you will need to set the PATH environmen variable as:
90
91 \begingroup
92     \fontsize{10pt}{12pt}\selectfont
93
94 \begin{verbatim}
95    $ export PATH=$PATH:/usr/local/share/python
96 \end{verbatim}
97
98 \endgroup
99
100 \subsection{Install SleekXMPP}
101
102 You will need \textit{git} to get the SleekXMPP sources.
103
104 \begingroup
105     \fontsize{10pt}{12pt}\selectfont
106
107 \begin{verbatim}
108     $ git clone -b develop git://github.com/fritzy/SleekXMPP.git
109     $ cd SleekXMPP
110     $ sudo python setup.py install
111 \end{verbatim}
112
113 \endgroup
114
115 \section{The source code}
116
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: \\
119
120 \url{http://nepi.inria.fr/code/nepi/} 
121
122 \subsection{Clone the repo}
123
124 \begingroup
125     \fontsize{10pt}{12pt}\selectfont
126
127 \begin{verbatim}
128 $ hg clone http://nepi.inria.fr/code/nepi -r nepi-3.2.0
129 \end{verbatim}
130
131 \endgroup
132
133 \section{Install NEPI in your system}
134
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.
138
139 To install NEPI, just run \emph{make install} in the NEPI source
140 folder.
141
142 \begingroup
143     \fontsize{10pt}{12pt}\selectfont
144
145 \begin{verbatim}
146     $ cd nepi
147     $ make install 
148 \end{verbatim}
149
150 \endgroup
151
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.
157
158 \begingroup
159     \fontsize{10pt}{12pt}\selectfont
160
161 \begin{verbatim}
162     $ export PYTHONPATH=$PYTHONPATH:<path-to-nepi>/src 
163 \end{verbatim}
164
165 \endgroup
166
167 \section{Run experiments}
168
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.
173
174 \subsection{Run from script}
175
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
182 NEPI's libraries.
183
184 \begingroup
185     \fontsize{10pt}{12pt}\selectfont
186
187 \begin{verbatim}
188     $ export PYTHONPATH=<path-to-nepi>/src:$PYTHONPATH
189     $ cd <path-to-nepi> 
190     $ python examples/linux/ping.py -a localhost
191 \end{verbatim}
192
193 \endgroup
194
195 \subsection{Run NEPI interactively}
196
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. 
201
202 You can easily install IPython on Debian, Ubuntu, Fedora or Mac as follows:\\
203
204 \textbf{Debian/Ubuntu}
205
206 \begingroup
207     \fontsize{10pt}{12pt}\selectfont
208
209 \begin{verbatim}
210     $ sudo apt-get install ipython
211 \end{verbatim}
212
213 \endgroup
214
215 \textbf{Fedora}\\
216
217 \begingroup
218     \fontsize{10pt}{12pt}\selectfont
219
220 \begin{verbatim}
221     $ sudo yum install ipython
222 \end{verbatim}
223
224 \endgroup
225
226 \textbf{Mac}\\
227
228 \begingroup
229     \fontsize{10pt}{12pt}\selectfont
230
231 \begin{verbatim}
232     $ pip install ipython
233 \end{verbatim}
234
235 \endgroup
236
237 Before starting, make sure to add Python and IPython source directory 
238 path to the PYTHONPATH environment variable
239
240 \begingroup
241     \fontsize{10pt}{12pt}\selectfont
242
243 \begin{verbatim}
244     $ export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python:/usr/local/share/python/ipython
245 \end{verbatim}
246
247 \endgroup
248
249 Then you can start IPython as follows: 
250
251 \begin{verbatim}
252 $ export PYTHONPATH=<path-to-nepi>/src:$PYTHONPATH
253 $ ipython
254 Python 2.7.3 (default, Jan  2 2013, 13:56:14) 
255 Type "copyright", "credits" or "license" for more information.
256
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.
262
263 \end{verbatim}
264
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{\-\-}.
267
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: 
272
273 \begin{lstlisting}[language=Python]
274
275 from nepi.execution.ec import ExperimentController
276
277 \end{lstlisting}
278
279 After importing the ExperimentController class, it is possible to 
280 create a new instance of an the ExperimentController (EC) for 
281 your experiment. 
282 The <exp-id> argument is the name you want to give the experiment 
283 to identify it and distinguish it from other experiments. 
284
285 \begin{lstlisting}[language=Python]
286
287 ec = ExperimentController(exp_id = "<your-exp-id>")
288
289 \end{lstlisting}
290
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. 
294
295 \begin{lstlisting}[language=Python]
296
297 %cpaste
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)
305     return node
306
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)
311     return app
312 --
313
314 \end{lstlisting}
315
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
322 be invoked.
323
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.
332
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 
339 linux::Application. 
340
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
343 key authentication. 
344
345 \begin{lstlisting}[language=Python]
346
347 hostname = <the-hostname>
348 username = <my-username>
349 identity = </home/myuser/.ssh/id_rsa>
350
351 node = add_node(ec, hostname, username, ssh_key)
352 app = add_app(ec, "ping -c3 nepi.inria.fr",  node)
353
354 \end{lstlisting}
355
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).
360
361 Now that we have registered some resources, we can ask the ExperimentController
362 (EC) to deploy them. 
363 Invoking the \emph{deploy} command will not only configure the 
364 resource but also automatically launch the applications.
365
366 \begin{lstlisting}[language=Python]
367
368  ec.deploy()
369
370 \end{lstlisting}
371
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. 
381
382 \begingroup
383     \fontsize{10pt}{12pt}\selectfont
384
385 \begin{verbatim}
386
387 $ ssh -i identity username@hostname
388
389 \end{verbatim}
390
391 \endgroup
392
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).
401
402 We can see if a resource finished deploying by querying its state through the EC 
403
404 \begin{lstlisting}[language=Python]
405
406 ec.state(app, hr=True)
407
408 \end{lstlisting}
409
410 Once a linux::Application has reached the state 'STARTED', 
411 we can retrieve the 'stdout' trace, which should contain the output 
412 of the PING command. 
413
414 \begin{lstlisting}[language=Python]
415
416  ec.trace(app, "stdout")
417
418 \end{lstlisting}
419
420 That is it. We can terminate the experiment by invoking the method \emph{shutdown}.
421
422 \begin{lstlisting}[language=Python]
423
424  ec.shutdown()
425
426 \end{lstlisting}
427
428 \subsection{Define a workflow}
429
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:
434
435 \begin{lstlisting}[language=Python]
436
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'.
441     
442         :param guids1: List of guids of RMs subjected to action
443         :type guids1: list
444     
445         :param action: Action to perform (either START, STOP or DEPLOY)
446         :type action: ResourceAction
447     
448         :param guids2: List of guids of RMs to we waited for
449         :type guids2: list
450     
451         :param state: State to wait for on RMs of list guids2 (STARTED,
452             STOPPED, etc)
453         :type state: ResourceState
454     
455         :param time: Time to wait after guids2 has reached status 
456         :type time: string
457
458 \end{lstlisting}
459
460 To use the \textit{register\_condition} method we will need to import the 
461 ResourceState and the ResourceAction classes
462
463 \begin{lstlisting}[language=Python]
464
465 from nepi.execution.resource import ResourceState, ResourceAction
466
467 \end{lstlisting}
468
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 
474 string "FAILED".
475
476 \begin{lstlisting}[language=Python]
477
478 app1 = add_app(ec, "sleep 5; echo 'HELLO WORLD!' > ~/greetings", node)
479 app2 = add_app(ec, "cat ~/greetings || echo 'FAILED'", node)
480
481 \end{lstlisting}
482
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 
485 a condition:
486
487 \begin{lstlisting}[language=Python]
488
489 ec.register_condition (app2, ResourceAction.START, app1, ResourceState.STOPPED)
490
491 \end{lstlisting}
492
493 We then deploy the two application:
494
495 \begin{lstlisting}[language=Python]
496
497 ec.deploy(guids=[app1,app2])
498
499 \end{lstlisting}
500
501 Finally, we retrieve the standard output of the second application, 
502 which should return the string "HELLO WORLD!".
503
504 \begin{lstlisting}[language=Python]
505
506 ec.trace(app2, "stdout")
507
508 \end{lstlisting}
509