diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7fec3f148e52794ae46e9937e9fd0be882461598..a45ef0e03f9ca8111eec4a8af4873d66e973910f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,11 +3,7 @@ pages:
   tags: [qlf-ci.inria.fr]
   script:
   - mkdir -p public
-  - cp index.html public/index.html
-  - cp timeline.css public/.
-  - cp -r exercices public/
-  - cp -r figs public/
-
+  - cp -r . public/ || true
   artifacts:
     paths:
     - public
diff --git a/index.html b/index.html
index f69b6efaeed60d17525568a37ce78897011a2d49..880546810510c57460569a930cb06052ac53c685 100644
--- a/index.html
+++ b/index.html
@@ -3,7 +3,7 @@
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 <head>
-<!-- 2019-11-15 ven. 14:14 -->
+<!-- 2019-11-29 ven. 00:28 -->
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 <meta name="viewport" content="width=device-width, initial-scale=1" />
 <title>Distributed experiments on Grid'5000 &#x2026; and beyond !</title>
@@ -231,1056 +231,14 @@ for the JavaScript code in this tag.
 <body>
 <div id="content">
 <h1 class="title">Distributed experiments on Grid'5000 &#x2026; and beyond !</h1>
-<div id="table-of-contents">
-<h2>Table of Contents</h2>
-<div id="text-table-of-contents">
-<ul>
-<li><a href="#orgb1aa660">1. Foreword</a>
-<ul>
-<li><a href="#org33af631">1.1. Existing tools (Grid'5000)</a></li>
-<li><a href="#org769cfcb">1.2. EnOSlib quicktour</a></li>
-<li><a href="#org4a53df5">1.3. Contributing</a></li>
-</ul>
-</li>
-<li><a href="#orgc7e91b9">2. Before you start</a></li>
-<li><a href="#org782c78a">3. Setup on Grid'5000</a></li>
-<li><a href="#org441c9dd">4. Your first experiment on Grid'5000</a>
-<ul>
-<li><a href="#orgf5c5450">4.1. First iteration</a></li>
-<li><a href="#org993bcaf">4.2. Let's observe in real-time what is happening</a></li>
-<li><a href="#org830e31f">4.3. Discussion</a></li>
-<li><a href="#org5f35d8c">4.4. A bit better approach</a></li>
-<li><a href="#orgdddf696">4.5. Ninja level</a></li>
-<li><a href="#org1193557">4.6. Some references</a></li>
-</ul>
-</li>
-<li><a href="#orgf965b96">5. Providers: to replicate your experiment</a>
-<ul>
-<li><a href="#orgad471c7">5.1. iperf3 on virtual machines on Grid'5000</a></li>
-<li><a href="#org08faf88">5.2. References</a></li>
-</ul>
-</li>
-<li><a href="#org56f9c08">6. Variables in EnOSlib</a>
-<ul>
-<li><a href="#org2281689">6.1. Discover the <code>run</code> command and its variants</a></li>
-<li><a href="#orgd2c7291">6.2. Advanced usages</a></li>
-<li><a href="#orgd78a6d8">6.3. Ninja level</a></li>
-<li><a href="#orge739be4">6.4. Putting all together</a></li>
-<li><a href="#org5dafa08">6.5. Some references</a></li>
-</ul>
-</li>
-<li><a href="#orga167566">7. Modules: for safer remote actions</a>
-<ul>
-<li><a href="#orgc30170a">7.1. Idempotency</a></li>
-<li><a href="#org334a244">7.2. One reason why idempotency is important</a></li>
-<li><a href="#orgcf77118">7.3. Idempotency trick</a></li>
-<li><a href="#orgcaa5aa0">7.4. General idempotency</a></li>
-</ul>
-</li>
-<li><a href="#orgb39fe8f">8. Tasks: to organize your experiment</a></li>
-</ul>
-</div>
-</div>
-
-<div id="outline-container-orgb1aa660" class="outline-2">
-<h2 id="orgb1aa660"><span class="section-number-2">1</span> Foreword</h2>
-<div class="outline-text-2" id="text-1">
-</div>
-<div id="outline-container-org33af631" class="outline-3">
-<h3 id="org33af631"><span class="section-number-3">1.1</span> Existing tools (Grid'5000)</h3>
-<div class="outline-text-3" id="text-1-1">
-<ul class="org-ul">
-<li>EnOSlib falls under the <b><b>Experiment management tools</b></b> of the following
-list:
-<a href="https://www.grid5000.fr/w/Grid5000:Software">https://www.grid5000.fr/w/Grid5000:Software</a></li>
-
-<li>EnOSlib can target Grid'5000 but also other testbeds (Chameleon, local machines&#x2026;)</li>
-
-<li>EnOSlib provides high level constructs to help you with your experiments</li>
-</ul>
-</div>
-</div>
-
-<div id="outline-container-org769cfcb" class="outline-3">
-<h3 id="org769cfcb"><span class="section-number-3">1.2</span> EnOSlib quicktour</h3>
-<div class="outline-text-3" id="text-1-2">
-<ul class="org-ul">
-<li>Documentation: <a href="https://discovery.gitlabpages.inria.fr/enoslib/index.html">https://discovery.gitlabpages.inria.fr/enoslib/index.html</a></li>
-<li>Source:  <a href="https://gitlab.inria.fr/discovery/enoslib">https://gitlab.inria.fr/discovery/enoslib</a></li>
-<li>Reach us on:
-<ul class="org-ul">
-<li><a href="https://framateam.org/enoslib">https://framateam.org/enoslib</a></li>
-<li><a href="https://gitlab.inria.fr/discovery/enoslib/issues">https://gitlab.inria.fr/discovery/enoslib/issues</a></li>
-</ul></li>
-</ul>
-</div>
-</div>
-
-<div id="outline-container-org4a53df5" class="outline-3">
-<h3 id="org4a53df5"><span class="section-number-3">1.3</span> Contributing</h3>
-<div class="outline-text-3" id="text-1-3">
-<p>
-<b>Before experimenting</b>
-</p>
-
-<ul class="org-ul">
-<li>Tell us what your plans are:
-<ul class="org-ul">
-<li>There might be already users doing similar thing</li>
-<li>There might be some missing/hidden pieces in the library you might need</li>
-</ul></li>
-</ul>
-
-<p>
-<b>While experimenting</b>
-</p>
-
-<ul class="org-ul">
-<li>Write bug reports / ask questions</li>
-<li>Fix bugs / add your features</li>
-</ul>
-
-<p>
-<b>After experimenting</b>
-</p>
-
-<ul class="org-ul">
-<li>Give your feedback</li>
-<li>Add yourself to the list: <a href="https://discovery.gitlabpages.inria.fr/enoslib/theyuseit.html">https://discovery.gitlabpages.inria.fr/enoslib/theyuseit.html</a></li>
-</ul>
-</div>
-</div>
-</div>
-
-
-<div id="outline-container-orgc7e91b9" class="outline-2">
-<h2 id="orgc7e91b9"><span class="section-number-2">2</span> Before you start</h2>
-<div class="outline-text-2" id="text-2">
-<div class="note">
-<p>
-make sure you are familiar with the grid'5000 architecture. see section 1 &amp; 2 of
-<a href="https://www.grid5000.fr/w/Getting_Started">https://www.grid5000.fr/w/Getting_Started</a>. note that we won't do this tutorial
-we'll prefer to use higher level tools for now.
-</p>
-
-</div>
-</div>
-</div>
-
-<div id="outline-container-org782c78a" class="outline-2">
-<h2 id="org782c78a"><span class="section-number-2">3</span> Setup on Grid'5000</h2>
-<div class="outline-text-2" id="text-3">
-<p>
-Connect to a Grid'5000 frontend of your choice (e.g rennes, nancy &#x2026;)
-</p>
-
-<ul class="org-ul">
-<li>create a new directory to host all the scripts of the session</li>
-<li>bootstrap a new python3 virtualenv</li>
-<li>install EnOSlib and configure the access to the API</li>
-</ul>
-
-<div class="org-src-container">
-<pre class="src src-bash">$<span style="color: #7590db;">frontend</span>: mkdir enoslib_seminar
-$<span style="color: #7590db;">frontend</span>: cd enoslib_seminar
-$<span style="color: #7590db;">frontend</span>: virtualenv --python=python3 venv
-$<span style="color: #7590db;">frontend</span>: source venv/bin/activate
-$<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: pip install enoslib
-$<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: echo <span style="color: #2d9574;">'</span>
-<span style="color: #2d9574;">verify_ssl: False</span>
-<span style="color: #2d9574;">'</span> &gt; ~/.python-grid5000.yaml
-</pre>
-</div>
-</div>
-</div>
-
-<div id="outline-container-org441c9dd" class="outline-2">
-<h2 id="org441c9dd"><span class="section-number-2">4</span> Your first experiment on Grid'5000</h2>
-<div class="outline-text-2" id="text-4">
-<p>
-Let's experiment with <a href="https://iperf.fr/">iperf3</a>: a network bandwidth measuring tool. The goal is
-to deploy a simple benchmark between two hosts. 
-</p>
-
-<p>
-We'll also instrument the deployment in order to visualize in real-time the
-network traffic between the hosts. Since this is super common, EnOSlib
-exposes a <i>monitoring service</i> that lets you deploy very quickly what is
-needed.
-</p>
-</div>
-
-<div id="outline-container-orgf5c5450" class="outline-3">
-<h3 id="orgf5c5450"><span class="section-number-3">4.1</span> First iteration</h3>
-<div class="outline-text-3" id="text-4-1">
-<p>
-We consider the following script
-</p>
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.api <span style="color: #4f97d7; font-weight: bold;">import</span> run_command, wait_ssh
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.provider <span style="color: #4f97d7; font-weight: bold;">import</span> G5k
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.configuration <span style="color: #4f97d7; font-weight: bold;">import</span> Configuration, NetworkConfiguration
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.service <span style="color: #4f97d7; font-weight: bold;">import</span> Monitoring
-
-<span style="color: #4f97d7; font-weight: bold;">import</span> logging
-
-
-<span style="color: #4f97d7; font-weight: bold;">def</span> <span style="color: #bc6ec5; font-weight: bold;">pprint</span><span style="color: #4f97d7;">(</span>d<span style="color: #4f97d7;">)</span>:
-    <span style="color: #2aa1ae;">"""Utils fonction to pretty print the results"""</span>
-    <span style="color: #4f97d7; font-weight: bold;">for</span> k, v <span style="color: #4f97d7; font-weight: bold;">in</span> d<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"ok"</span><span style="color: #4f97d7;">]</span>.items<span style="color: #4f97d7;">()</span>:
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"Result for {k}"</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"-"</span> * <span style="color: #a45bad;">70</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDOUT:"</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stdout"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDERR:"</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stderr"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
-
-
-logging.basicConfig<span style="color: #4f97d7;">(</span>level=logging.INFO<span style="color: #4f97d7;">)</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Some parameters.</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 1: that you don't need to be on rennes frontend to use nodes</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">from rennes</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 2: Adapt the site/cluster according to the availibility</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">see the Gantt in https://www.grid5000.fr/w/Status</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #7590db;">SITE</span> = <span style="color: #2d9574;">"rennes"</span>
-<span style="color: #7590db;">CLUSTER</span> = <span style="color: #2d9574;">"paravance"</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Configuration object describes the resource we want</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">here: 2 machines on the same cluster using the production network</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #7590db;">network</span> = NetworkConfiguration<span style="color: #4f97d7;">(</span><span style="color: #4f97d7;">id</span>=<span style="color: #2d9574;">"n1"</span>,
-                               <span style="color: #4f97d7;">type</span>=<span style="color: #2d9574;">"prod"</span>,
-                               roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"my_network"</span><span style="color: #bc6ec5;">]</span>,
-                               site=SITE<span style="color: #4f97d7;">)</span>
-
-<span style="color: #7590db;">conf</span> = Configuration.from_settings<span style="color: #4f97d7;">(</span>job_name=<span style="color: #2d9574;">"enoslib_tutorial"</span>,
-                                   job_type=<span style="color: #2d9574;">"allow_classic_ssh"</span><span style="color: #4f97d7;">)</span>\
-    .add_network_conf<span style="color: #4f97d7;">(</span>network<span style="color: #4f97d7;">)</span>\
-    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
-                 cluster=CLUSTER,
-                 nodes=<span style="color: #a45bad;">1</span>,
-                 primary_network=network<span style="color: #4f97d7;">)</span>\
-    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
-                 cluster=CLUSTER,
-                 nodes=<span style="color: #a45bad;">1</span>,
-                 primary_network=network<span style="color: #4f97d7;">)</span>\
-    .finalize<span style="color: #4f97d7;">()</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Reserve the ressources corresponding to the configuration</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">you'll get two **physical machine** (not virtual)</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">the roles object is a dictionnary of the concrete compute resources</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">roles = {"server": [host1], "client": [host2] }</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #7590db;">provider</span> = G5k<span style="color: #4f97d7;">(</span>conf<span style="color: #4f97d7;">)</span>
-<span style="color: #7590db;">roles</span>, <span style="color: #7590db;">networks</span> =  provider.init<span style="color: #4f97d7;">()</span>
-wait_ssh<span style="color: #4f97d7;">(</span>roles<span style="color: #4f97d7;">)</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Below is the experimentation logic</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- It installs the bare minimum to run iperf3</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'server' is used to run a iperf3 server</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">started in the background (using tmux)</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'client' connects to that server and initiate a</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">transfer for 30s (duration variable)</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- Report is printed in stdout</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
-<span style="color: #7590db;">duration</span> = <span style="color: #a45bad;">30</span>
-run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"apt update &amp;&amp; apt install -y iperf3 tmux"</span>, roles=roles<span style="color: #4f97d7;">)</span>
-run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"tmux new-session -d 'exec iperf3 -s'"</span>, pattern_hosts=<span style="color: #2d9574;">"server"</span>, roles=roles<span style="color: #4f97d7;">)</span>
-<span style="color: #7590db;">result</span> = run_command<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t {duration}"</span>, pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span>
-pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Destroy the reservation, uncomment when needed</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">provider.destroy()</span>
-</pre>
-</div>
-
-<div class="question">
-<p>
-How fast is the network between the nodes you have chosen ?
-</p>
-
-</div>
-
-<div class="note">
-<p>
-Before moving to the next questions, you'll need to clean the reservation.
-You can either uncomment the line <code>provider.destroy()</code> at the end of the script.
-You can also do it manually using the low-level <code>oarstat</code> / <code>oardel</code> tools.
-</p>
-
-<div class="org-src-container">
-<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">get you reservation id</span>
-$<span style="color: #7590db;">frontend</span>: oarstat -u
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">release the resources / kill the reservation</span>
-$<span style="color: #7590db;">frontend</span>: oardel &lt;the id of the reservation goes here&gt;
-</pre>
-</div>
-
-</div>
-
-<div class="question">
-<p>
-Can you adapt the script so that:
-</p>
-<ol class="org-ol">
-<li>The two nodes are in two different cluster in the same site ?</li>
-<li>The two nodes are in two different sites ?</li>
-</ol>
-
-</div>
-</div>
-</div>
-
-
-<div id="outline-container-org993bcaf" class="outline-3">
-<h3 id="org993bcaf"><span class="section-number-3">4.2</span> Let's observe in real-time what is happening</h3>
-<div class="outline-text-3" id="text-4-2">
-<div class="note">
-<p>
-Make sure you have cleaned your previous reservations.
-</p>
-
-</div>
-
-<p>
-The following script installs a monitoring stack on your nodes. This is almost
-the same script as before except the lines corresponding to the configuration
-of the monitoring stack.
-</p>
-
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.api <span style="color: #4f97d7; font-weight: bold;">import</span> run_command, wait_ssh
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.provider <span style="color: #4f97d7; font-weight: bold;">import</span> G5k
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.configuration <span style="color: #4f97d7; font-weight: bold;">import</span> Configuration, NetworkConfiguration
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.service <span style="color: #4f97d7; font-weight: bold;">import</span> Monitoring
-
-<span style="color: #4f97d7; font-weight: bold;">import</span> logging
-
-
-<span style="color: #4f97d7; font-weight: bold;">def</span> <span style="color: #bc6ec5; font-weight: bold;">pprint</span><span style="color: #4f97d7;">(</span>d<span style="color: #4f97d7;">)</span>:
-    <span style="color: #2aa1ae;">"""Utils fonction to pretty print the results"""</span>
-    <span style="color: #4f97d7; font-weight: bold;">for</span> k, v <span style="color: #4f97d7; font-weight: bold;">in</span> d<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"ok"</span><span style="color: #4f97d7;">]</span>.items<span style="color: #4f97d7;">()</span>:
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"Result for {k}"</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"-"</span> * <span style="color: #a45bad;">70</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDOUT:"</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stdout"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDERR:"</span><span style="color: #4f97d7;">)</span>
-        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stderr"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
-
-
-logging.basicConfig<span style="color: #4f97d7;">(</span>level=logging.INFO<span style="color: #4f97d7;">)</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Some parameters.</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 1: that you don't need to be on rennes frontend to use nodes</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">from rennes</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 2: Adapt the site/cluster according to the availibility</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">see the Gantt in https://www.grid5000.fr/w/Status</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #7590db;">SITE</span> = <span style="color: #2d9574;">"rennes"</span>
-<span style="color: #7590db;">CLUSTER</span> = <span style="color: #2d9574;">"paravance"</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Configuration object describes the resource we want</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">here: 2 machines on the same cluster using the production network</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #7590db;">network</span> = NetworkConfiguration<span style="color: #4f97d7;">(</span><span style="color: #4f97d7;">id</span>=<span style="color: #2d9574;">"n1"</span>,
-                               <span style="color: #4f97d7;">type</span>=<span style="color: #2d9574;">"prod"</span>,
-                               roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"my_network"</span><span style="color: #bc6ec5;">]</span>,
-                               site=SITE<span style="color: #4f97d7;">)</span>
-
-<span style="color: #7590db;">conf</span> = Configuration.from_settings<span style="color: #4f97d7;">(</span>job_name=<span style="color: #2d9574;">"enoslib_tutorial"</span>,
-                                   job_type=<span style="color: #2d9574;">"allow_classic_ssh"</span><span style="color: #4f97d7;">)</span>\
-    .add_network_conf<span style="color: #4f97d7;">(</span>network<span style="color: #4f97d7;">)</span>\
-    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
-                 cluster=CLUSTER,
-                 nodes=<span style="color: #a45bad;">1</span>,
-                 primary_network=network<span style="color: #4f97d7;">)</span>\
-    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
-                 cluster=CLUSTER,
-                 nodes=<span style="color: #a45bad;">1</span>,
-                 primary_network=network<span style="color: #4f97d7;">)</span>\
-    .finalize<span style="color: #4f97d7;">()</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Reserve the ressources corresponding to the configuration</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">you'll get two **physical machine** (not virtual)</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">the roles object is a dictionnary of the concrete compute resources</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">roles = {"server": [host1], "client": [host2] }</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #7590db;">provider</span> = G5k<span style="color: #4f97d7;">(</span>conf<span style="color: #4f97d7;">)</span>
-<span style="color: #7590db;">roles</span>, <span style="color: #7590db;">networks</span> =  provider.init<span style="color: #4f97d7;">()</span>
-wait_ssh<span style="color: #4f97d7;">(</span>roles<span style="color: #4f97d7;">)</span>
-
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">This deploys a monitoring stack. It is composed of</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">- some agents on each monitored nodes</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">- one collector that collects the metrics from the agents</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">- one UI to visualize</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #7590db;">m</span> = Monitoring<span style="color: #4f97d7;">(</span>collector=roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
-               agent=roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span> + roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
-               ui=roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span><span style="color: #4f97d7;">)</span>
-m.deploy<span style="color: #4f97d7;">()</span>
-
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Below is the experimentation logic</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- It installs the bare minimum to run iperf3</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'server' is used to run a iperf3 server</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">started in the background (using tmux)</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'client' connects to that server and initiate a</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">transfer for 600s (duration variable)</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- Report is printed in stdout</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
-<span style="color: #7590db;">duration</span> = <span style="color: #a45bad;">600</span>
-run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"apt update &amp;&amp; apt install -y iperf3 tmux"</span>, roles=roles<span style="color: #4f97d7;">)</span>
-run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"tmux new-session -d 'exec iperf3 -s'"</span>, pattern_hosts=<span style="color: #2d9574;">"server"</span>, roles=roles<span style="color: #4f97d7;">)</span>
-<span style="color: #7590db;">result</span> = run_command<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t {duration}"</span>, pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span>
-pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Destroy the reservation, uncomment when needed</span>
-<span style="color: #2aa1ae; background-color: #292e34;">##</span>
-<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">provider.destroy()</span>
-</pre>
-</div>
-
-<p>
-Now, let's visualize the network traffic in real-time !
-</p>
-<div class="note">
-<p>
-Usually I follow this to access services running inside Grid'5000:
-<a href="https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html#accessing-http-services-inside-grid-5000">https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html#accessing-http-services-inside-grid-5000</a>.
-</p>
-
-
-<p>
-Today you can just create a tunnel like this (from your local machine).
-</p>
-
-<div class="org-src-container">
-<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Adapt the node names with the node where grafana (the UI) has been installed</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Replace &lt;login&gt; by your Grid'5000 login</span>
-$<span style="color: #7590db;">yourmachine</span>: ssh -NL <span style="color: #a45bad;">3000:paravance-16.rennes.grid5000.fr:3000</span> &lt;login&gt;@access.grid5000.fr
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">point your browser to localhost:3000</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">username/mdp: admin/admin</span>
-</pre>
-</div>
-
-</div>
-
-<p>
-Part of the experimenter work also consists in analysing the data. Here it
-corresponds in writing the right request to monitor the traffic (check the
-Fig. <a href="#orga4a34ec">1</a>). You should be able to visualize such a thing (after a bit
-of point and clicks).
-</p>
-
-
-<div id="orga4a34ec" class="figure">
-<p><a href="figs/iperf3.png" width="100%" style="border:1px solid black;"><img src="figs/iperf3.png" alt="iperf3.png" width="100%" style="border:1px solid black;" /></a>
-</p>
-<p><span class="figure-number">Figure 1: </span>iperf3 / monitoring</p>
-</div>
-</div>
-</div>
-
-
-<div id="outline-container-org830e31f" class="outline-3">
-<h3 id="org830e31f"><span class="section-number-3">4.3</span> Discussion</h3>
-<div class="outline-text-3" id="text-4-3">
-<p>
-So, far this seems (at least for me) very handy. But there might be some problems in our setup:
-</p>
 <ul class="org-ul">
-<li>we aren't isolated from the other users</li>
-<li>we aren't isolated from ourself in the sense that the monitoring stack generates its own 
-network traffic (yes, this is negligible in our case)</li>
+<li>First tutorial: <a href="./tuto1/index.html">./tuto1/index.html</a></li>
+<li>Second tutorial: <a href="./tuto2/index.html">./tuto2/index.html</a></li>
 </ul>
-
-<p>
-Sometimes it's desirable to have the following setup (see Fig. <a href="#orgf90cb97">2</a>).
-</p>
-
-
-<div id="orgf90cb97" class="figure">
-<p><a href="figs/skydive_enoslib.png"><img src="figs/skydive_enoslib.png" alt="skydive_enoslib.png" /></a>
-</p>
-<p><span class="figure-number">Figure 2: </span>nodes are using two network interfaces. Monitoring traffic and benchmark traffic are separated.</p>
-</div>
-</div>
-</div>
-
-<div id="outline-container-org5f35d8c" class="outline-3">
-<h3 id="org5f35d8c"><span class="section-number-3">4.4</span> A bit better approach</h3>
-<div class="outline-text-3" id="text-4-4">
-<p>
-Analyse/Understand the following script <a href="exercices/iperf3_better.py">exercices/iperf3_better.py</a>
-Launch it.
-</p>
-
-<div class="note">
-<p>
-On Grid'5000, using the secondary interfaces requires to <b>deploy</b> the nodes:
-an new OS will be installed on your nodes. This will give you full control on
-the physical machine (root access). This might be longer to run the
-experiment due to this deployment phase.
-</p>
-
-</div>
-</div>
-</div>
-
-<div id="outline-container-orgdddf696" class="outline-3">
-<h3 id="orgdddf696"><span class="section-number-3">4.5</span> Ninja level</h3>
-<div class="outline-text-3" id="text-4-5">
-<p>
-Add the <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html#skydive">Skydive</a> service to your deployment. 
-It should be accessible on the port <code>8082</code> of the analyzer node. You should
-get something like Fig. <a href="#orgf90cb97">2</a>.
-</p>
-</div>
-</div>
-
-<div id="outline-container-org1193557" class="outline-3">
-<h3 id="org1193557"><span class="section-number-3">4.6</span> Some references</h3>
-<div class="outline-text-3" id="text-4-6">
-<ul class="org-ul">
-<li>Services: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html</a></li>
-</ul>
-</div>
-</div>
-</div>
-
-<div id="outline-container-orgf965b96" class="outline-2">
-<h2 id="orgf965b96"><span class="section-number-2">5</span> Providers: to replicate your experiment</h2>
-<div class="outline-text-2" id="text-5">
-<div class="note">
-<p>
-The resources that are used for your experiment are acquired through a
-provider. Providers are a mean to decouple the infrastructure code (the code
-that gets the resources) from the code that runs the experiment. Changing the
-provider allows to replicate the experiment on another testbed.
-</p>
-
-</div>
-
-<p>
-Originally it was used to iterate on the code locally (using the Vagrant
-provider) and to only test on Grid'5000 when necessary.
-</p>
-
-<p>
-We now have couple of providers that you may picked or mixed.
-</p>
-</div>
-
-<div id="outline-container-orgad471c7" class="outline-3">
-<h3 id="orgad471c7"><span class="section-number-3">5.1</span> iperf3 on virtual machines on Grid'5000</h3>
-<div class="outline-text-3" id="text-5-1">
-<p>
-We'll adapt the initial iperf3 example to use virtual machines instead of
-bare-metal machine. 
-</p>
-
-<p>
-Note that:
-</p>
-
-<ul class="org-ul">
-<li>The configuration object is different</li>
-<li>The experimentation logic is the same</li>
-<li>Some part have been rewritten using modules (see later in the dedicated section).</li>
-</ul>
-
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.api <span style="color: #4f97d7; font-weight: bold;">import</span> play_on, wait_ssh
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_vmong5k.provider <span style="color: #4f97d7; font-weight: bold;">import</span> VMonG5k
-<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_vmong5k.configuration <span style="color: #4f97d7; font-weight: bold;">import</span> Configuration
-
-<span style="color: #4f97d7; font-weight: bold;">import</span> logging
-<span style="color: #4f97d7; font-weight: bold;">import</span> os
-
-logging.basicConfig<span style="color: #4f97d7;">(</span>level=logging.DEBUG<span style="color: #4f97d7;">)</span>
-
-<span style="color: #7590db;">CLUSTER</span> = <span style="color: #2d9574;">"paravance"</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">path to the inventory</span>
-<span style="color: #7590db;">inventory</span> = os.path.join<span style="color: #4f97d7;">(</span>os.getcwd<span style="color: #bc6ec5;">()</span>, <span style="color: #2d9574;">"hosts"</span><span style="color: #4f97d7;">)</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">claim the resources</span>
-<span style="color: #7590db;">conf</span> = Configuration.from_settings<span style="color: #4f97d7;">(</span>job_name=<span style="color: #2d9574;">"enoslib_tutorial"</span>, gateway=<span style="color: #a45bad;">True</span><span style="color: #4f97d7;">)</span>\
-                    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
-                                 cluster=CLUSTER,
-                                 number=<span style="color: #a45bad;">1</span>,
-                                 flavour=<span style="color: #2d9574;">"large"</span><span style="color: #4f97d7;">)</span>\
-                    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
-                                 cluster=CLUSTER,
-                                 number=<span style="color: #a45bad;">1</span>,
-                                 flavour=<span style="color: #2d9574;">"medium"</span><span style="color: #4f97d7;">)</span>\
-                    .finalize<span style="color: #4f97d7;">()</span>
-
-<span style="color: #7590db;">provider</span> = VMonG5k<span style="color: #4f97d7;">(</span>conf<span style="color: #4f97d7;">)</span>
-
-<span style="color: #7590db;">roles</span>, <span style="color: #7590db;">networks</span> = provider.init<span style="color: #4f97d7;">()</span>
-wait_ssh<span style="color: #4f97d7;">(</span>roles<span style="color: #4f97d7;">)</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Below is the experimentation logic</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">It installs the bare minimum to run iperf3</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">The machine with the role 'server' is used to run a iperf3 server</span>
-<span style="color: #2aa1ae; background-color: #292e34;">#     </span><span style="color: #2aa1ae; background-color: #292e34;">started in the background in a tmux</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">The machine with the role 'client' connects to that server</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Report is printed in stdout</span>
-<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
-
-<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
-    p.apt<span style="color: #4f97d7;">(</span>name=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"iperf3"</span>, <span style="color: #2d9574;">"tmux"</span><span style="color: #bc6ec5;">]</span>, state=<span style="color: #2d9574;">"present"</span><span style="color: #4f97d7;">)</span>
-
-<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>pattern_hosts=<span style="color: #2d9574;">"server"</span>, roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
-    p.shell<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"tmux new-session -d 'exec iperf3 -s'"</span><span style="color: #4f97d7;">)</span>
-
-<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
-    p.shell<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t 30"</span><span style="color: #4f97d7;">)</span>
-
-<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
-    p.shell<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t 30 --logfile iperf3.out"</span><span style="color: #4f97d7;">)</span>
-    p.fetch<span style="color: #4f97d7;">(</span>src=<span style="color: #2d9574;">"iperf3.out"</span>, dest=<span style="color: #2d9574;">"iperf3.out"</span><span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<p>
-Using module using the <code>play_on</code> context manager does not bring back the
-results of the commands. Iperf3 let's you write the result of the command on
-a file. We just need to scp the file back to our local machine using the
-<code>fetch</code> module.
-</p>
-</div>
-</div>
-
-
-<div id="outline-container-org08faf88" class="outline-3">
-<h3 id="org08faf88"><span class="section-number-3">5.2</span> References</h3>
-<div class="outline-text-3" id="text-5-2">
-<ul class="org-ul">
-<li>Doc: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html</a></li>
-<li>Sources: <a href="https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra">https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra</a></li>
-</ul>
-</div>
-</div>
-</div>
-
-
-<div id="outline-container-org56f9c08" class="outline-2">
-<h2 id="org56f9c08"><span class="section-number-2">6</span> Variables in EnOSlib</h2>
-<div class="outline-text-2" id="text-6">
-<p>
-Learn how to get 2 nodes from Grid'5000 and start launching remote commands.
-</p>
-</div>
-
-<div id="outline-container-org2281689" class="outline-3">
-<h3 id="org2281689"><span class="section-number-3">6.1</span> Discover the <code>run</code> command and its variants</h3>
-<div class="outline-text-3" id="text-6-1">
-<p>
-Before proceeding you can add this util function to your code. It is only
-used to pretty print a python dictionnary.
-</p>
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">def</span> <span style="color: #bc6ec5; font-weight: bold;">pprint</span><span style="color: #4f97d7;">(</span>d<span style="color: #4f97d7;">)</span>:
-    <span style="color: #4f97d7; font-weight: bold;">import</span> json
-    <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>json.dumps<span style="color: #bc6ec5;">(</span>d, indent=<span style="color: #a45bad;">4</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<p>
-And use the <code>enoslib.api.run</code> function 
-</p>
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Using run</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
-<span style="color: #7590db;">result</span> = run<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"ping -c 5 {server.address}"</span>, roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span><span style="color: #4f97d7;">)</span>
-pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<p>
-Or the <code>enoslib.api.run_command</code> function
-</p>
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Using run_command 1/2</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
-<span style="color: #7590db;">result</span> = run_command<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"ping -c 5 {server.address}"</span>,
-                     pattern_hosts=<span style="color: #2d9574;">"client"</span>,
-                     roles=roles<span style="color: #4f97d7;">)</span>
-pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<div class="note">
-<p>
-<code>enoslib.api.run</code> is a specialisation of <code>enoslib.api.run_command</code>. 
-The latter let's you use <a href="https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html">some fancy patterns</a> to determine the list of hosts to run the command on.
-</p>
-
-<p>
-And yes, it uses Ansible behind the scene.
-</p>
-
-</div>
-</div>
-</div>
-
-<div id="outline-container-orgd2c7291" class="outline-3">
-<h3 id="orgd2c7291"><span class="section-number-3">6.2</span> Advanced usages</h3>
-<div class="outline-text-3" id="text-6-2">
-<div class="note">
-<p>
-For all the remote interactions, EnOSlib relies on <a href="https://docs.ansible.com/ansible/latest/index.html">Ansible</a>. Ansible
-has it own variables management system.
-For instance the task <code>Gather Facts</code> at the beginning of the previous tasks
-gathers informations about all/some remote hosts and store them in the
-Ansible management system.
-</p>
-
-</div>
-
-<p>
-Let's see what Ansible is gathering about the hosts:
-</p>
-
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Gather facts</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
-<span style="color: #7590db;">result</span> = gather_facts<span style="color: #4f97d7;">(</span>roles=roles<span style="color: #4f97d7;">)</span>
-pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<div class="note">
-<p>
-EnOSlib sits in between two worlds: the Python world and the Ansible
-world. One common need is to pass a variables from one world to another.
-</p>
-<ul class="org-ul">
-<li><code>enoslib.api.gather_facts</code> is a way to get, in Python, the variables known
-by Ansible about each host.</li>
-<li><code>extra_vars</code> keyword argument of <code>enoslib.api.run</code> or <code>enoslib.api.run_command</code> will 
-pass variables from Python world to Ansible world (global variable)</li>
-<li>Injecting a key/value in a <code>Host.extra</code> attribute will make the variable <code>key</code> available to Ansible.
-This makes the variables Host specific.</li>
-</ul>
-
-</div>
-
-<p>
-The following inject a global variable in the Ansible world
-</p>
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Passing a variable to the Ansible World using a global level variable</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
-<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
-<span style="color: #7590db;">extra_vars</span>=<span style="color: #4f97d7;">{</span><span style="color: #2d9574;">"server_ip"</span>: server.address<span style="color: #4f97d7;">}</span>
-<span style="color: #7590db;">result</span> = run<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"ping -c 5 {{ server_ip }}"</span>, roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>, extra_vars=extra_vars<span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-</div>
-</div>
-
-<div id="outline-container-orgd78a6d8" class="outline-3">
-<h3 id="orgd78a6d8"><span class="section-number-3">6.3</span> Ninja level</h3>
-<div class="outline-text-3" id="text-6-3">
-<p>
-The following is valid and inject in the <code>client</code> host a specific variable to
-keep track of the server IP.
-</p>
-
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Passing a variable to the Ansible World using a host level variable</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
-<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
-<span style="color: #7590db;">client</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
-client.extra.update<span style="color: #4f97d7;">(</span>server_ip=server.address<span style="color: #4f97d7;">)</span>
-<span style="color: #7590db;">result</span> = run<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"ping -c 5 {{ server_ip }}"</span>, roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span><span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<div class="note">
-<p>
-Host level variables are interesting to introduce some dissymetry between
-hosts while still using one single command to reach all of them.
-</p>
-
-</div>
-
-<div class="question">
-<p>
-How to perform simultaneously the ping to the other machine in calling only
-once <code>run</code> or <code>run_command</code> and using host level variables?
-</p>
-
-</div>
-
-<div class="question">
-<p>
-We'd like to create 5 <code>server</code> machines and 5 <code>client</code> machines and start 5
-<b>parallel</b> streams of data using <code>iperf3</code>. To answer this we'll need to learn
-a bit more on how variables are handled in EnOSlib.
-</p>
-
-</div>
-</div>
-</div>
-
-<div id="outline-container-orge739be4" class="outline-3">
-<h3 id="orge739be4"><span class="section-number-3">6.4</span> Putting all together</h3>
-<div class="outline-text-3" id="text-6-4">
-<p>
-Access the full file: <a href="exercices/run.py">exercices/run.py</a>
-</p>
-</div>
-</div>
-
-<div id="outline-container-org5dafa08" class="outline-3">
-<h3 id="org5dafa08"><span class="section-number-3">6.5</span> Some references</h3>
-<div class="outline-text-3" id="text-6-5">
-<ul class="org-ul">
-<li>G5k configuration schema: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html#g5k-schema">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html#g5k-schema</a></li>
-<li>API Reference: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html</a></li>
-</ul>
-</div>
-</div>
-</div>
-
-<div id="outline-container-orga167566" class="outline-2">
-<h2 id="orga167566"><span class="section-number-2">7</span> Modules: for safer remote actions</h2>
-<div class="outline-text-2" id="text-7">
-<p>
-In this section we'll discover the idiomatic way of managing resources on the
-remote hosts. A resource can be anything: a user, a file, a line in a file, a
-repo on Gitlab, a firewall rule &#x2026;
-</p>
-</div>
-
-
-<div id="outline-container-orgc30170a" class="outline-3">
-<h3 id="orgc30170a"><span class="section-number-3">7.1</span> Idempotency</h3>
-<div class="outline-text-3" id="text-7-1">
-<p>
-Let's assume you want to create a user (<code>foo</code>). With the <code>run_command</code> this would look like:
-</p>
-
-<div class="org-src-container">
-<pre class="src src-python">run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"useradd -m foo"</span>, roles=role<span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<p>
-The main issue with this code is that it is not <b>idempotent</b>. Running it once
-will applied the effect (create the user). But, as soon as the user exist in
-the system, this will raise an error.
-</p>
-</div>
-</div>
-
-<div id="outline-container-org334a244" class="outline-3">
-<h3 id="org334a244"><span class="section-number-3">7.2</span> One reason why idempotency is important</h3>
-<div class="outline-text-3" id="text-7-2">
-<p>
-Let's consider the following snippet (mispelling the second command is intentional)
-</p>
-<div class="org-src-container">
-<pre class="src src-python">run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"useradd -m foo"</span>, roles=role<span style="color: #4f97d7;">)</span>
-run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"mkdirz plop"</span><span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-<p>
-Executing the above leads the system with the user <code>foo</code> created but the the
-directory <code>plop</code> not created since the second command fails.
-</p>
-
-<p>
-So what you want to do is to fix the second command and re-run the snippet again.
-But, you can't do that because <code>useradd</code> isn't idempotent.
-</p>
-</div>
-</div>
-
-<div id="outline-container-orgcf77118" class="outline-3">
-<h3 id="orgcf77118"><span class="section-number-3">7.3</span> Idempotency trick</h3>
-<div class="outline-text-3" id="text-7-3">
-<p>
-One easy solution is to protect your call to non idempotent commands with
-some ad'hoc tricks
-</p>
-
-<p>
-Here it can look like this:
-</p>
-
-<div class="org-src-container">
-<pre class="src src-python">run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"id foo || useradd -m foo"</span>, roles=role<span style="color: #4f97d7;">)</span>
-run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"mkdir -p plop"</span><span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<p>
-<b>What's wrong with that</b>
-</p>
-
-<ul class="org-ul">
-<li>The trick depends on the command</li>
-<li>Re-reading the code is more complex: the code focus on the <b><b>how</b></b> not the <b><b>what</b></b></li>
-</ul>
-</div>
-</div>
-
-<div id="outline-container-orgcaa5aa0" class="outline-3">
-<h3 id="orgcaa5aa0"><span class="section-number-3">7.4</span> General idempotency</h3>
-<div class="outline-text-3" id="text-7-4">
-<p>
-The idiomatic solution is to use modules (inherited from the Ansible
-Modules). The modules are specified in a <b>declarative</b> way and they ensure
-<b>idempotency</b> for most of them.
-</p>
-
-<p>
-So rewriting the example with modules looks like:
-</p>
-<div class="org-src-container">
-<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
-    p.user<span style="color: #4f97d7;">(</span>name=<span style="color: #2d9574;">"foo"</span>, state=<span style="color: #2d9574;">"present"</span>, create_home=<span style="color: #2d9574;">"yes"</span><span style="color: #4f97d7;">)</span>
-    p.<span style="color: #4f97d7;">file</span><span style="color: #4f97d7;">(</span>name=<span style="color: #2d9574;">"plop"</span>, state=<span style="color: #2d9574;">"directory"</span><span style="color: #4f97d7;">)</span>
-</pre>
-</div>
-
-<p>
-<code>enoslib.api.play_on</code> is the entry point to the module system.
-</p>
-
-<p>
-You can run this code as many times as you want without any error. You'll
-eventually find one user <code>foo</code> and one directory <code>plop</code> in your target
-systems.
-</p>
-
-<p>
-They are more than 2500 modules: <a href="https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html">https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html</a>
-</p>
-
-<p>
-If you can't find what you want you must know that:
-</p>
-<ul class="org-ul">
-<li>Writing your own module is possible</li>
-<li>Falling back to the idempotency trick is reasonable</li>
-</ul>
-</div>
-</div>
-</div>
-
-<div id="outline-container-orgb39fe8f" class="outline-2">
-<h2 id="orgb39fe8f"><span class="section-number-2">8</span> Tasks: to organize your experiment</h2>
-<div class="outline-text-2" id="text-8">
-<p>
-To discover the Task API, head to <a href="https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html">https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html</a>.
-</p>
-
-<p>
-The examples are written for Vagrant but may be changed to whatever provider you like/have.
-</p>
-
-<div class="question">
-<p>
-Adapt the <code>iperf3</code> example to provide a command line
-</p>
-<ul class="org-ul">
-<li><p>
-Either using G5k physical machines:
-</p>
-<div class="org-src-container">
-<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">deploy the dependencies of the experimentation using the G5k provider</span>
-myperf g5k
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">launch a performance measurement</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">ideally exposes all the iperf3 client options there ;)</span>
-myperf bench -t <span style="color: #a45bad;">120</span>
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Backup the reports / influxdb database</span>
-myperf backup
-</pre>
-</div>
-
-<p>
-myperf destroy
-</p></li>
-
-<li><p>
-Either using the virtual machines on Grid'5000:
-</p>
-<div class="org-src-container">
-<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">deploy the dependencies of the experimentation using the G5k provider</span>
-myperf vm5k
-
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Subsequent command line should be the same as above</span>
-<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">enjoy :)</span>
-</pre>
-</div></li>
-</ul>
-
-</div>
-</div>
-</div>
 </div>
 <div id="postamble" class="status">
 <p class="author">Author: Matthieu Simonin</p>
-<p class="date">Created: 2019-11-15 ven. 14:14</p>
+<p class="date">Created: 2019-11-29 ven. 00:28</p>
 <p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
 </div>
 </body>
diff --git a/index.org b/index.org
index 777996da50565341ddd8ed47ba611b9e44dd874c..c3c9d6c65454d8fbaa1ebc5464e22d9f93f3b7fc 100644
--- a/index.org
+++ b/index.org
@@ -4,425 +4,6 @@
 
 #+HTML_HEAD: <link rel="stylesheet" type="text/css" href="timeline.css" />
 
-#+MACRO: enoslib EnOSlib
-#+MACRO: src_host https://gitlab.inria.fr/discovery/enoslib/blob/v4.8.1/enoslib/host.py#L8-14
-#+MACRO: doc_external_access https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html#accessing-http-services-inside-grid-5000
-#+MACRO: src_provider https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra
-#+MACRO: doc_provider https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html
-#+MACRO: doc_tasks https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html
-#+MACRO: doc_g5k_schema https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html#g5k-schema
-#+MACRO: doc_api https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html
-#+MACRO: doc_services https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html
-
-* Foreword
-
-** Existing tools (Grid'5000)
-
-    - {{{enoslib}}} falls under the **Experiment management tools** of the following
-      list:
-      https://www.grid5000.fr/w/Grid5000:Software
-
-    - {{{enoslib}}} can target Grid'5000 but also other testbeds (Chameleon, local machines...)
-
-    - {{{enoslib}}} provides high level constructs to help you with your experiments
-
-** EnOSlib quicktour
-   
-    - Documentation: https://discovery.gitlabpages.inria.fr/enoslib/index.html 
-    - Source:  https://gitlab.inria.fr/discovery/enoslib
-    - Reach us on:
-        + https://framateam.org/enoslib
-        + https://gitlab.inria.fr/discovery/enoslib/issues
-
-** Contributing
-  
-    *Before experimenting*
-
-    - Tell us what your plans are:
-      + There might be already users doing similar thing
-      + There might be some missing/hidden pieces in the library you might need
-
-    *While experimenting*
-
-    - Write bug reports / ask questions
-    - Fix bugs / add your features
-
-    *After experimenting*
-
-    - Give your feedback
-    - Add yourself to the list: https://discovery.gitlabpages.inria.fr/enoslib/theyuseit.html
-
-
-* Before you start
-
-  #+begin_note
-  make sure you are familiar with the grid'5000 architecture. see section 1 & 2 of
-  https://www.grid5000.fr/w/Getting_Started. note that we won't do this tutorial
-  we'll prefer to use higher level tools for now.
-  #+end_note
-
-* Setup on Grid'5000
-
-  Connect to a Grid'5000 frontend of your choice (e.g rennes, nancy ...)
-
-  - create a new directory to host all the scripts of the session
-  - bootstrap a new python3 virtualenv 
-  - install {{{enoslib}}} and configure the access to the API
-
-  #+BEGIN_SRC bash :noeval
-  $frontend: mkdir enoslib_seminar
-  $frontend: cd enoslib_seminar
-  $frontend: virtualenv --python=python3 venv
-  $frontend: source venv/bin/activate
-  $frontend(venv): pip install enoslib
-  $frontend(venv): echo '
-  verify_ssl: False
-  ' > ~/.python-grid5000.yaml
-  #+END_SRC
-
-* Your first experiment on Grid'5000
-
-  Let's experiment with [[https://iperf.fr/][iperf3]]: a network bandwidth measuring tool. The goal is
-  to deploy a simple benchmark between two hosts. 
-
-  We'll also instrument the deployment in order to visualize in real-time the
-  network traffic between the hosts. Since this is super common, {{{enoslib}}}
-  exposes a /monitoring service/ that lets you deploy very quickly what is
-  needed.
-  
-** First iteration
-  
-   We consider the following script
-   #+INCLUDE: exercices/iperf3.py src python
-
-    #+BEGIN_question
-    How fast is the network between the nodes you have chosen ?
-    #+END_question
-
-    #+BEGIN_note
-    Before moving to the next questions, you'll need to clean the reservation.
-    You can either uncomment the line ~provider.destroy()~ at the end of the script.
-    You can also do it manually using the low-level ~oarstat~ / ~oardel~ tools.
-
-    #+BEGIN_SRC bash :noeval
-    # get you reservation id
-    $frontend: oarstat -u
-    # release the resources / kill the reservation
-    $frontend: oardel <the id of the reservation goes here>
-    #+END_SRC
-    #+END_note
-
-    #+BEGIN_question
-    Can you adapt the script so that:
-    1. The two nodes are in two different cluster in the same site ?
-    2. The two nodes are in two different sites ?
-    #+END_question
-
-
-**  Let's observe in real-time what is happening
-
-    #+BEGIN_note
-    Make sure you have cleaned your previous reservations.
-    #+END_note
-
-    The following script installs a monitoring stack on your nodes. This is almost
-    the same script as before except the lines corresponding to the configuration
-    of the monitoring stack.
-
-    #+INCLUDE: exercices/iperf3_monitoring.py src python
-
-    Now, let's visualize the network traffic in real-time !
-    #+BEGIN_note
-    Usually I follow this to access services running inside Grid'5000:
-    {{{doc_external_access}}}.
-
-
-    Today you can just create a tunnel like this (from your local machine).
-
-    #+BEGIN_SRC bash :noeval
-    # Adapt the node names with the node where grafana (the UI) has been installed
-    # Replace <login> by your Grid'5000 login
-    $yourmachine: ssh -NL 3000:paravance-16.rennes.grid5000.fr:3000 <login>@access.grid5000.fr
-
-    # point your browser to localhost:3000
-    # username/mdp: admin/admin
-    #+END_SRC
-
-    #+END_note
-
-    Part of the experimenter work also consists in analysing the data. Here it
-    corresponds in writing the right request to monitor the traffic (check the
-    Fig. [[fig:iperf3]]). You should be able to visualize such a thing (after a bit
-    of point and clicks).
-
-    #+CAPTION: iperf3 / monitoring
-    #+NAME:   fig:iperf3
-    #+ATTR_HTML: :width 100% :style border:1px solid black;
-    [[file:figs/iperf3.png][file:figs/iperf3.png]]
-
-
-** Discussion
-   
-   So, far this seems (at least for me) very handy. But there might be some problems in our setup:
-   - we aren't isolated from the other users
-   - we aren't isolated from ourself in the sense that the monitoring stack generates its own 
-     network traffic (yes, this is negligible in our case)
-   
-   Sometimes it's desirable to have the following setup (see Fig. [[fig:two_networks]]).
-
-    #+CAPTION: nodes are using two network interfaces.
-    #+CAPTION: Monitoring traffic and benchmark traffic are separated.
-    #+NAME:   fig:two_networks
-   [[file:figs/skydive_enoslib.png][file:figs/skydive_enoslib.png]]
-
-** A bit better approach
-
-   Analyse/Understand the following script [[file:exercices/iperf3_better.py]]
-   Launch it.
-
-   #+BEGIN_note
-   On Grid'5000, using the secondary interfaces requires to *deploy* the nodes:
-   an new OS will be installed on your nodes. This will give you full control on
-   the physical machine (root access). This might be longer to run the
-   experiment due to this deployment phase.
-   #+END_note
-
-** Ninja level
-
-   Add the [[https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html#skydive][Skydive]] service to your deployment. 
-   It should be accessible on the port ~8082~ of the analyzer node. You should
-   get something like Fig. [[fig:two_networks]].
-
-** Some references
-   
-   - Services: {{{doc_services}}}
-   
-* Providers: to replicate your experiment
-
-  #+BEGIN_note
-  The resources that are used for your experiment are acquired through a
-  provider. Providers are a mean to decouple the infrastructure code (the code
-  that gets the resources) from the code that runs the experiment. Changing the
-  provider allows to replicate the experiment on another testbed.
-  #+END_note
-
-  Originally it was used to iterate on the code locally (using the Vagrant
-  provider) and to only test on Grid'5000 when necessary.
-
-  We now have couple of providers that you may picked or mixed.
-
-** iperf3 on virtual machines on Grid'5000
-
-   We'll adapt the initial iperf3 example to use virtual machines instead of
-   bare-metal machine. 
-
-   Note that:
-   
-   - The configuration object is different
-   - The experimentation logic is the same
-   - Some part have been rewritten using modules (see later in the dedicated section).
-
-   #+INCLUDE: exercices/iperf3_vms.py src python
-
-   Using module using the ~play_on~ context manager does not bring back the
-   results of the commands. Iperf3 let's you write the result of the command on
-   a file. We just need to scp the file back to our local machine using the
-   ~fetch~ module.
-
-   
-** References
-
-   - Doc: {{{doc_provider}}} 
-   - Sources: {{{src_provider}}}
-
-
-* Variables in {{{enoslib}}}
-  
-  Learn how to get 2 nodes from Grid'5000 and start launching remote commands.
-
-** Discover the ~run~ command and its variants
-
-    Before proceeding you can add this util function to your code. It is only
-    used to pretty print a python dictionnary.
-    #+INCLUDE: exercices/run.py :lines "35-39" src python
-
-    And use the ~enoslib.api.run~ function 
-    #+INCLUDE: exercices/run.py :lines "40-47" src python
-   
-    Or the ~enoslib.api.run_command~ function
-    #+INCLUDE: exercices/run.py :lines "48-56" src python
-
-    #+BEGIN_note
-    ~enoslib.api.run~ is a specialisation of ~enoslib.api.run_command~. 
-    The latter let's you use [[https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html][some fancy patterns]] to determine the list of hosts to run the command on.
-
-    And yes, it uses Ansible behind the scene.
-    #+END_note
-
-** Advanced usages
-    
-   #+BEGIN_note
-   For all the remote interactions, {{{enoslib}}} relies on [[https://docs.ansible.com/ansible/latest/index.html][Ansible]]. Ansible
-   has it own variables management system.
-   For instance the task ~Gather Facts~ at the beginning of the previous tasks
-   gathers informations about all/some remote hosts and store them in the
-   Ansible management system.
-   #+END_note
-
-   Let's see what Ansible is gathering about the hosts:
-
-   #+INCLUDE: exercices/run.py :lines "58-65" src python
-
-   #+BEGIN_note
-   {{{enoslib}}} sits in between two worlds: the Python world and the Ansible
-   world. One common need is to pass a variables from one world to another.
-   - ~enoslib.api.gather_facts~ is a way to get, in Python, the variables known
-     by Ansible about each host.
-   - ~extra_vars~ keyword argument of ~enoslib.api.run~ or ~enoslib.api.run_command~ will 
-     pass variables from Python world to Ansible world (global variable)
-   - Injecting a key/value in a ~Host.extra~ attribute will make the variable ~key~ available to Ansible.
-     This makes the variables Host specific.
-   #+END_note
-
-   The following inject a global variable in the Ansible world
-   #+INCLUDE: exercices/run.py :lines "65-71" src python
-
-** Ninja level
-
-   The following is valid and inject in the ~client~ host a specific variable to
-   keep track of the server IP.
-
-   #+INCLUDE: exercices/run.py :lines "73-81" src python
-
-   #+BEGIN_note
-   Host level variables are interesting to introduce some dissymetry between
-   hosts while still using one single command to reach all of them.
-   #+END_note
-
-   #+BEGIN_question
-   How to perform simultaneously the ping to the other machine in calling only
-   once ~run~ or ~run_command~ and using host level variables?
-   #+END_question
-
-  #+BEGIN_question
-  We'd like to create 5 ~server~ machines and 5 ~client~ machines and start 5
-  *parallel* streams of data using ~iperf3~. To answer this we'll need to learn
-  a bit more on how variables are handled in {{{enoslib}}}.
-  #+END_question
-
-** Putting all together
-   Access the full file: [[file:exercices/run.py]]
-
-** Some references
-
-   - G5k configuration schema: {{{doc_g5k_schema}}}
-   - API Reference: {{{doc_api}}}
-
-* Modules: for safer remote actions
-  
-  In this section we'll discover the idiomatic way of managing resources on the
-  remote hosts. A resource can be anything: a user, a file, a line in a file, a
-  repo on Gitlab, a firewall rule ...
-
-
-** Idempotency
-
-  Let's assume you want to create a user (~foo~). With the ~run_command~ this would look like:
-
-  #+BEGIN_SRC python :noeval 
-  run_command("useradd -m foo", roles=role)
-  #+END_SRC
-
-  The main issue with this code is that it is not *idempotent*. Running it once
-  will applied the effect (create the user). But, as soon as the user exist in
-  the system, this will raise an error.
-
-** One reason why idempotency is important
-
-  Let's consider the following snippet (mispelling the second command is intentional)
-  #+BEGIN_SRC python :noeval 
-  run_command("useradd -m foo", roles=role)
-  run_command("mkdirz plop")
-  #+END_SRC
-  Executing the above leads the system with the user ~foo~ created but the the
-  directory ~plop~ not created since the second command fails.
-
-  So what you want to do is to fix the second command and re-run the snippet again.
-  But, you can't do that because ~useradd~ isn't idempotent.
-
-** Idempotency trick
-
-   One easy solution is to protect your call to non idempotent commands with
-   some ad'hoc tricks
-
-   Here it can look like this:
-
-   #+BEGIN_SRC python :noeval 
-   run_command("id foo || useradd -m foo", roles=role)
-   run_command("mkdir -p plop")
-   #+END_SRC
-
-   *What's wrong with that*
-
-   - The trick depends on the command
-   - Re-reading the code is more complex: the code focus on the **how** not the **what**
-
-** General idempotency
-    
-   The idiomatic solution is to use modules (inherited from the Ansible
-   Modules). The modules are specified in a *declarative* way and they ensure
-   *idempotency* for most of them.
-
-   So rewriting the example with modules looks like:
-   #+BEGIN_SRC python :noeval 
-   with play_on(roles=roles) as p:
-       p.user(name="foo", state="present", create_home="yes")
-       p.file(name="plop", state="directory")
-   #+END_SRC
-   
-   ~enoslib.api.play_on~ is the entry point to the module system.
-
-   You can run this code as many times as you want without any error. You'll
-   eventually find one user ~foo~ and one directory ~plop~ in your target
-   systems.
-
-   They are more than 2500 modules: https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
-
-   If you can't find what you want you must know that:
-   - Writing your own module is possible
-   - Falling back to the idempotency trick is reasonable
-
-* Tasks: to organize your experiment
-
-  To discover the Task API, head to {{{doc_tasks}}}.
-
-  The examples are written for Vagrant but may be changed to whatever provider you like/have.
-
-   #+BEGIN_question
-   Adapt the ~iperf3~ example to provide a command line
-    - Either using G5k physical machines:
-      #+BEGIN_SRC bash
-      # deploy the dependencies of the experimentation using the G5k provider
-      myperf g5k
-
-      # launch a performance measurement
-      # ideally exposes all the iperf3 client options there ;)
-      myperf bench -t 120
-
-      # Backup the reports / influxdb database
-      myperf backup
-      #+END_SRC
-
-      # Destroy the ressources on Grid'5000
-      myperf destroy
-
-    - Either using the virtual machines on Grid'5000:
-      #+BEGIN_SRC bash
-      # deploy the dependencies of the experimentation using the G5k provider
-      myperf vm5k
-
-      # Subsequent command line should be the same as above
-      # enjoy :)
-      #+END_SRC
-   #+END_question
 
+- First tutorial: [[./tuto1/index.html]]
+- Second tutorial: [[./tuto2/index.html]]
diff --git a/tuto1/exercices/.#00_setup.sh b/tuto1/exercices/.#00_setup.sh
new file mode 120000
index 0000000000000000000000000000000000000000..7c7e5b335f82fad0ead6fd3f20b98fa0071102f1
--- /dev/null
+++ b/tuto1/exercices/.#00_setup.sh
@@ -0,0 +1 @@
+msimonin@talouette.27523:1570544298
\ No newline at end of file
diff --git a/exercices/iperf3.py b/tuto1/exercices/iperf3.py
similarity index 100%
rename from exercices/iperf3.py
rename to tuto1/exercices/iperf3.py
diff --git a/exercices/iperf3_5vms.py b/tuto1/exercices/iperf3_5vms.py
similarity index 100%
rename from exercices/iperf3_5vms.py
rename to tuto1/exercices/iperf3_5vms.py
diff --git a/exercices/iperf3_better.py b/tuto1/exercices/iperf3_better.py
similarity index 100%
rename from exercices/iperf3_better.py
rename to tuto1/exercices/iperf3_better.py
diff --git a/exercices/iperf3_monitoring.py b/tuto1/exercices/iperf3_monitoring.py
similarity index 100%
rename from exercices/iperf3_monitoring.py
rename to tuto1/exercices/iperf3_monitoring.py
diff --git a/exercices/iperf3_vms.py b/tuto1/exercices/iperf3_vms.py
similarity index 100%
rename from exercices/iperf3_vms.py
rename to tuto1/exercices/iperf3_vms.py
diff --git a/tuto1/exercices/iperfs_xvms.py b/tuto1/exercices/iperfs_xvms.py
new file mode 100644
index 0000000000000000000000000000000000000000..65e478b9d9fc7d28220beb3aa78995704986501b
--- /dev/null
+++ b/tuto1/exercices/iperfs_xvms.py
@@ -0,0 +1,59 @@
+from enoslib.api import play_on, wait_ssh, ensure_python3
+from enoslib.infra.enos_vmong5k.provider import VMonG5k
+from enoslib.infra.enos_vmong5k.configuration import Configuration
+
+import logging
+import os
+
+logging.basicConfig(level=logging.DEBUG)
+
+CLUSTER = "paravance"
+NB_VMS = 4
+
+def bench(nb_vms: int) -> None:
+    # claim the resources
+    conf = Configuration.from_settings(job_name="enoslib_tutorial_", gateway=True)\
+                        .add_machine(roles=["server"],
+                                    cluster=CLUSTER,
+                                    number=nb_vms,
+                                    flavour="tiny")\
+                        .add_machine(roles=["client"],
+                                    cluster=CLUSTER,
+                                    number=nb_vms,
+                                    flavour="tiny")\
+                        .finalize()
+
+    provider = VMonG5k(conf)
+
+    roles, networks = provider.init()
+    wait_ssh(roles)
+
+
+    servers = roles["server"]
+    clients = roles["client"]
+
+    for s, c in zip(servers, clients):
+        c.extra.update(target=s.address)
+
+    # Install python3 and make it the default
+    ensure_python3(roles=roles)
+
+    with play_on(roles=roles) as p:
+        p.apt_repository(repo="deb http://deb.debian.org/debian stretch main contrib non-free",
+                        state="present")
+        p.apt(name=["flent", "netperf", "python3-setuptools", "python3-matplotlib", "tmux"],
+            state="present")
+
+    with play_on(pattern_hosts="server", roles=roles) as p:
+        p.shell("tmux new-session -d 'exec netperf'")
+
+    with play_on(pattern_hosts="client", roles=roles) as p:
+        p.shell("flent tcp_upload -p totals "
+                + "-l 60 "
+                + "-H {{ target }} "
+                + f"-t 'tcp_upload_{nb_vms}' "
+                + f"-o tcp_upload_{nb_vms}.png", display_name=f"Benchmarkings with {nb_vms} vms")
+        p.fetch(src=f"tcp_upload_{nb_vms}.png", dest=f"result_{nb_vms}")
+
+for nb_vms in [1, 4, 8, 16]:
+    bench(nb_vms)
diff --git a/exercices/run.py b/tuto1/exercices/run.py
similarity index 100%
rename from exercices/run.py
rename to tuto1/exercices/run.py
diff --git a/tuto1/exercices/test.py b/tuto1/exercices/test.py
new file mode 100644
index 0000000000000000000000000000000000000000..6d47d35a6a2de12792eb726e13bfe6287dbc7a7d
--- /dev/null
+++ b/tuto1/exercices/test.py
@@ -0,0 +1,11 @@
+from enoslib.api import play_on
+from enoslib.host import Host
+
+import logging
+
+
+logging.basicConfig(level=logging.DEBUG)
+
+roles = {"all": [Host("localhost", extra={"ansible_connection": "local"})]}
+with play_on(roles=roles) as p:
+    p.shell("ls {{ ansible_connection }}")
diff --git a/figs/iperf3.png b/tuto1/figs/iperf3.png
similarity index 100%
rename from figs/iperf3.png
rename to tuto1/figs/iperf3.png
diff --git a/figs/skydive_enoslib.png b/tuto1/figs/skydive_enoslib.png
similarity index 100%
rename from figs/skydive_enoslib.png
rename to tuto1/figs/skydive_enoslib.png
diff --git a/tuto1/index.html b/tuto1/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..f69b6efaeed60d17525568a37ce78897011a2d49
--- /dev/null
+++ b/tuto1/index.html
@@ -0,0 +1,1287 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<!-- 2019-11-15 ven. 14:14 -->
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<title>Distributed experiments on Grid'5000 &#x2026; and beyond !</title>
+<meta name="generator" content="Org mode" />
+<meta name="author" content="Matthieu Simonin" />
+<style type="text/css">
+ <!--/*--><![CDATA[/*><!--*/
+  .title  { text-align: center;
+             margin-bottom: .2em; }
+  .subtitle { text-align: center;
+              font-size: medium;
+              font-weight: bold;
+              margin-top:0; }
+  .todo   { font-family: monospace; color: red; }
+  .done   { font-family: monospace; color: green; }
+  .priority { font-family: monospace; color: orange; }
+  .tag    { background-color: #eee; font-family: monospace;
+            padding: 2px; font-size: 80%; font-weight: normal; }
+  .timestamp { color: #bebebe; }
+  .timestamp-kwd { color: #5f9ea0; }
+  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
+  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
+  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
+  .underline { text-decoration: underline; }
+  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
+  p.verse { margin-left: 3%; }
+  pre {
+    border: 1px solid #ccc;
+    box-shadow: 3px 3px 3px #eee;
+    padding: 8pt;
+    font-family: monospace;
+    overflow: auto;
+    margin: 1.2em;
+  }
+  pre.src {
+    position: relative;
+    overflow: visible;
+    padding-top: 1.2em;
+  }
+  pre.src:before {
+    display: none;
+    position: absolute;
+    background-color: white;
+    top: -10px;
+    right: 10px;
+    padding: 3px;
+    border: 1px solid black;
+  }
+  pre.src:hover:before { display: inline;}
+  /* Languages per Org manual */
+  pre.src-asymptote:before { content: 'Asymptote'; }
+  pre.src-awk:before { content: 'Awk'; }
+  pre.src-C:before { content: 'C'; }
+  /* pre.src-C++ doesn't work in CSS */
+  pre.src-clojure:before { content: 'Clojure'; }
+  pre.src-css:before { content: 'CSS'; }
+  pre.src-D:before { content: 'D'; }
+  pre.src-ditaa:before { content: 'ditaa'; }
+  pre.src-dot:before { content: 'Graphviz'; }
+  pre.src-calc:before { content: 'Emacs Calc'; }
+  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
+  pre.src-fortran:before { content: 'Fortran'; }
+  pre.src-gnuplot:before { content: 'gnuplot'; }
+  pre.src-haskell:before { content: 'Haskell'; }
+  pre.src-hledger:before { content: 'hledger'; }
+  pre.src-java:before { content: 'Java'; }
+  pre.src-js:before { content: 'Javascript'; }
+  pre.src-latex:before { content: 'LaTeX'; }
+  pre.src-ledger:before { content: 'Ledger'; }
+  pre.src-lisp:before { content: 'Lisp'; }
+  pre.src-lilypond:before { content: 'Lilypond'; }
+  pre.src-lua:before { content: 'Lua'; }
+  pre.src-matlab:before { content: 'MATLAB'; }
+  pre.src-mscgen:before { content: 'Mscgen'; }
+  pre.src-ocaml:before { content: 'Objective Caml'; }
+  pre.src-octave:before { content: 'Octave'; }
+  pre.src-org:before { content: 'Org mode'; }
+  pre.src-oz:before { content: 'OZ'; }
+  pre.src-plantuml:before { content: 'Plantuml'; }
+  pre.src-processing:before { content: 'Processing.js'; }
+  pre.src-python:before { content: 'Python'; }
+  pre.src-R:before { content: 'R'; }
+  pre.src-ruby:before { content: 'Ruby'; }
+  pre.src-sass:before { content: 'Sass'; }
+  pre.src-scheme:before { content: 'Scheme'; }
+  pre.src-screen:before { content: 'Gnu Screen'; }
+  pre.src-sed:before { content: 'Sed'; }
+  pre.src-sh:before { content: 'shell'; }
+  pre.src-sql:before { content: 'SQL'; }
+  pre.src-sqlite:before { content: 'SQLite'; }
+  /* additional languages in org.el's org-babel-load-languages alist */
+  pre.src-forth:before { content: 'Forth'; }
+  pre.src-io:before { content: 'IO'; }
+  pre.src-J:before { content: 'J'; }
+  pre.src-makefile:before { content: 'Makefile'; }
+  pre.src-maxima:before { content: 'Maxima'; }
+  pre.src-perl:before { content: 'Perl'; }
+  pre.src-picolisp:before { content: 'Pico Lisp'; }
+  pre.src-scala:before { content: 'Scala'; }
+  pre.src-shell:before { content: 'Shell Script'; }
+  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
+  /* additional language identifiers per "defun org-babel-execute"
+       in ob-*.el */
+  pre.src-cpp:before  { content: 'C++'; }
+  pre.src-abc:before  { content: 'ABC'; }
+  pre.src-coq:before  { content: 'Coq'; }
+  pre.src-groovy:before  { content: 'Groovy'; }
+  /* additional language identifiers from org-babel-shell-names in
+     ob-shell.el: ob-shell is the only babel language using a lambda to put
+     the execution function name together. */
+  pre.src-bash:before  { content: 'bash'; }
+  pre.src-csh:before  { content: 'csh'; }
+  pre.src-ash:before  { content: 'ash'; }
+  pre.src-dash:before  { content: 'dash'; }
+  pre.src-ksh:before  { content: 'ksh'; }
+  pre.src-mksh:before  { content: 'mksh'; }
+  pre.src-posh:before  { content: 'posh'; }
+  /* Additional Emacs modes also supported by the LaTeX listings package */
+  pre.src-ada:before { content: 'Ada'; }
+  pre.src-asm:before { content: 'Assembler'; }
+  pre.src-caml:before { content: 'Caml'; }
+  pre.src-delphi:before { content: 'Delphi'; }
+  pre.src-html:before { content: 'HTML'; }
+  pre.src-idl:before { content: 'IDL'; }
+  pre.src-mercury:before { content: 'Mercury'; }
+  pre.src-metapost:before { content: 'MetaPost'; }
+  pre.src-modula-2:before { content: 'Modula-2'; }
+  pre.src-pascal:before { content: 'Pascal'; }
+  pre.src-ps:before { content: 'PostScript'; }
+  pre.src-prolog:before { content: 'Prolog'; }
+  pre.src-simula:before { content: 'Simula'; }
+  pre.src-tcl:before { content: 'tcl'; }
+  pre.src-tex:before { content: 'TeX'; }
+  pre.src-plain-tex:before { content: 'Plain TeX'; }
+  pre.src-verilog:before { content: 'Verilog'; }
+  pre.src-vhdl:before { content: 'VHDL'; }
+  pre.src-xml:before { content: 'XML'; }
+  pre.src-nxml:before { content: 'XML'; }
+  /* add a generic configuration mode; LaTeX export needs an additional
+     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
+  pre.src-conf:before { content: 'Configuration File'; }
+
+  table { border-collapse:collapse; }
+  caption.t-above { caption-side: top; }
+  caption.t-bottom { caption-side: bottom; }
+  td, th { vertical-align:top;  }
+  th.org-right  { text-align: center;  }
+  th.org-left   { text-align: center;   }
+  th.org-center { text-align: center; }
+  td.org-right  { text-align: right;  }
+  td.org-left   { text-align: left;   }
+  td.org-center { text-align: center; }
+  dt { font-weight: bold; }
+  .footpara { display: inline; }
+  .footdef  { margin-bottom: 1em; }
+  .figure { padding: 1em; }
+  .figure p { text-align: center; }
+  .inlinetask {
+    padding: 10px;
+    border: 2px solid gray;
+    margin: 10px;
+    background: #ffffcc;
+  }
+  #org-div-home-and-up
+   { text-align: right; font-size: 70%; white-space: nowrap; }
+  textarea { overflow-x: auto; }
+  .linenr { font-size: smaller }
+  .code-highlighted { background-color: #ffff00; }
+  .org-info-js_info-navigation { border-style: none; }
+  #org-info-js_console-label
+    { font-size: 10px; font-weight: bold; white-space: nowrap; }
+  .org-info-js_search-highlight
+    { background-color: #ffff00; color: #000000; font-weight: bold; }
+  .org-svg { width: 90%; }
+  /*]]>*/-->
+</style>
+<link rel="stylesheet" type="text/css" href="timeline.css" />
+<script type="text/javascript">
+/*
+@licstart  The following is the entire license notice for the
+JavaScript code in this tag.
+
+Copyright (C) 2012-2018 Free Software Foundation, Inc.
+
+The JavaScript code in this tag is free software: you can
+redistribute it and/or modify it under the terms of the GNU
+General Public License (GNU GPL) as published by the Free Software
+Foundation, either version 3 of the License, or (at your option)
+any later version.  The code is distributed WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+
+As additional permission under GNU GPL version 3 section 7, you
+may distribute non-source (e.g., minimized or compacted) forms of
+that code without the copy of the GNU GPL normally required by
+section 4, provided you include this license notice and a URL
+through which recipients can access the Corresponding Source.
+
+
+@licend  The above is the entire license notice
+for the JavaScript code in this tag.
+*/
+<!--/*--><![CDATA[/*><!--*/
+ function CodeHighlightOn(elem, id)
+ {
+   var target = document.getElementById(id);
+   if(null != target) {
+     elem.cacheClassElem = elem.className;
+     elem.cacheClassTarget = target.className;
+     target.className = "code-highlighted";
+     elem.className   = "code-highlighted";
+   }
+ }
+ function CodeHighlightOff(elem, id)
+ {
+   var target = document.getElementById(id);
+   if(elem.cacheClassElem)
+     elem.className = elem.cacheClassElem;
+   if(elem.cacheClassTarget)
+     target.className = elem.cacheClassTarget;
+ }
+/*]]>*///-->
+</script>
+</head>
+<body>
+<div id="content">
+<h1 class="title">Distributed experiments on Grid'5000 &#x2026; and beyond !</h1>
+<div id="table-of-contents">
+<h2>Table of Contents</h2>
+<div id="text-table-of-contents">
+<ul>
+<li><a href="#orgb1aa660">1. Foreword</a>
+<ul>
+<li><a href="#org33af631">1.1. Existing tools (Grid'5000)</a></li>
+<li><a href="#org769cfcb">1.2. EnOSlib quicktour</a></li>
+<li><a href="#org4a53df5">1.3. Contributing</a></li>
+</ul>
+</li>
+<li><a href="#orgc7e91b9">2. Before you start</a></li>
+<li><a href="#org782c78a">3. Setup on Grid'5000</a></li>
+<li><a href="#org441c9dd">4. Your first experiment on Grid'5000</a>
+<ul>
+<li><a href="#orgf5c5450">4.1. First iteration</a></li>
+<li><a href="#org993bcaf">4.2. Let's observe in real-time what is happening</a></li>
+<li><a href="#org830e31f">4.3. Discussion</a></li>
+<li><a href="#org5f35d8c">4.4. A bit better approach</a></li>
+<li><a href="#orgdddf696">4.5. Ninja level</a></li>
+<li><a href="#org1193557">4.6. Some references</a></li>
+</ul>
+</li>
+<li><a href="#orgf965b96">5. Providers: to replicate your experiment</a>
+<ul>
+<li><a href="#orgad471c7">5.1. iperf3 on virtual machines on Grid'5000</a></li>
+<li><a href="#org08faf88">5.2. References</a></li>
+</ul>
+</li>
+<li><a href="#org56f9c08">6. Variables in EnOSlib</a>
+<ul>
+<li><a href="#org2281689">6.1. Discover the <code>run</code> command and its variants</a></li>
+<li><a href="#orgd2c7291">6.2. Advanced usages</a></li>
+<li><a href="#orgd78a6d8">6.3. Ninja level</a></li>
+<li><a href="#orge739be4">6.4. Putting all together</a></li>
+<li><a href="#org5dafa08">6.5. Some references</a></li>
+</ul>
+</li>
+<li><a href="#orga167566">7. Modules: for safer remote actions</a>
+<ul>
+<li><a href="#orgc30170a">7.1. Idempotency</a></li>
+<li><a href="#org334a244">7.2. One reason why idempotency is important</a></li>
+<li><a href="#orgcf77118">7.3. Idempotency trick</a></li>
+<li><a href="#orgcaa5aa0">7.4. General idempotency</a></li>
+</ul>
+</li>
+<li><a href="#orgb39fe8f">8. Tasks: to organize your experiment</a></li>
+</ul>
+</div>
+</div>
+
+<div id="outline-container-orgb1aa660" class="outline-2">
+<h2 id="orgb1aa660"><span class="section-number-2">1</span> Foreword</h2>
+<div class="outline-text-2" id="text-1">
+</div>
+<div id="outline-container-org33af631" class="outline-3">
+<h3 id="org33af631"><span class="section-number-3">1.1</span> Existing tools (Grid'5000)</h3>
+<div class="outline-text-3" id="text-1-1">
+<ul class="org-ul">
+<li>EnOSlib falls under the <b><b>Experiment management tools</b></b> of the following
+list:
+<a href="https://www.grid5000.fr/w/Grid5000:Software">https://www.grid5000.fr/w/Grid5000:Software</a></li>
+
+<li>EnOSlib can target Grid'5000 but also other testbeds (Chameleon, local machines&#x2026;)</li>
+
+<li>EnOSlib provides high level constructs to help you with your experiments</li>
+</ul>
+</div>
+</div>
+
+<div id="outline-container-org769cfcb" class="outline-3">
+<h3 id="org769cfcb"><span class="section-number-3">1.2</span> EnOSlib quicktour</h3>
+<div class="outline-text-3" id="text-1-2">
+<ul class="org-ul">
+<li>Documentation: <a href="https://discovery.gitlabpages.inria.fr/enoslib/index.html">https://discovery.gitlabpages.inria.fr/enoslib/index.html</a></li>
+<li>Source:  <a href="https://gitlab.inria.fr/discovery/enoslib">https://gitlab.inria.fr/discovery/enoslib</a></li>
+<li>Reach us on:
+<ul class="org-ul">
+<li><a href="https://framateam.org/enoslib">https://framateam.org/enoslib</a></li>
+<li><a href="https://gitlab.inria.fr/discovery/enoslib/issues">https://gitlab.inria.fr/discovery/enoslib/issues</a></li>
+</ul></li>
+</ul>
+</div>
+</div>
+
+<div id="outline-container-org4a53df5" class="outline-3">
+<h3 id="org4a53df5"><span class="section-number-3">1.3</span> Contributing</h3>
+<div class="outline-text-3" id="text-1-3">
+<p>
+<b>Before experimenting</b>
+</p>
+
+<ul class="org-ul">
+<li>Tell us what your plans are:
+<ul class="org-ul">
+<li>There might be already users doing similar thing</li>
+<li>There might be some missing/hidden pieces in the library you might need</li>
+</ul></li>
+</ul>
+
+<p>
+<b>While experimenting</b>
+</p>
+
+<ul class="org-ul">
+<li>Write bug reports / ask questions</li>
+<li>Fix bugs / add your features</li>
+</ul>
+
+<p>
+<b>After experimenting</b>
+</p>
+
+<ul class="org-ul">
+<li>Give your feedback</li>
+<li>Add yourself to the list: <a href="https://discovery.gitlabpages.inria.fr/enoslib/theyuseit.html">https://discovery.gitlabpages.inria.fr/enoslib/theyuseit.html</a></li>
+</ul>
+</div>
+</div>
+</div>
+
+
+<div id="outline-container-orgc7e91b9" class="outline-2">
+<h2 id="orgc7e91b9"><span class="section-number-2">2</span> Before you start</h2>
+<div class="outline-text-2" id="text-2">
+<div class="note">
+<p>
+make sure you are familiar with the grid'5000 architecture. see section 1 &amp; 2 of
+<a href="https://www.grid5000.fr/w/Getting_Started">https://www.grid5000.fr/w/Getting_Started</a>. note that we won't do this tutorial
+we'll prefer to use higher level tools for now.
+</p>
+
+</div>
+</div>
+</div>
+
+<div id="outline-container-org782c78a" class="outline-2">
+<h2 id="org782c78a"><span class="section-number-2">3</span> Setup on Grid'5000</h2>
+<div class="outline-text-2" id="text-3">
+<p>
+Connect to a Grid'5000 frontend of your choice (e.g rennes, nancy &#x2026;)
+</p>
+
+<ul class="org-ul">
+<li>create a new directory to host all the scripts of the session</li>
+<li>bootstrap a new python3 virtualenv</li>
+<li>install EnOSlib and configure the access to the API</li>
+</ul>
+
+<div class="org-src-container">
+<pre class="src src-bash">$<span style="color: #7590db;">frontend</span>: mkdir enoslib_seminar
+$<span style="color: #7590db;">frontend</span>: cd enoslib_seminar
+$<span style="color: #7590db;">frontend</span>: virtualenv --python=python3 venv
+$<span style="color: #7590db;">frontend</span>: source venv/bin/activate
+$<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: pip install enoslib
+$<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: echo <span style="color: #2d9574;">'</span>
+<span style="color: #2d9574;">verify_ssl: False</span>
+<span style="color: #2d9574;">'</span> &gt; ~/.python-grid5000.yaml
+</pre>
+</div>
+</div>
+</div>
+
+<div id="outline-container-org441c9dd" class="outline-2">
+<h2 id="org441c9dd"><span class="section-number-2">4</span> Your first experiment on Grid'5000</h2>
+<div class="outline-text-2" id="text-4">
+<p>
+Let's experiment with <a href="https://iperf.fr/">iperf3</a>: a network bandwidth measuring tool. The goal is
+to deploy a simple benchmark between two hosts. 
+</p>
+
+<p>
+We'll also instrument the deployment in order to visualize in real-time the
+network traffic between the hosts. Since this is super common, EnOSlib
+exposes a <i>monitoring service</i> that lets you deploy very quickly what is
+needed.
+</p>
+</div>
+
+<div id="outline-container-orgf5c5450" class="outline-3">
+<h3 id="orgf5c5450"><span class="section-number-3">4.1</span> First iteration</h3>
+<div class="outline-text-3" id="text-4-1">
+<p>
+We consider the following script
+</p>
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.api <span style="color: #4f97d7; font-weight: bold;">import</span> run_command, wait_ssh
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.provider <span style="color: #4f97d7; font-weight: bold;">import</span> G5k
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.configuration <span style="color: #4f97d7; font-weight: bold;">import</span> Configuration, NetworkConfiguration
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.service <span style="color: #4f97d7; font-weight: bold;">import</span> Monitoring
+
+<span style="color: #4f97d7; font-weight: bold;">import</span> logging
+
+
+<span style="color: #4f97d7; font-weight: bold;">def</span> <span style="color: #bc6ec5; font-weight: bold;">pprint</span><span style="color: #4f97d7;">(</span>d<span style="color: #4f97d7;">)</span>:
+    <span style="color: #2aa1ae;">"""Utils fonction to pretty print the results"""</span>
+    <span style="color: #4f97d7; font-weight: bold;">for</span> k, v <span style="color: #4f97d7; font-weight: bold;">in</span> d<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"ok"</span><span style="color: #4f97d7;">]</span>.items<span style="color: #4f97d7;">()</span>:
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"Result for {k}"</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"-"</span> * <span style="color: #a45bad;">70</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDOUT:"</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stdout"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDERR:"</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stderr"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
+
+
+logging.basicConfig<span style="color: #4f97d7;">(</span>level=logging.INFO<span style="color: #4f97d7;">)</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Some parameters.</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 1: that you don't need to be on rennes frontend to use nodes</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">from rennes</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 2: Adapt the site/cluster according to the availibility</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">see the Gantt in https://www.grid5000.fr/w/Status</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #7590db;">SITE</span> = <span style="color: #2d9574;">"rennes"</span>
+<span style="color: #7590db;">CLUSTER</span> = <span style="color: #2d9574;">"paravance"</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Configuration object describes the resource we want</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">here: 2 machines on the same cluster using the production network</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #7590db;">network</span> = NetworkConfiguration<span style="color: #4f97d7;">(</span><span style="color: #4f97d7;">id</span>=<span style="color: #2d9574;">"n1"</span>,
+                               <span style="color: #4f97d7;">type</span>=<span style="color: #2d9574;">"prod"</span>,
+                               roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"my_network"</span><span style="color: #bc6ec5;">]</span>,
+                               site=SITE<span style="color: #4f97d7;">)</span>
+
+<span style="color: #7590db;">conf</span> = Configuration.from_settings<span style="color: #4f97d7;">(</span>job_name=<span style="color: #2d9574;">"enoslib_tutorial"</span>,
+                                   job_type=<span style="color: #2d9574;">"allow_classic_ssh"</span><span style="color: #4f97d7;">)</span>\
+    .add_network_conf<span style="color: #4f97d7;">(</span>network<span style="color: #4f97d7;">)</span>\
+    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
+                 cluster=CLUSTER,
+                 nodes=<span style="color: #a45bad;">1</span>,
+                 primary_network=network<span style="color: #4f97d7;">)</span>\
+    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
+                 cluster=CLUSTER,
+                 nodes=<span style="color: #a45bad;">1</span>,
+                 primary_network=network<span style="color: #4f97d7;">)</span>\
+    .finalize<span style="color: #4f97d7;">()</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Reserve the ressources corresponding to the configuration</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">you'll get two **physical machine** (not virtual)</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">the roles object is a dictionnary of the concrete compute resources</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">roles = {"server": [host1], "client": [host2] }</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #7590db;">provider</span> = G5k<span style="color: #4f97d7;">(</span>conf<span style="color: #4f97d7;">)</span>
+<span style="color: #7590db;">roles</span>, <span style="color: #7590db;">networks</span> =  provider.init<span style="color: #4f97d7;">()</span>
+wait_ssh<span style="color: #4f97d7;">(</span>roles<span style="color: #4f97d7;">)</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Below is the experimentation logic</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- It installs the bare minimum to run iperf3</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'server' is used to run a iperf3 server</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">started in the background (using tmux)</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'client' connects to that server and initiate a</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">transfer for 30s (duration variable)</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- Report is printed in stdout</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
+<span style="color: #7590db;">duration</span> = <span style="color: #a45bad;">30</span>
+run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"apt update &amp;&amp; apt install -y iperf3 tmux"</span>, roles=roles<span style="color: #4f97d7;">)</span>
+run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"tmux new-session -d 'exec iperf3 -s'"</span>, pattern_hosts=<span style="color: #2d9574;">"server"</span>, roles=roles<span style="color: #4f97d7;">)</span>
+<span style="color: #7590db;">result</span> = run_command<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t {duration}"</span>, pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span>
+pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Destroy the reservation, uncomment when needed</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">provider.destroy()</span>
+</pre>
+</div>
+
+<div class="question">
+<p>
+How fast is the network between the nodes you have chosen ?
+</p>
+
+</div>
+
+<div class="note">
+<p>
+Before moving to the next questions, you'll need to clean the reservation.
+You can either uncomment the line <code>provider.destroy()</code> at the end of the script.
+You can also do it manually using the low-level <code>oarstat</code> / <code>oardel</code> tools.
+</p>
+
+<div class="org-src-container">
+<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">get you reservation id</span>
+$<span style="color: #7590db;">frontend</span>: oarstat -u
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">release the resources / kill the reservation</span>
+$<span style="color: #7590db;">frontend</span>: oardel &lt;the id of the reservation goes here&gt;
+</pre>
+</div>
+
+</div>
+
+<div class="question">
+<p>
+Can you adapt the script so that:
+</p>
+<ol class="org-ol">
+<li>The two nodes are in two different cluster in the same site ?</li>
+<li>The two nodes are in two different sites ?</li>
+</ol>
+
+</div>
+</div>
+</div>
+
+
+<div id="outline-container-org993bcaf" class="outline-3">
+<h3 id="org993bcaf"><span class="section-number-3">4.2</span> Let's observe in real-time what is happening</h3>
+<div class="outline-text-3" id="text-4-2">
+<div class="note">
+<p>
+Make sure you have cleaned your previous reservations.
+</p>
+
+</div>
+
+<p>
+The following script installs a monitoring stack on your nodes. This is almost
+the same script as before except the lines corresponding to the configuration
+of the monitoring stack.
+</p>
+
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.api <span style="color: #4f97d7; font-weight: bold;">import</span> run_command, wait_ssh
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.provider <span style="color: #4f97d7; font-weight: bold;">import</span> G5k
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_g5k.configuration <span style="color: #4f97d7; font-weight: bold;">import</span> Configuration, NetworkConfiguration
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.service <span style="color: #4f97d7; font-weight: bold;">import</span> Monitoring
+
+<span style="color: #4f97d7; font-weight: bold;">import</span> logging
+
+
+<span style="color: #4f97d7; font-weight: bold;">def</span> <span style="color: #bc6ec5; font-weight: bold;">pprint</span><span style="color: #4f97d7;">(</span>d<span style="color: #4f97d7;">)</span>:
+    <span style="color: #2aa1ae;">"""Utils fonction to pretty print the results"""</span>
+    <span style="color: #4f97d7; font-weight: bold;">for</span> k, v <span style="color: #4f97d7; font-weight: bold;">in</span> d<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"ok"</span><span style="color: #4f97d7;">]</span>.items<span style="color: #4f97d7;">()</span>:
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"Result for {k}"</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"-"</span> * <span style="color: #a45bad;">70</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDOUT:"</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stdout"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"STDERR:"</span><span style="color: #4f97d7;">)</span>
+        <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>v.get<span style="color: #bc6ec5;">(</span><span style="color: #2d9574;">"stderr"</span>, <span style="color: #2d9574;">""</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
+
+
+logging.basicConfig<span style="color: #4f97d7;">(</span>level=logging.INFO<span style="color: #4f97d7;">)</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Some parameters.</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 1: that you don't need to be on rennes frontend to use nodes</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">from rennes</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Note 2: Adapt the site/cluster according to the availibility</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##         </span><span style="color: #2aa1ae; background-color: #292e34;">see the Gantt in https://www.grid5000.fr/w/Status</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #7590db;">SITE</span> = <span style="color: #2d9574;">"rennes"</span>
+<span style="color: #7590db;">CLUSTER</span> = <span style="color: #2d9574;">"paravance"</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Configuration object describes the resource we want</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">here: 2 machines on the same cluster using the production network</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #7590db;">network</span> = NetworkConfiguration<span style="color: #4f97d7;">(</span><span style="color: #4f97d7;">id</span>=<span style="color: #2d9574;">"n1"</span>,
+                               <span style="color: #4f97d7;">type</span>=<span style="color: #2d9574;">"prod"</span>,
+                               roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"my_network"</span><span style="color: #bc6ec5;">]</span>,
+                               site=SITE<span style="color: #4f97d7;">)</span>
+
+<span style="color: #7590db;">conf</span> = Configuration.from_settings<span style="color: #4f97d7;">(</span>job_name=<span style="color: #2d9574;">"enoslib_tutorial"</span>,
+                                   job_type=<span style="color: #2d9574;">"allow_classic_ssh"</span><span style="color: #4f97d7;">)</span>\
+    .add_network_conf<span style="color: #4f97d7;">(</span>network<span style="color: #4f97d7;">)</span>\
+    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
+                 cluster=CLUSTER,
+                 nodes=<span style="color: #a45bad;">1</span>,
+                 primary_network=network<span style="color: #4f97d7;">)</span>\
+    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
+                 cluster=CLUSTER,
+                 nodes=<span style="color: #a45bad;">1</span>,
+                 primary_network=network<span style="color: #4f97d7;">)</span>\
+    .finalize<span style="color: #4f97d7;">()</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Reserve the ressources corresponding to the configuration</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">you'll get two **physical machine** (not virtual)</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">the roles object is a dictionnary of the concrete compute resources</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">roles = {"server": [host1], "client": [host2] }</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #7590db;">provider</span> = G5k<span style="color: #4f97d7;">(</span>conf<span style="color: #4f97d7;">)</span>
+<span style="color: #7590db;">roles</span>, <span style="color: #7590db;">networks</span> =  provider.init<span style="color: #4f97d7;">()</span>
+wait_ssh<span style="color: #4f97d7;">(</span>roles<span style="color: #4f97d7;">)</span>
+
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">This deploys a monitoring stack. It is composed of</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">- some agents on each monitored nodes</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">- one collector that collects the metrics from the agents</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">- one UI to visualize</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #7590db;">m</span> = Monitoring<span style="color: #4f97d7;">(</span>collector=roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
+               agent=roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span> + roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
+               ui=roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span><span style="color: #4f97d7;">)</span>
+m.deploy<span style="color: #4f97d7;">()</span>
+
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Below is the experimentation logic</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- It installs the bare minimum to run iperf3</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'server' is used to run a iperf3 server</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">started in the background (using tmux)</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- The machine with the role 'client' connects to that server and initiate a</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##    </span><span style="color: #2aa1ae; background-color: #292e34;">transfer for 600s (duration variable)</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##  </span><span style="color: #2aa1ae; background-color: #292e34;">- Report is printed in stdout</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
+<span style="color: #7590db;">duration</span> = <span style="color: #a45bad;">600</span>
+run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"apt update &amp;&amp; apt install -y iperf3 tmux"</span>, roles=roles<span style="color: #4f97d7;">)</span>
+run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"tmux new-session -d 'exec iperf3 -s'"</span>, pattern_hosts=<span style="color: #2d9574;">"server"</span>, roles=roles<span style="color: #4f97d7;">)</span>
+<span style="color: #7590db;">result</span> = run_command<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t {duration}"</span>, pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span>
+pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">## </span><span style="color: #2aa1ae; background-color: #292e34;">Destroy the reservation, uncomment when needed</span>
+<span style="color: #2aa1ae; background-color: #292e34;">##</span>
+<span style="color: #2aa1ae; background-color: #292e34;">######################################################################</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">provider.destroy()</span>
+</pre>
+</div>
+
+<p>
+Now, let's visualize the network traffic in real-time !
+</p>
+<div class="note">
+<p>
+Usually I follow this to access services running inside Grid'5000:
+<a href="https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html#accessing-http-services-inside-grid-5000">https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html#accessing-http-services-inside-grid-5000</a>.
+</p>
+
+
+<p>
+Today you can just create a tunnel like this (from your local machine).
+</p>
+
+<div class="org-src-container">
+<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Adapt the node names with the node where grafana (the UI) has been installed</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Replace &lt;login&gt; by your Grid'5000 login</span>
+$<span style="color: #7590db;">yourmachine</span>: ssh -NL <span style="color: #a45bad;">3000:paravance-16.rennes.grid5000.fr:3000</span> &lt;login&gt;@access.grid5000.fr
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">point your browser to localhost:3000</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">username/mdp: admin/admin</span>
+</pre>
+</div>
+
+</div>
+
+<p>
+Part of the experimenter work also consists in analysing the data. Here it
+corresponds in writing the right request to monitor the traffic (check the
+Fig. <a href="#orga4a34ec">1</a>). You should be able to visualize such a thing (after a bit
+of point and clicks).
+</p>
+
+
+<div id="orga4a34ec" class="figure">
+<p><a href="figs/iperf3.png" width="100%" style="border:1px solid black;"><img src="figs/iperf3.png" alt="iperf3.png" width="100%" style="border:1px solid black;" /></a>
+</p>
+<p><span class="figure-number">Figure 1: </span>iperf3 / monitoring</p>
+</div>
+</div>
+</div>
+
+
+<div id="outline-container-org830e31f" class="outline-3">
+<h3 id="org830e31f"><span class="section-number-3">4.3</span> Discussion</h3>
+<div class="outline-text-3" id="text-4-3">
+<p>
+So, far this seems (at least for me) very handy. But there might be some problems in our setup:
+</p>
+<ul class="org-ul">
+<li>we aren't isolated from the other users</li>
+<li>we aren't isolated from ourself in the sense that the monitoring stack generates its own 
+network traffic (yes, this is negligible in our case)</li>
+</ul>
+
+<p>
+Sometimes it's desirable to have the following setup (see Fig. <a href="#orgf90cb97">2</a>).
+</p>
+
+
+<div id="orgf90cb97" class="figure">
+<p><a href="figs/skydive_enoslib.png"><img src="figs/skydive_enoslib.png" alt="skydive_enoslib.png" /></a>
+</p>
+<p><span class="figure-number">Figure 2: </span>nodes are using two network interfaces. Monitoring traffic and benchmark traffic are separated.</p>
+</div>
+</div>
+</div>
+
+<div id="outline-container-org5f35d8c" class="outline-3">
+<h3 id="org5f35d8c"><span class="section-number-3">4.4</span> A bit better approach</h3>
+<div class="outline-text-3" id="text-4-4">
+<p>
+Analyse/Understand the following script <a href="exercices/iperf3_better.py">exercices/iperf3_better.py</a>
+Launch it.
+</p>
+
+<div class="note">
+<p>
+On Grid'5000, using the secondary interfaces requires to <b>deploy</b> the nodes:
+an new OS will be installed on your nodes. This will give you full control on
+the physical machine (root access). This might be longer to run the
+experiment due to this deployment phase.
+</p>
+
+</div>
+</div>
+</div>
+
+<div id="outline-container-orgdddf696" class="outline-3">
+<h3 id="orgdddf696"><span class="section-number-3">4.5</span> Ninja level</h3>
+<div class="outline-text-3" id="text-4-5">
+<p>
+Add the <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html#skydive">Skydive</a> service to your deployment. 
+It should be accessible on the port <code>8082</code> of the analyzer node. You should
+get something like Fig. <a href="#orgf90cb97">2</a>.
+</p>
+</div>
+</div>
+
+<div id="outline-container-org1193557" class="outline-3">
+<h3 id="org1193557"><span class="section-number-3">4.6</span> Some references</h3>
+<div class="outline-text-3" id="text-4-6">
+<ul class="org-ul">
+<li>Services: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html</a></li>
+</ul>
+</div>
+</div>
+</div>
+
+<div id="outline-container-orgf965b96" class="outline-2">
+<h2 id="orgf965b96"><span class="section-number-2">5</span> Providers: to replicate your experiment</h2>
+<div class="outline-text-2" id="text-5">
+<div class="note">
+<p>
+The resources that are used for your experiment are acquired through a
+provider. Providers are a mean to decouple the infrastructure code (the code
+that gets the resources) from the code that runs the experiment. Changing the
+provider allows to replicate the experiment on another testbed.
+</p>
+
+</div>
+
+<p>
+Originally it was used to iterate on the code locally (using the Vagrant
+provider) and to only test on Grid'5000 when necessary.
+</p>
+
+<p>
+We now have couple of providers that you may picked or mixed.
+</p>
+</div>
+
+<div id="outline-container-orgad471c7" class="outline-3">
+<h3 id="orgad471c7"><span class="section-number-3">5.1</span> iperf3 on virtual machines on Grid'5000</h3>
+<div class="outline-text-3" id="text-5-1">
+<p>
+We'll adapt the initial iperf3 example to use virtual machines instead of
+bare-metal machine. 
+</p>
+
+<p>
+Note that:
+</p>
+
+<ul class="org-ul">
+<li>The configuration object is different</li>
+<li>The experimentation logic is the same</li>
+<li>Some part have been rewritten using modules (see later in the dedicated section).</li>
+</ul>
+
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.api <span style="color: #4f97d7; font-weight: bold;">import</span> play_on, wait_ssh
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_vmong5k.provider <span style="color: #4f97d7; font-weight: bold;">import</span> VMonG5k
+<span style="color: #4f97d7; font-weight: bold;">from</span> enoslib.infra.enos_vmong5k.configuration <span style="color: #4f97d7; font-weight: bold;">import</span> Configuration
+
+<span style="color: #4f97d7; font-weight: bold;">import</span> logging
+<span style="color: #4f97d7; font-weight: bold;">import</span> os
+
+logging.basicConfig<span style="color: #4f97d7;">(</span>level=logging.DEBUG<span style="color: #4f97d7;">)</span>
+
+<span style="color: #7590db;">CLUSTER</span> = <span style="color: #2d9574;">"paravance"</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">path to the inventory</span>
+<span style="color: #7590db;">inventory</span> = os.path.join<span style="color: #4f97d7;">(</span>os.getcwd<span style="color: #bc6ec5;">()</span>, <span style="color: #2d9574;">"hosts"</span><span style="color: #4f97d7;">)</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">claim the resources</span>
+<span style="color: #7590db;">conf</span> = Configuration.from_settings<span style="color: #4f97d7;">(</span>job_name=<span style="color: #2d9574;">"enoslib_tutorial"</span>, gateway=<span style="color: #a45bad;">True</span><span style="color: #4f97d7;">)</span>\
+                    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #bc6ec5;">]</span>,
+                                 cluster=CLUSTER,
+                                 number=<span style="color: #a45bad;">1</span>,
+                                 flavour=<span style="color: #2d9574;">"large"</span><span style="color: #4f97d7;">)</span>\
+                    .add_machine<span style="color: #4f97d7;">(</span>roles=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>,
+                                 cluster=CLUSTER,
+                                 number=<span style="color: #a45bad;">1</span>,
+                                 flavour=<span style="color: #2d9574;">"medium"</span><span style="color: #4f97d7;">)</span>\
+                    .finalize<span style="color: #4f97d7;">()</span>
+
+<span style="color: #7590db;">provider</span> = VMonG5k<span style="color: #4f97d7;">(</span>conf<span style="color: #4f97d7;">)</span>
+
+<span style="color: #7590db;">roles</span>, <span style="color: #7590db;">networks</span> = provider.init<span style="color: #4f97d7;">()</span>
+wait_ssh<span style="color: #4f97d7;">(</span>roles<span style="color: #4f97d7;">)</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Below is the experimentation logic</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">It installs the bare minimum to run iperf3</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">The machine with the role 'server' is used to run a iperf3 server</span>
+<span style="color: #2aa1ae; background-color: #292e34;">#     </span><span style="color: #2aa1ae; background-color: #292e34;">started in the background in a tmux</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">The machine with the role 'client' connects to that server</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Report is printed in stdout</span>
+<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
+
+<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
+    p.apt<span style="color: #4f97d7;">(</span>name=<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"iperf3"</span>, <span style="color: #2d9574;">"tmux"</span><span style="color: #bc6ec5;">]</span>, state=<span style="color: #2d9574;">"present"</span><span style="color: #4f97d7;">)</span>
+
+<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>pattern_hosts=<span style="color: #2d9574;">"server"</span>, roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
+    p.shell<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"tmux new-session -d 'exec iperf3 -s'"</span><span style="color: #4f97d7;">)</span>
+
+<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
+    p.shell<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t 30"</span><span style="color: #4f97d7;">)</span>
+
+<span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>pattern_hosts=<span style="color: #2d9574;">"client"</span>, roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
+    p.shell<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"iperf3 -c {server.address} -t 30 --logfile iperf3.out"</span><span style="color: #4f97d7;">)</span>
+    p.fetch<span style="color: #4f97d7;">(</span>src=<span style="color: #2d9574;">"iperf3.out"</span>, dest=<span style="color: #2d9574;">"iperf3.out"</span><span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<p>
+Using module using the <code>play_on</code> context manager does not bring back the
+results of the commands. Iperf3 let's you write the result of the command on
+a file. We just need to scp the file back to our local machine using the
+<code>fetch</code> module.
+</p>
+</div>
+</div>
+
+
+<div id="outline-container-org08faf88" class="outline-3">
+<h3 id="org08faf88"><span class="section-number-3">5.2</span> References</h3>
+<div class="outline-text-3" id="text-5-2">
+<ul class="org-ul">
+<li>Doc: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html</a></li>
+<li>Sources: <a href="https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra">https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra</a></li>
+</ul>
+</div>
+</div>
+</div>
+
+
+<div id="outline-container-org56f9c08" class="outline-2">
+<h2 id="org56f9c08"><span class="section-number-2">6</span> Variables in EnOSlib</h2>
+<div class="outline-text-2" id="text-6">
+<p>
+Learn how to get 2 nodes from Grid'5000 and start launching remote commands.
+</p>
+</div>
+
+<div id="outline-container-org2281689" class="outline-3">
+<h3 id="org2281689"><span class="section-number-3">6.1</span> Discover the <code>run</code> command and its variants</h3>
+<div class="outline-text-3" id="text-6-1">
+<p>
+Before proceeding you can add this util function to your code. It is only
+used to pretty print a python dictionnary.
+</p>
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">def</span> <span style="color: #bc6ec5; font-weight: bold;">pprint</span><span style="color: #4f97d7;">(</span>d<span style="color: #4f97d7;">)</span>:
+    <span style="color: #4f97d7; font-weight: bold;">import</span> json
+    <span style="color: #4f97d7; font-weight: bold;">print</span><span style="color: #4f97d7;">(</span>json.dumps<span style="color: #bc6ec5;">(</span>d, indent=<span style="color: #a45bad;">4</span><span style="color: #bc6ec5;">)</span><span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<p>
+And use the <code>enoslib.api.run</code> function 
+</p>
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Using run</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
+<span style="color: #7590db;">result</span> = run<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"ping -c 5 {server.address}"</span>, roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span><span style="color: #4f97d7;">)</span>
+pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<p>
+Or the <code>enoslib.api.run_command</code> function
+</p>
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Using run_command 1/2</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
+<span style="color: #7590db;">result</span> = run_command<span style="color: #4f97d7;">(</span>f<span style="color: #2d9574;">"ping -c 5 {server.address}"</span>,
+                     pattern_hosts=<span style="color: #2d9574;">"client"</span>,
+                     roles=roles<span style="color: #4f97d7;">)</span>
+pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<div class="note">
+<p>
+<code>enoslib.api.run</code> is a specialisation of <code>enoslib.api.run_command</code>. 
+The latter let's you use <a href="https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html">some fancy patterns</a> to determine the list of hosts to run the command on.
+</p>
+
+<p>
+And yes, it uses Ansible behind the scene.
+</p>
+
+</div>
+</div>
+</div>
+
+<div id="outline-container-orgd2c7291" class="outline-3">
+<h3 id="orgd2c7291"><span class="section-number-3">6.2</span> Advanced usages</h3>
+<div class="outline-text-3" id="text-6-2">
+<div class="note">
+<p>
+For all the remote interactions, EnOSlib relies on <a href="https://docs.ansible.com/ansible/latest/index.html">Ansible</a>. Ansible
+has it own variables management system.
+For instance the task <code>Gather Facts</code> at the beginning of the previous tasks
+gathers informations about all/some remote hosts and store them in the
+Ansible management system.
+</p>
+
+</div>
+
+<p>
+Let's see what Ansible is gathering about the hosts:
+</p>
+
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Gather facts</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
+<span style="color: #7590db;">result</span> = gather_facts<span style="color: #4f97d7;">(</span>roles=roles<span style="color: #4f97d7;">)</span>
+pprint<span style="color: #4f97d7;">(</span>result<span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<div class="note">
+<p>
+EnOSlib sits in between two worlds: the Python world and the Ansible
+world. One common need is to pass a variables from one world to another.
+</p>
+<ul class="org-ul">
+<li><code>enoslib.api.gather_facts</code> is a way to get, in Python, the variables known
+by Ansible about each host.</li>
+<li><code>extra_vars</code> keyword argument of <code>enoslib.api.run</code> or <code>enoslib.api.run_command</code> will 
+pass variables from Python world to Ansible world (global variable)</li>
+<li>Injecting a key/value in a <code>Host.extra</code> attribute will make the variable <code>key</code> available to Ansible.
+This makes the variables Host specific.</li>
+</ul>
+
+</div>
+
+<p>
+The following inject a global variable in the Ansible world
+</p>
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Passing a variable to the Ansible World using a global level variable</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
+<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
+<span style="color: #7590db;">extra_vars</span>=<span style="color: #4f97d7;">{</span><span style="color: #2d9574;">"server_ip"</span>: server.address<span style="color: #4f97d7;">}</span>
+<span style="color: #7590db;">result</span> = run<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"ping -c 5 {{ server_ip }}"</span>, roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span>, extra_vars=extra_vars<span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+</div>
+</div>
+
+<div id="outline-container-orgd78a6d8" class="outline-3">
+<h3 id="orgd78a6d8"><span class="section-number-3">6.3</span> Ninja level</h3>
+<div class="outline-text-3" id="text-6-3">
+<p>
+The following is valid and inject in the <code>client</code> host a specific variable to
+keep track of the server IP.
+</p>
+
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">---</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Passing a variable to the Ansible World using a host level variable</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">--------------------------------------------------------------------</span>
+<span style="color: #7590db;">server</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"server"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
+<span style="color: #7590db;">client</span> = roles<span style="color: #4f97d7;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #4f97d7;">][</span><span style="color: #a45bad;">0</span><span style="color: #4f97d7;">]</span>
+client.extra.update<span style="color: #4f97d7;">(</span>server_ip=server.address<span style="color: #4f97d7;">)</span>
+<span style="color: #7590db;">result</span> = run<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"ping -c 5 {{ server_ip }}"</span>, roles<span style="color: #bc6ec5;">[</span><span style="color: #2d9574;">"client"</span><span style="color: #bc6ec5;">]</span><span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<div class="note">
+<p>
+Host level variables are interesting to introduce some dissymetry between
+hosts while still using one single command to reach all of them.
+</p>
+
+</div>
+
+<div class="question">
+<p>
+How to perform simultaneously the ping to the other machine in calling only
+once <code>run</code> or <code>run_command</code> and using host level variables?
+</p>
+
+</div>
+
+<div class="question">
+<p>
+We'd like to create 5 <code>server</code> machines and 5 <code>client</code> machines and start 5
+<b>parallel</b> streams of data using <code>iperf3</code>. To answer this we'll need to learn
+a bit more on how variables are handled in EnOSlib.
+</p>
+
+</div>
+</div>
+</div>
+
+<div id="outline-container-orge739be4" class="outline-3">
+<h3 id="orge739be4"><span class="section-number-3">6.4</span> Putting all together</h3>
+<div class="outline-text-3" id="text-6-4">
+<p>
+Access the full file: <a href="exercices/run.py">exercices/run.py</a>
+</p>
+</div>
+</div>
+
+<div id="outline-container-org5dafa08" class="outline-3">
+<h3 id="org5dafa08"><span class="section-number-3">6.5</span> Some references</h3>
+<div class="outline-text-3" id="text-6-5">
+<ul class="org-ul">
+<li>G5k configuration schema: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html#g5k-schema">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html#g5k-schema</a></li>
+<li>API Reference: <a href="https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html">https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html</a></li>
+</ul>
+</div>
+</div>
+</div>
+
+<div id="outline-container-orga167566" class="outline-2">
+<h2 id="orga167566"><span class="section-number-2">7</span> Modules: for safer remote actions</h2>
+<div class="outline-text-2" id="text-7">
+<p>
+In this section we'll discover the idiomatic way of managing resources on the
+remote hosts. A resource can be anything: a user, a file, a line in a file, a
+repo on Gitlab, a firewall rule &#x2026;
+</p>
+</div>
+
+
+<div id="outline-container-orgc30170a" class="outline-3">
+<h3 id="orgc30170a"><span class="section-number-3">7.1</span> Idempotency</h3>
+<div class="outline-text-3" id="text-7-1">
+<p>
+Let's assume you want to create a user (<code>foo</code>). With the <code>run_command</code> this would look like:
+</p>
+
+<div class="org-src-container">
+<pre class="src src-python">run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"useradd -m foo"</span>, roles=role<span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<p>
+The main issue with this code is that it is not <b>idempotent</b>. Running it once
+will applied the effect (create the user). But, as soon as the user exist in
+the system, this will raise an error.
+</p>
+</div>
+</div>
+
+<div id="outline-container-org334a244" class="outline-3">
+<h3 id="org334a244"><span class="section-number-3">7.2</span> One reason why idempotency is important</h3>
+<div class="outline-text-3" id="text-7-2">
+<p>
+Let's consider the following snippet (mispelling the second command is intentional)
+</p>
+<div class="org-src-container">
+<pre class="src src-python">run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"useradd -m foo"</span>, roles=role<span style="color: #4f97d7;">)</span>
+run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"mkdirz plop"</span><span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+<p>
+Executing the above leads the system with the user <code>foo</code> created but the the
+directory <code>plop</code> not created since the second command fails.
+</p>
+
+<p>
+So what you want to do is to fix the second command and re-run the snippet again.
+But, you can't do that because <code>useradd</code> isn't idempotent.
+</p>
+</div>
+</div>
+
+<div id="outline-container-orgcf77118" class="outline-3">
+<h3 id="orgcf77118"><span class="section-number-3">7.3</span> Idempotency trick</h3>
+<div class="outline-text-3" id="text-7-3">
+<p>
+One easy solution is to protect your call to non idempotent commands with
+some ad'hoc tricks
+</p>
+
+<p>
+Here it can look like this:
+</p>
+
+<div class="org-src-container">
+<pre class="src src-python">run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"id foo || useradd -m foo"</span>, roles=role<span style="color: #4f97d7;">)</span>
+run_command<span style="color: #4f97d7;">(</span><span style="color: #2d9574;">"mkdir -p plop"</span><span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<p>
+<b>What's wrong with that</b>
+</p>
+
+<ul class="org-ul">
+<li>The trick depends on the command</li>
+<li>Re-reading the code is more complex: the code focus on the <b><b>how</b></b> not the <b><b>what</b></b></li>
+</ul>
+</div>
+</div>
+
+<div id="outline-container-orgcaa5aa0" class="outline-3">
+<h3 id="orgcaa5aa0"><span class="section-number-3">7.4</span> General idempotency</h3>
+<div class="outline-text-3" id="text-7-4">
+<p>
+The idiomatic solution is to use modules (inherited from the Ansible
+Modules). The modules are specified in a <b>declarative</b> way and they ensure
+<b>idempotency</b> for most of them.
+</p>
+
+<p>
+So rewriting the example with modules looks like:
+</p>
+<div class="org-src-container">
+<pre class="src src-python"><span style="color: #4f97d7; font-weight: bold;">with</span> play_on<span style="color: #4f97d7;">(</span>roles=roles<span style="color: #4f97d7;">)</span> <span style="color: #4f97d7; font-weight: bold;">as</span> p:
+    p.user<span style="color: #4f97d7;">(</span>name=<span style="color: #2d9574;">"foo"</span>, state=<span style="color: #2d9574;">"present"</span>, create_home=<span style="color: #2d9574;">"yes"</span><span style="color: #4f97d7;">)</span>
+    p.<span style="color: #4f97d7;">file</span><span style="color: #4f97d7;">(</span>name=<span style="color: #2d9574;">"plop"</span>, state=<span style="color: #2d9574;">"directory"</span><span style="color: #4f97d7;">)</span>
+</pre>
+</div>
+
+<p>
+<code>enoslib.api.play_on</code> is the entry point to the module system.
+</p>
+
+<p>
+You can run this code as many times as you want without any error. You'll
+eventually find one user <code>foo</code> and one directory <code>plop</code> in your target
+systems.
+</p>
+
+<p>
+They are more than 2500 modules: <a href="https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html">https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html</a>
+</p>
+
+<p>
+If you can't find what you want you must know that:
+</p>
+<ul class="org-ul">
+<li>Writing your own module is possible</li>
+<li>Falling back to the idempotency trick is reasonable</li>
+</ul>
+</div>
+</div>
+</div>
+
+<div id="outline-container-orgb39fe8f" class="outline-2">
+<h2 id="orgb39fe8f"><span class="section-number-2">8</span> Tasks: to organize your experiment</h2>
+<div class="outline-text-2" id="text-8">
+<p>
+To discover the Task API, head to <a href="https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html">https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html</a>.
+</p>
+
+<p>
+The examples are written for Vagrant but may be changed to whatever provider you like/have.
+</p>
+
+<div class="question">
+<p>
+Adapt the <code>iperf3</code> example to provide a command line
+</p>
+<ul class="org-ul">
+<li><p>
+Either using G5k physical machines:
+</p>
+<div class="org-src-container">
+<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">deploy the dependencies of the experimentation using the G5k provider</span>
+myperf g5k
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">launch a performance measurement</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">ideally exposes all the iperf3 client options there ;)</span>
+myperf bench -t <span style="color: #a45bad;">120</span>
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Backup the reports / influxdb database</span>
+myperf backup
+</pre>
+</div>
+
+<p>
+myperf destroy
+</p></li>
+
+<li><p>
+Either using the virtual machines on Grid'5000:
+</p>
+<div class="org-src-container">
+<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">deploy the dependencies of the experimentation using the G5k provider</span>
+myperf vm5k
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Subsequent command line should be the same as above</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">enjoy :)</span>
+</pre>
+</div></li>
+</ul>
+
+</div>
+</div>
+</div>
+</div>
+<div id="postamble" class="status">
+<p class="author">Author: Matthieu Simonin</p>
+<p class="date">Created: 2019-11-15 ven. 14:14</p>
+<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
+</div>
+</body>
+</html>
diff --git a/tuto1/index.org b/tuto1/index.org
new file mode 100644
index 0000000000000000000000000000000000000000..777996da50565341ddd8ed47ba611b9e44dd874c
--- /dev/null
+++ b/tuto1/index.org
@@ -0,0 +1,428 @@
+#+TITLE: Distributed experiments on Grid'5000 ... and beyond !
+#+DATE: 
+#+AUTHOR: Matthieu Simonin
+
+#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="timeline.css" />
+
+#+MACRO: enoslib EnOSlib
+#+MACRO: src_host https://gitlab.inria.fr/discovery/enoslib/blob/v4.8.1/enoslib/host.py#L8-14
+#+MACRO: doc_external_access https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html#accessing-http-services-inside-grid-5000
+#+MACRO: src_provider https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra
+#+MACRO: doc_provider https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html
+#+MACRO: doc_tasks https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html
+#+MACRO: doc_g5k_schema https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html#g5k-schema
+#+MACRO: doc_api https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html
+#+MACRO: doc_services https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html
+
+* Foreword
+
+** Existing tools (Grid'5000)
+
+    - {{{enoslib}}} falls under the **Experiment management tools** of the following
+      list:
+      https://www.grid5000.fr/w/Grid5000:Software
+
+    - {{{enoslib}}} can target Grid'5000 but also other testbeds (Chameleon, local machines...)
+
+    - {{{enoslib}}} provides high level constructs to help you with your experiments
+
+** EnOSlib quicktour
+   
+    - Documentation: https://discovery.gitlabpages.inria.fr/enoslib/index.html 
+    - Source:  https://gitlab.inria.fr/discovery/enoslib
+    - Reach us on:
+        + https://framateam.org/enoslib
+        + https://gitlab.inria.fr/discovery/enoslib/issues
+
+** Contributing
+  
+    *Before experimenting*
+
+    - Tell us what your plans are:
+      + There might be already users doing similar thing
+      + There might be some missing/hidden pieces in the library you might need
+
+    *While experimenting*
+
+    - Write bug reports / ask questions
+    - Fix bugs / add your features
+
+    *After experimenting*
+
+    - Give your feedback
+    - Add yourself to the list: https://discovery.gitlabpages.inria.fr/enoslib/theyuseit.html
+
+
+* Before you start
+
+  #+begin_note
+  make sure you are familiar with the grid'5000 architecture. see section 1 & 2 of
+  https://www.grid5000.fr/w/Getting_Started. note that we won't do this tutorial
+  we'll prefer to use higher level tools for now.
+  #+end_note
+
+* Setup on Grid'5000
+
+  Connect to a Grid'5000 frontend of your choice (e.g rennes, nancy ...)
+
+  - create a new directory to host all the scripts of the session
+  - bootstrap a new python3 virtualenv 
+  - install {{{enoslib}}} and configure the access to the API
+
+  #+BEGIN_SRC bash :noeval
+  $frontend: mkdir enoslib_seminar
+  $frontend: cd enoslib_seminar
+  $frontend: virtualenv --python=python3 venv
+  $frontend: source venv/bin/activate
+  $frontend(venv): pip install enoslib
+  $frontend(venv): echo '
+  verify_ssl: False
+  ' > ~/.python-grid5000.yaml
+  #+END_SRC
+
+* Your first experiment on Grid'5000
+
+  Let's experiment with [[https://iperf.fr/][iperf3]]: a network bandwidth measuring tool. The goal is
+  to deploy a simple benchmark between two hosts. 
+
+  We'll also instrument the deployment in order to visualize in real-time the
+  network traffic between the hosts. Since this is super common, {{{enoslib}}}
+  exposes a /monitoring service/ that lets you deploy very quickly what is
+  needed.
+  
+** First iteration
+  
+   We consider the following script
+   #+INCLUDE: exercices/iperf3.py src python
+
+    #+BEGIN_question
+    How fast is the network between the nodes you have chosen ?
+    #+END_question
+
+    #+BEGIN_note
+    Before moving to the next questions, you'll need to clean the reservation.
+    You can either uncomment the line ~provider.destroy()~ at the end of the script.
+    You can also do it manually using the low-level ~oarstat~ / ~oardel~ tools.
+
+    #+BEGIN_SRC bash :noeval
+    # get you reservation id
+    $frontend: oarstat -u
+    # release the resources / kill the reservation
+    $frontend: oardel <the id of the reservation goes here>
+    #+END_SRC
+    #+END_note
+
+    #+BEGIN_question
+    Can you adapt the script so that:
+    1. The two nodes are in two different cluster in the same site ?
+    2. The two nodes are in two different sites ?
+    #+END_question
+
+
+**  Let's observe in real-time what is happening
+
+    #+BEGIN_note
+    Make sure you have cleaned your previous reservations.
+    #+END_note
+
+    The following script installs a monitoring stack on your nodes. This is almost
+    the same script as before except the lines corresponding to the configuration
+    of the monitoring stack.
+
+    #+INCLUDE: exercices/iperf3_monitoring.py src python
+
+    Now, let's visualize the network traffic in real-time !
+    #+BEGIN_note
+    Usually I follow this to access services running inside Grid'5000:
+    {{{doc_external_access}}}.
+
+
+    Today you can just create a tunnel like this (from your local machine).
+
+    #+BEGIN_SRC bash :noeval
+    # Adapt the node names with the node where grafana (the UI) has been installed
+    # Replace <login> by your Grid'5000 login
+    $yourmachine: ssh -NL 3000:paravance-16.rennes.grid5000.fr:3000 <login>@access.grid5000.fr
+
+    # point your browser to localhost:3000
+    # username/mdp: admin/admin
+    #+END_SRC
+
+    #+END_note
+
+    Part of the experimenter work also consists in analysing the data. Here it
+    corresponds in writing the right request to monitor the traffic (check the
+    Fig. [[fig:iperf3]]). You should be able to visualize such a thing (after a bit
+    of point and clicks).
+
+    #+CAPTION: iperf3 / monitoring
+    #+NAME:   fig:iperf3
+    #+ATTR_HTML: :width 100% :style border:1px solid black;
+    [[file:figs/iperf3.png][file:figs/iperf3.png]]
+
+
+** Discussion
+   
+   So, far this seems (at least for me) very handy. But there might be some problems in our setup:
+   - we aren't isolated from the other users
+   - we aren't isolated from ourself in the sense that the monitoring stack generates its own 
+     network traffic (yes, this is negligible in our case)
+   
+   Sometimes it's desirable to have the following setup (see Fig. [[fig:two_networks]]).
+
+    #+CAPTION: nodes are using two network interfaces.
+    #+CAPTION: Monitoring traffic and benchmark traffic are separated.
+    #+NAME:   fig:two_networks
+   [[file:figs/skydive_enoslib.png][file:figs/skydive_enoslib.png]]
+
+** A bit better approach
+
+   Analyse/Understand the following script [[file:exercices/iperf3_better.py]]
+   Launch it.
+
+   #+BEGIN_note
+   On Grid'5000, using the secondary interfaces requires to *deploy* the nodes:
+   an new OS will be installed on your nodes. This will give you full control on
+   the physical machine (root access). This might be longer to run the
+   experiment due to this deployment phase.
+   #+END_note
+
+** Ninja level
+
+   Add the [[https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html#skydive][Skydive]] service to your deployment. 
+   It should be accessible on the port ~8082~ of the analyzer node. You should
+   get something like Fig. [[fig:two_networks]].
+
+** Some references
+   
+   - Services: {{{doc_services}}}
+   
+* Providers: to replicate your experiment
+
+  #+BEGIN_note
+  The resources that are used for your experiment are acquired through a
+  provider. Providers are a mean to decouple the infrastructure code (the code
+  that gets the resources) from the code that runs the experiment. Changing the
+  provider allows to replicate the experiment on another testbed.
+  #+END_note
+
+  Originally it was used to iterate on the code locally (using the Vagrant
+  provider) and to only test on Grid'5000 when necessary.
+
+  We now have couple of providers that you may picked or mixed.
+
+** iperf3 on virtual machines on Grid'5000
+
+   We'll adapt the initial iperf3 example to use virtual machines instead of
+   bare-metal machine. 
+
+   Note that:
+   
+   - The configuration object is different
+   - The experimentation logic is the same
+   - Some part have been rewritten using modules (see later in the dedicated section).
+
+   #+INCLUDE: exercices/iperf3_vms.py src python
+
+   Using module using the ~play_on~ context manager does not bring back the
+   results of the commands. Iperf3 let's you write the result of the command on
+   a file. We just need to scp the file back to our local machine using the
+   ~fetch~ module.
+
+   
+** References
+
+   - Doc: {{{doc_provider}}} 
+   - Sources: {{{src_provider}}}
+
+
+* Variables in {{{enoslib}}}
+  
+  Learn how to get 2 nodes from Grid'5000 and start launching remote commands.
+
+** Discover the ~run~ command and its variants
+
+    Before proceeding you can add this util function to your code. It is only
+    used to pretty print a python dictionnary.
+    #+INCLUDE: exercices/run.py :lines "35-39" src python
+
+    And use the ~enoslib.api.run~ function 
+    #+INCLUDE: exercices/run.py :lines "40-47" src python
+   
+    Or the ~enoslib.api.run_command~ function
+    #+INCLUDE: exercices/run.py :lines "48-56" src python
+
+    #+BEGIN_note
+    ~enoslib.api.run~ is a specialisation of ~enoslib.api.run_command~. 
+    The latter let's you use [[https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html][some fancy patterns]] to determine the list of hosts to run the command on.
+
+    And yes, it uses Ansible behind the scene.
+    #+END_note
+
+** Advanced usages
+    
+   #+BEGIN_note
+   For all the remote interactions, {{{enoslib}}} relies on [[https://docs.ansible.com/ansible/latest/index.html][Ansible]]. Ansible
+   has it own variables management system.
+   For instance the task ~Gather Facts~ at the beginning of the previous tasks
+   gathers informations about all/some remote hosts and store them in the
+   Ansible management system.
+   #+END_note
+
+   Let's see what Ansible is gathering about the hosts:
+
+   #+INCLUDE: exercices/run.py :lines "58-65" src python
+
+   #+BEGIN_note
+   {{{enoslib}}} sits in between two worlds: the Python world and the Ansible
+   world. One common need is to pass a variables from one world to another.
+   - ~enoslib.api.gather_facts~ is a way to get, in Python, the variables known
+     by Ansible about each host.
+   - ~extra_vars~ keyword argument of ~enoslib.api.run~ or ~enoslib.api.run_command~ will 
+     pass variables from Python world to Ansible world (global variable)
+   - Injecting a key/value in a ~Host.extra~ attribute will make the variable ~key~ available to Ansible.
+     This makes the variables Host specific.
+   #+END_note
+
+   The following inject a global variable in the Ansible world
+   #+INCLUDE: exercices/run.py :lines "65-71" src python
+
+** Ninja level
+
+   The following is valid and inject in the ~client~ host a specific variable to
+   keep track of the server IP.
+
+   #+INCLUDE: exercices/run.py :lines "73-81" src python
+
+   #+BEGIN_note
+   Host level variables are interesting to introduce some dissymetry between
+   hosts while still using one single command to reach all of them.
+   #+END_note
+
+   #+BEGIN_question
+   How to perform simultaneously the ping to the other machine in calling only
+   once ~run~ or ~run_command~ and using host level variables?
+   #+END_question
+
+  #+BEGIN_question
+  We'd like to create 5 ~server~ machines and 5 ~client~ machines and start 5
+  *parallel* streams of data using ~iperf3~. To answer this we'll need to learn
+  a bit more on how variables are handled in {{{enoslib}}}.
+  #+END_question
+
+** Putting all together
+   Access the full file: [[file:exercices/run.py]]
+
+** Some references
+
+   - G5k configuration schema: {{{doc_g5k_schema}}}
+   - API Reference: {{{doc_api}}}
+
+* Modules: for safer remote actions
+  
+  In this section we'll discover the idiomatic way of managing resources on the
+  remote hosts. A resource can be anything: a user, a file, a line in a file, a
+  repo on Gitlab, a firewall rule ...
+
+
+** Idempotency
+
+  Let's assume you want to create a user (~foo~). With the ~run_command~ this would look like:
+
+  #+BEGIN_SRC python :noeval 
+  run_command("useradd -m foo", roles=role)
+  #+END_SRC
+
+  The main issue with this code is that it is not *idempotent*. Running it once
+  will applied the effect (create the user). But, as soon as the user exist in
+  the system, this will raise an error.
+
+** One reason why idempotency is important
+
+  Let's consider the following snippet (mispelling the second command is intentional)
+  #+BEGIN_SRC python :noeval 
+  run_command("useradd -m foo", roles=role)
+  run_command("mkdirz plop")
+  #+END_SRC
+  Executing the above leads the system with the user ~foo~ created but the the
+  directory ~plop~ not created since the second command fails.
+
+  So what you want to do is to fix the second command and re-run the snippet again.
+  But, you can't do that because ~useradd~ isn't idempotent.
+
+** Idempotency trick
+
+   One easy solution is to protect your call to non idempotent commands with
+   some ad'hoc tricks
+
+   Here it can look like this:
+
+   #+BEGIN_SRC python :noeval 
+   run_command("id foo || useradd -m foo", roles=role)
+   run_command("mkdir -p plop")
+   #+END_SRC
+
+   *What's wrong with that*
+
+   - The trick depends on the command
+   - Re-reading the code is more complex: the code focus on the **how** not the **what**
+
+** General idempotency
+    
+   The idiomatic solution is to use modules (inherited from the Ansible
+   Modules). The modules are specified in a *declarative* way and they ensure
+   *idempotency* for most of them.
+
+   So rewriting the example with modules looks like:
+   #+BEGIN_SRC python :noeval 
+   with play_on(roles=roles) as p:
+       p.user(name="foo", state="present", create_home="yes")
+       p.file(name="plop", state="directory")
+   #+END_SRC
+   
+   ~enoslib.api.play_on~ is the entry point to the module system.
+
+   You can run this code as many times as you want without any error. You'll
+   eventually find one user ~foo~ and one directory ~plop~ in your target
+   systems.
+
+   They are more than 2500 modules: https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
+
+   If you can't find what you want you must know that:
+   - Writing your own module is possible
+   - Falling back to the idempotency trick is reasonable
+
+* Tasks: to organize your experiment
+
+  To discover the Task API, head to {{{doc_tasks}}}.
+
+  The examples are written for Vagrant but may be changed to whatever provider you like/have.
+
+   #+BEGIN_question
+   Adapt the ~iperf3~ example to provide a command line
+    - Either using G5k physical machines:
+      #+BEGIN_SRC bash
+      # deploy the dependencies of the experimentation using the G5k provider
+      myperf g5k
+
+      # launch a performance measurement
+      # ideally exposes all the iperf3 client options there ;)
+      myperf bench -t 120
+
+      # Backup the reports / influxdb database
+      myperf backup
+      #+END_SRC
+
+      # Destroy the ressources on Grid'5000
+      myperf destroy
+
+    - Either using the virtual machines on Grid'5000:
+      #+BEGIN_SRC bash
+      # deploy the dependencies of the experimentation using the G5k provider
+      myperf vm5k
+
+      # Subsequent command line should be the same as above
+      # enjoy :)
+      #+END_SRC
+   #+END_question
+
diff --git a/tuto1/index.tex b/tuto1/index.tex
new file mode 100644
index 0000000000000000000000000000000000000000..2525d89f1cfa5aa88c321dfeee22a0bd2c90ca34
--- /dev/null
+++ b/tuto1/index.tex
@@ -0,0 +1,569 @@
+% Created 2019-10-17 jeu. 01:05
+% Intended LaTeX compiler: pdflatex
+\documentclass[11pt]{article}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{graphicx}
+\usepackage{grffile}
+\usepackage{longtable}
+\usepackage{wrapfig}
+\usepackage{rotating}
+\usepackage[normalem]{ulem}
+\usepackage{amsmath}
+\usepackage{textcomp}
+\usepackage{amssymb}
+\usepackage{capt-of}
+\usepackage{hyperref}
+\author{Matthieu Simonin}
+\date{}
+\title{Distributed experiments on Grid'5000 \ldots{} and beyond !}
+\hypersetup{
+ pdfauthor={Matthieu Simonin},
+ pdftitle={Distributed experiments on Grid'5000 \ldots{} and beyond !},
+ pdfkeywords={},
+ pdfsubject={},
+ pdfcreator={Emacs 26.1 (Org mode 9.1.9)}, 
+ pdflang={English}}
+\begin{document}
+
+\maketitle
+\tableofcontents
+
+
+\section{Foreword}
+\label{sec:org40b18b0}
+
+\section{Setup on Grid'5000}
+\label{sec:orgec7b370}
+
+Connect to a Grid'5000 frontend of your choice.
+
+\begin{itemize}
+\item create a new directory to host all the scripts of the session
+\item bootstrap a new python3 virtualenv
+\item install EnOSlib and configure the access to the API
+\item you'll also want to have ipython and ipdb installed
+\end{itemize}
+
+\begin{verbatim}
+$frontend: mkdir enoslib_seminar
+$frontend: cd enoslib_seminar
+$frontend: virtualenv --python=python3 venv
+$frontend: source venv/bin/activate
+$frontend(venv): pip install enoslib ipython ipdb
+$frontend(venv): echo '
+verify_ssl: False
+' > ~/.python-grid5000.yaml
+
+\end{verbatim}
+
+\section{EnOSlib warmup on Grid'5000}
+\label{sec:org54c7eac}
+
+Learn how to get 2 nodes from Grid'5000 and start launching commands.
+
+\subsection{Reserve 2 nodes}
+\label{sec:org543c543}
+
+\begin{note}
+With EnOSlib you first describe your resource requirements using an abstract
+resource description. 
+Note that the network should be explictly stated.
+\end{note}
+
+Write the following python script in a file \texttt{run.py}. If needed adapt the
+\texttt{CLUSTER} and \texttt{SITE} variables.
+
+\begin{verbatim}
+from enoslib.api import run, run_command, gather_facts
+from enoslib.infra.enos_g5k.provider import G5k
+from enoslib.infra.enos_g5k.configuration import Configuration, NetworkConfiguration
+
+import logging
+
+
+logging.basicConfig(level=logging.INFO)
+
+
+SITE = "rennes"
+CLUSTER = "paravance"
+
+network = NetworkConfiguration(id="n1",
+                               type="prod",
+                               roles=["my_network"],
+                               site=SITE)
+
+conf = Configuration.from_settings(job_name="enoslib_tutorial",
+                                   job_type="allow_classic_ssh")\
+    .add_network_conf(network)\
+    .add_machine(roles=["server"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .add_machine(roles=["client"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .finalize()
+
+provider = G5k(conf)
+roles, networks =  provider.init()
+\end{verbatim}
+
+For the sake of curiosity let's inspect the roles and networks data
+structures using ipython.
+
+\begin{verbatim}
+$frontend (venv): ipython
+In [1]: run run.py
+# ...
+# ...
+In [2]: roles
+# ...
+In [3]: networks
+\end{verbatim}
+
+\begin{note}
+The abstract resource description is concretized by the call to the
+\texttt{provider.init} method. \texttt{roles} and \texttt{networks} contains the concrete machines
+and networks given by Grid'5000.
+Check the attributes of the Host data structure in the code: \url{https://gitlab.inria.fr/discovery/enoslib/blob/v4.8.1/enoslib/host.py\#L8-14}
+\end{note}
+
+\subsection{Using the run command and its variants}
+\label{sec:org4f0ed16}
+
+For this part you have two choices to run the examples:
+\begin{itemize}
+\item (prefered) append it in the previous file and re-run the file (yes this is safe to do so)
+\item write the example in the previously open ipython console
+\end{itemize}
+
+\subsubsection{Basics usages}
+\label{sec:org7f40ca6}
+
+Before proceeding you can add this util function to your code. It only used
+to pretty print a python dictionnary.
+\begin{verbatim}
+def pprint(d):
+    import json
+    print(json.dumps(d, indent=4))
+\end{verbatim}
+
+And use the \texttt{enoslib.api.run} function 
+\begin{verbatim}
+server = roles["server"][0]
+# ---
+# Using run
+# --------------------------------------------------------------------
+result = run(f"ping -c 5 {server.address}", roles["client"])
+pprint(result)
+\end{verbatim}
+
+Or the \texttt{enoslib.api.run\_command} function
+\begin{verbatim}
+# ---
+# Using run_command 1/2
+# --------------------------------------------------------------------
+result = run_command(f"ping -c 5 {server.address}",
+                     pattern_hosts="client",
+                     roles=roles)
+pprint(result)
+\end{verbatim}
+
+\begin{note}
+\texttt{enoslib.api.run} is a specialisation of \texttt{enoslib.api.run\_command}. 
+The latter let's you use \href{https://docs.ansible.com/ansible/latest/user\_guide/intro\_patterns.html}{some fancy patterns} to determine the list of hosts to run the command on.
+
+And yes, it uses Ansible behind the scene.
+\end{note}
+
+\subsubsection{Advanced usages}
+\label{sec:org0e02fbb}
+
+\begin{note}
+For all the remote interactions, EnOSlib relies on \href{https://docs.ansible.com/ansible/latest/index.html}{Ansible}. Ansible
+has it own variables management system.
+For instance the task \texttt{Gather Facts} at the beginning of the previous tasks
+gathers informations about all/some remote hosts and store them in the
+Ansible management system.
+\end{note}
+
+Let's see what Ansible is gathering about the hosts:
+\begin{verbatim}
+# ---
+# Gather facts
+# --------------------------------------------------------------------
+result = gather_facts(roles=roles)
+pprint(result)
+\end{verbatim}
+\begin{note}
+\texttt{enoslib.api.gather\_facts} is a way to get, in python, the variables known
+by Ansible about each host.
+\end{note}
+
+\begin{note}
+EnOSlib sits in between two worlds: the Python world and the Ansible
+world. One common need is to pass a variables from one world to another.
+\begin{itemize}
+\item \texttt{enoslib.api.gather\_facts} is a way to get, in Python, the variables known
+by Ansible about each host.
+\item \texttt{extra\_vars} keyword argument of \texttt{enoslib.api.run} or \texttt{enoslib.api.run\_command} will 
+pass variables from Python world to Ansible world (global variable)
+\item Injecting a key/value in a \texttt{Host.extra} attribute will make the variable \texttt{key} available to Ansible.
+This makes the variables Host specific.
+\end{itemize}
+\end{note}
+
+The following inject a global variable in the Ansible world
+\begin{verbatim}
+# ---
+# Passing a variable to the Ansible World using a global level variable
+# --------------------------------------------------------------------
+server = roles["server"][0]
+extra_vars={"server_ip": server.address}
+result = run("ping -c 5 {{ server_ip }}", roles["client"], extra_vars=extra_vars)
+\end{verbatim}
+
+\subsubsection{Ninja level}
+\label{sec:org0edd362}
+
+The following is valid and inject in the client host a specific variable to
+keep of the server IP.
+
+\begin{verbatim}
+# ---
+# Passing a variable to the Ansible World using a host level variable
+# --------------------------------------------------------------------
+server = roles["server"][0]
+client.extra.update(server_ip=server.address)
+result = run("ping -c 5 {{ server_ip }}", roles["client"])
+\end{verbatim}
+
+\begin{note}
+Host level variables are interesting to introduce some dissymetry between
+hosts using the same intruction in your Python Code.
+\end{note}
+
+\begin{question}
+How to perform simultaneously the ping to the other machine in calling only
+once \texttt{run} or \texttt{run\_command} and using host level variables?
+\end{question}
+
+\subsubsection{All together}
+\label{sec:org31aadd8}
+Access the full file: \url{exercices/run.py}
+
+\subsubsection{Some references}
+\label{sec:orga6331bb}
+
+\begin{itemize}
+\item G5k configuration schema: \url{https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html\#g5k-schema}
+\item API Reference: \url{https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html}
+\end{itemize}
+\section{Iperf3 playground}
+\label{sec:org6a4417e}
+
+Let's experiment with \href{https://iperf.fr/}{iperf3}: a network bandwidth measuring tool. The goal is
+to deploy a simple benchmark between two hosts. 
+
+We'll also instrument the deployment in order to visualize in real-time the
+network traffic between the hosts. Since this is super common, EnOSlib
+exposes a \texttt{monitoring service} that lets you deploy very quickly what is
+needed.
+
+\subsection{First attempt}
+\label{sec:orgbfbe8c2}
+
+We adapt the previous example in the following script:
+\begin{verbatim}
+from enoslib.api import run_command, wait_ssh
+from enoslib.infra.enos_g5k.provider import G5k
+from enoslib.infra.enos_g5k.configuration import Configuration, NetworkConfiguration
+from enoslib.service import Monitoring
+
+import logging
+
+
+def pprint(d):
+    import json
+    print(json.dumps(d, indent=4))
+
+
+logging.basicConfig(level=logging.INFO)
+
+
+SITE = "rennes"
+CLUSTER = "paravance"
+
+network = NetworkConfiguration(id="n1",
+                               type="prod",
+                               roles=["my_network"],
+                               site=SITE)
+
+conf = Configuration.from_settings(job_name="enoslib_tutorial",
+                                   job_type="allow_classic_ssh")\
+    .add_network_conf(network)\
+    .add_machine(roles=["server"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .add_machine(roles=["client"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .finalize()
+
+provider = G5k(conf)
+roles, networks =  provider.init()
+wait_ssh(roles)
+
+# This deploys a monitoring stack
+m = Monitoring(collector=roles["server"],
+               agent=roles["server"] + roles["client"],
+               ui=roles["server"])
+m.deploy()
+
+
+# Below is the experimentation logic
+# It installs the bare minimum to run iperf3
+# The machine with the role 'server' is used to run a iperf3 server
+#     started in the background in a tmux
+# The machine with the role 'client' connects to that server
+# Report is printed in stdout
+server = roles["server"][0]
+run_command("apt update && apt install -y iperf3 tmux", roles=roles)
+run_command("tmux new-session -d 'exec iperf3 -s'", pattern_hosts="server", roles=roles)
+result = run_command(f"iperf3 -c {server.address} -t 30", pattern_hosts="client", roles=roles)
+pprint(result)
+\end{verbatim}
+
+Now, let's visualize the network traffic in real-time !
+\begin{note}
+Usually I follow this to access services running inside Grid'5000:
+\url{https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html\#accessing-http-services-inside-grid-5000}
+
+So to access the monitoring dashboard you need to connect using your browser
+to the machine `server` on the port 3000.
+\end{note}
+
+You should be able to visualize such a thing (after a bit of point and clicks).
+
+\href{./iperf3.png}{\begin{figure}[htbp]
+\centering
+\includegraphics[width=.9\linewidth]{./figs/iperf3.png}
+\caption{\label{fig:orgd2b4ea5}
+iperf3 / monitoring}
+\end{figure}}
+
+\subsection{Discussion}
+\label{sec:org8354e5d}
+
+\begin{itemize}
+\item What's good is: \ldots{}
+\item What's wrong is: \ldots{}
+\end{itemize}
+
+\subsection{A better approach (maybe)}
+\label{sec:org16d8bce}
+Access the full file: \url{exercices/iperf3\_better.py}
+
+\section{{\bfseries\sffamily TODO} Partial wrap-up}
+\label{sec:orgb35f46e}
+
+\begin{itemize}
+\item Configuration for G5k
+\begin{itemize}
+\item non deploy / deploy
+\item prod network / kavlan
+\end{itemize}
+\item Services
+\end{itemize}
+
+\section{Modules: for safer remote actions}
+\label{sec:org1ae5927}
+
+In this section we'll discover the idiomatic way of managing resources on the
+remote hosts. A resource can be anything: a user, a file, a line in a file, a
+repo on Gitlab, a firewall rule \ldots{}
+
+
+\subsection{Idempotency}
+\label{sec:org81e26b7}
+
+Let's assume you want to create a user (\texttt{foo}). With the \texttt{run\_command} this would look like:
+
+\begin{verbatim}
+run_command("useradd -m foo", roles=role)
+\end{verbatim}
+
+The main issue with this code is that it is not \textbf{idempotent}. Running it once
+will applied the effect (create the user). But, as soon as the user exist in
+the system, this will raise an error.
+
+\subsection{One reason why idempotency is important}
+\label{sec:org53c14cb}
+
+Let's consider the following snippet (mispelling the second command is intentional)
+\begin{verbatim}
+run_command("useradd -m foo", roles=role)
+run_command("mkdirz plop")
+\end{verbatim}
+Executing the above leads the system with the user \texttt{foo} created but the the
+directory \texttt{plop} not created since the second command fails.
+
+So what you want to do is to fix the second command and re-run the snippet again.
+But, you can't do that because \texttt{useradd} isn't idempotent.
+
+\subsection{Idempotency trick}
+\label{sec:orgb15c5ef}
+
+One easy solution is to protect your call to non idempotent commands with
+some ad'hoc tricks
+
+Here it can look like this:
+
+\begin{verbatim}
+run_command("id foo || useradd -m foo", roles=role)
+run_command("mkdir -p plop")
+\end{verbatim}
+
+\textbf{What's wrong with that}
+
+\begin{itemize}
+\item The trick depends on the command
+\item Re-reading the code is more complex: the code focus on the \textbf{\textbf{how}} not the \textbf{\textbf{what}}
+\end{itemize}
+
+\subsection{General idempotency}
+\label{sec:org4061e60}
+
+The idiomatic solution is to use modules (inherited from the Ansible
+Modules). The modules are specified in a \textbf{declarative} way and they ensure
+\textbf{idempotency} for most of them.
+
+So rewriting the example with modules looks like:
+\begin{verbatim}
+with play_on(roles=roles) as p:
+    p.user(name="foo", state="present", create_home="yes")
+    p.file(name="plop", state="directory")
+\end{verbatim}
+
+You can run this code as many times as you want without any error. You'll
+eventually find one user \texttt{foo} and one directory \texttt{plop} in your target
+systems.
+
+
+They are more than 2500 modules: \url{https://docs.ansible.com/ansible/latest/modules/list\_of\_all\_modules.html}
+
+If you can't find what you want you must know that:
+\begin{itemize}
+\item Writing your own module is possible
+\item Falling back to the idempotency trick is reasonable
+\end{itemize}
+
+\section{Providers: to replicate your experiment}
+\label{sec:orgfc2ec82}
+
+The resources that are used for your experiment are acquired through a
+provider. Providers are a mean to decouple the infrastructure code (the code
+that get the resources) from the code that runs the experiment. Changing the
+provider allows to replicate the experiment on another testbed.
+
+Originally it was used to iterate on the code locally (using the Vagrant
+provider) and to only test on Grid'5000 when necessary.
+
+We now have couple of providers that you may picked or mixed.
+
+\subsection{iperf3 on virtual machines on Grid'5000}
+\label{sec:org162cac9}
+
+We'll adapt the initial iperf3 example to use virtual machines instead of
+bare-metal machine. 
+
+Note that:
+
+\begin{itemize}
+\item The configuration object is different
+\item The experimentation logic is the same (rewritten using modules when it applies)
+\end{itemize}
+
+\begin{verbatim}
+from enoslib.api import play_on, wait_ssh
+from enoslib.infra.enos_vmong5k.provider import VMonG5k
+from enoslib.infra.enos_vmong5k.configuration import Configuration
+
+import logging
+import os
+
+logging.basicConfig(level=logging.DEBUG)
+
+CLUSTER = "paravance"
+
+# path to the inventory
+inventory = os.path.join(os.getcwd(), "hosts")
+
+# claim the resources
+conf = Configuration.from_settings(job_name="enoslib_tutorial", gateway=True)\
+                    .add_machine(roles=["server"],
+                                 cluster=CLUSTER,
+                                 number=1,
+                                 flavour="large")\
+                    .add_machine(roles=["client"],
+                                 cluster=CLUSTER,
+                                 number=1,
+                                 flavour="medium")\
+                    .finalize()
+
+provider = VMonG5k(conf)
+
+roles, networks = provider.init()
+wait_ssh(roles)
+
+# Below is the experimentation logic
+# It installs the bare minimum to run iperf3
+# The machine with the role 'server' is used to run a iperf3 server
+#     started in the background in a tmux
+# The machine with the role 'client' connects to that server
+# Report is printed in stdout
+server = roles["server"][0]
+
+with play_on(roles=roles) as p:
+    p.apt(name=["iperf3", "tmux"], state="present")
+
+with play_on(pattern_hosts="server", roles=roles) as p:
+    p.shell("tmux new-session -d 'exec iperf3 -s'")
+
+with play_on(pattern_hosts="client", roles=roles) as p:
+    p.shell(f"iperf3 -c {server.address} -t 30")
+
+with play_on(pattern_hosts="client", roles=roles) as p:
+    p.shell(f"iperf3 -c {server.address} -t 30 --logfile iperf3.out")
+    p.fetch(src="iperf3.out", dest="iperf3.out")
+\end{verbatim}
+
+Using module using the \texttt{play\_on} context manager does not bring back the
+results of the commands. Iperf3 let's you write the result of the command on
+a file. We just need to scp the file back to our local machine using the
+\texttt{fetch} module.
+
+\subsection{Ninja level}
+\label{sec:orge484eb8}
+
+Creates 5 \texttt{server} machines and 5 \texttt{client} machines and start 5 \textbf{parallel}
+streams of data using \texttt{iperf3}.
+
+\subsection{References}
+\label{sec:org9c0017b}
+
+\begin{itemize}
+\item Doc: \url{https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html}
+\item Sources: \url{https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra}
+\end{itemize}
+
+\section{Tasks: to organize your experiment}
+\label{sec:org7f002c7}
+
+To discover the Task API, head to \url{https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html}.
+The examples are written for Vagrant but may be changed to whatever provider you like/have.
+\end{document}
diff --git a/tuto1/timeline.css b/tuto1/timeline.css
new file mode 100644
index 0000000000000000000000000000000000000000..268b0deaebe45d42a32888682272253296930629
--- /dev/null
+++ b/tuto1/timeline.css
@@ -0,0 +1,1035 @@
+@import url('https://fonts.googleapis.com/css?family=Crimson+Text:700|Fira+Sans:400,700');
+html {
+    font-family: sans-serif;
+    line-height: 1.15;
+    -ms-text-size-adjust: 100%;
+    -webkit-text-size-adjust: 100%
+}
+body {
+    margin: 0
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+    display: block
+}
+audio,
+canvas,
+progress,
+video {
+    display: inline-block
+}
+audio:not([controls]) {
+    display: none;
+    height: 0
+}
+progress {
+    vertical-align: baseline
+}
+[hidden],
+template {
+    display: none
+}
+a {
+    background-color: transparent;
+    -webkit-text-decoration-skip: objects
+}
+a:active,
+a:hover {
+    outline-width: 0
+}
+abbr[title] {
+    border-bottom: none;
+    text-decoration: underline;
+    text-decoration: underline dotted
+}
+b,
+strong {
+    font-weight: inherit;
+    font-weight: bolder
+}
+dfn {
+    font-style: italic
+}
+h1 {
+    font-size: 2em;
+    margin: .67em 0
+}
+mark {
+    background-color: #ff0;
+    color: #000
+}
+small {
+    font-size: 80%
+}
+sub,
+sup {
+    font-size: 75%;
+    line-height: 0;
+    position: relative;
+    vertical-align: baseline
+}
+sub {
+    bottom: -.25em
+}
+sup {
+    top: -.5em
+}
+img {
+    border-style: none
+}
+svg:not(:root) {
+    overflow: hidden
+}
+code,
+kbd,
+pre,
+samp {
+    font-family: monospace, monospace;
+    font-size: 1em
+}
+figure {
+    margin: 1em 40px
+}
+hr {
+    box-sizing: content-box;
+    height: 0;
+    overflow: visible
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+    font: inherit;
+    margin: 0
+}
+optgroup {
+    font-weight: 700
+}
+button,
+input {
+    overflow: visible
+}
+button,
+select {
+    text-transform: none
+}
+[type=reset],
+[type=submit],
+button,
+html [type=button] {
+    -webkit-appearance: button
+}
+[type=button]::-moz-focus-inner,
+[type=reset]::-moz-focus-inner,
+[type=submit]::-moz-focus-inner,
+button::-moz-focus-inner {
+    border-style: none;
+    padding: 0
+}
+[type=button]:-moz-focusring,
+[type=reset]:-moz-focusring,
+[type=submit]:-moz-focusring,
+button:-moz-focusring {
+    outline: 1px dotted ButtonText
+}
+fieldset {
+    border: 1px solid silver;
+    margin: 0 2px;
+    padding: .35em .625em .75em
+}
+legend {
+    box-sizing: border-box;
+    color: inherit;
+    display: table;
+    max-width: 100%;
+    padding: 0;
+    white-space: normal
+}
+textarea {
+    overflow: auto
+}
+[type=checkbox],
+[type=radio] {
+    box-sizing: border-box;
+    padding: 0
+}
+[type=number]::-webkit-inner-spin-button,
+[type=number]::-webkit-outer-spin-button {
+    height: auto
+}
+[type=search] {
+    -webkit-appearance: textfield;
+    outline-offset: -2px
+}
+[type=search]::-webkit-search-cancel-button,
+[type=search]::-webkit-search-decoration {
+    -webkit-appearance: none
+}
+::-webkit-input-placeholder {
+    color: inherit;
+    opacity: .54
+}
+::-webkit-file-upload-button {
+    -webkit-appearance: button;
+    font: inherit
+}
+.org-bold {
+    font-weight: 700
+}
+.org-bold-italic {
+    font-weight: 700;
+    font-style: italic
+}
+.org-buffer-menu-buffer {
+    font-weight: 700
+}
+.org-builtin {
+    color: #483d8b
+}
+.org-button {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-calendar-month-header {
+    color: #00f
+}
+.org-calendar-today {
+    text-decoration: underline
+}
+.org-calendar-weekday-header {
+    color: #008b8b
+}
+.org-calendar-weekend-header {
+    color: #b22222
+}
+.org-comint-highlight-input {
+    font-weight: 700
+}
+.org-comint-highlight-prompt {
+    color: #0000cd
+}
+.org-comment,
+.org-comment-delimiter {
+    color: #b22222
+}
+.org-constant {
+    color: #008b8b
+}
+.org-diary {
+    color: red
+}
+.org-doc {
+    color: #8b2252
+}
+.org-error {
+    color: red;
+    font-weight: 700
+}
+.org-escape-glyph {
+    color: brown
+}
+.org-file-name-shadow {
+    color: #7f7f7f
+}
+.org-fringe {
+    background-color: #f2f2f2
+}
+.org-function-name {
+    color: #00f
+}
+.org-glyphless-char {
+    font-size: 60%
+}
+.org-header-line {
+    color: #333;
+    background-color: #e5e5e5
+}
+.org-help-argument-name {
+    font-style: italic
+}
+.org-highlight {
+    background-color: #b4eeb4
+}
+.org-holiday {
+    background-color: pink
+}
+.org-info-header-node {
+    color: brown;
+    font-weight: 700;
+    font-style: italic
+}
+.org-info-header-xref {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-info-index-match {
+    background-color: #ff0
+}
+.org-info-menu-header {
+    font-weight: 700
+}
+.org-info-menu-star {
+    color: red
+}
+.org-info-node {
+    color: brown;
+    font-weight: 700;
+    font-style: italic
+}
+.org-info-title-1 {
+    font-size: 172%;
+    font-weight: 700
+}
+.org-info-title-2 {
+    font-size: 144%;
+    font-weight: 700
+}
+.org-info-title-3 {
+    font-size: 120%;
+    font-weight: 700
+}
+.org-info-title-4 {
+    font-weight: 700
+}
+.org-info-xref {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-italic {
+    font-style: italic
+}
+.org-keyword {
+    color: #a020f0
+}
+.org-lazy-highlight {
+    background-color: #afeeee
+}
+.org-link {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-link-visited {
+    color: #8b008b;
+    text-decoration: underline
+}
+.org-makefile-makepp-perl {
+    background-color: #bfefff
+}
+.org-makefile-space {
+    background-color: #ff69b4
+}
+.org-makefile-targets {
+    color: #00f
+}
+.org-match {
+    background-color: #ff0
+}
+.org-next-error {
+    background-color: gtk_selection_bg_color
+}
+.org-nobreak-space {
+    color: brown;
+    text-decoration: underline
+}
+.org-org-agenda-calendar-event,
+.org-org-agenda-calendar-sexp {
+    color: #000;
+    background-color: #fff
+}
+.org-org-agenda-clocking {
+    background-color: #ff0
+}
+.org-org-agenda-column-dateline {
+    background-color: #e5e5e5
+}
+.org-org-agenda-current-time {
+    color: #b8860b
+}
+.org-org-agenda-date {
+    color: #00f
+}
+.org-org-agenda-date-today {
+    color: #00f;
+    font-weight: 700;
+    font-style: italic
+}
+.org-org-agenda-date-weekend {
+    color: #00f;
+    font-weight: 700
+}
+.org-org-agenda-diary {
+    color: #000;
+    background-color: #fff
+}
+.org-org-agenda-dimmed-todo {
+    color: #7f7f7f
+}
+.org-org-agenda-done {
+    color: #228b22
+}
+.org-org-agenda-filter-category,
+.org-org-agenda-filter-effort,
+.org-org-agenda-filter-regexp,
+.org-org-agenda-filter-tags {
+    color: #000;
+    background-color: #bfbfbf
+}
+.org-org-agenda-restriction-lock {
+    background-color: #eee
+}
+.org-org-agenda-structure {
+    color: #00f
+}
+.org-org-archived,
+.org-org-block {
+    color: #7f7f7f
+}
+.org-org-block-begin-line,
+.org-org-block-end-line {
+    color: #b22222
+}
+.org-org-checkbox {
+    font-weight: 700
+}
+.org-org-checkbox-statistics-done {
+    color: #228b22;
+    font-weight: 700
+}
+.org-org-checkbox-statistics-todo {
+    color: red;
+    font-weight: 700
+}
+.org-org-clock-overlay {
+    color: #000;
+    background-color: #d3d3d3
+}
+.org-org-code {
+    color: #7f7f7f
+}
+.org-org-column,
+.org-org-column-title {
+    background-color: #e5e5e5
+}
+.org-org-column-title {
+    font-weight: 700;
+    text-decoration: underline
+}
+.org-org-date {
+    color: #a020f0;
+    text-decoration: underline
+}
+.org-org-date-selected {
+    color: red
+}
+.org-org-default {
+    color: #000;
+    background-color: #fff
+}
+.org-org-document-info {
+    color: #191970
+}
+.org-org-document-info-keyword {
+    color: #7f7f7f
+}
+.org-org-document-title {
+    color: #191970;
+    font-weight: 700
+}
+.org-org-done {
+    color: #228b22;
+    font-weight: 700
+}
+.org-org-drawer {
+    color: #00f
+}
+.org-org-ellipsis {
+    color: #b8860b;
+    text-decoration: underline
+}
+.org-org-footnote {
+    color: #a020f0;
+    text-decoration: underline
+}
+.org-org-formula {
+    color: #b22222
+}
+.org-org-headline-done {
+    color: #bc8f8f
+}
+.org-org-hide {
+    color: #fff
+}
+.org-org-latex-and-related {
+    color: #8b4513
+}
+.org-org-level-1 {
+    color: #00f
+}
+.org-org-level-2 {
+    color: sienna
+}
+.org-org-level-3 {
+    color: #a020f0
+}
+.org-org-level-4 {
+    color: #b22222
+}
+.org-org-level-5 {
+    color: #228b22
+}
+.org-org-level-6 {
+    color: #008b8b
+}
+.org-org-level-7 {
+    color: #483d8b
+}
+.org-org-level-8 {
+    color: #8b2252
+}
+.org-org-link {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-org-list-dt {
+    font-weight: 700
+}
+.org-org-macro {
+    color: #8b4513
+}
+.org-org-meta-line {
+    color: #b22222
+}
+.org-org-mode-line-clock {
+    color: #000;
+    background-color: #bfbfbf
+}
+.org-org-mode-line-clock-overrun {
+    color: #000;
+    background-color: red
+}
+.org-org-priority {
+    color: #a020f0
+}
+.org-org-quote {
+    color: #7f7f7f
+}
+.org-org-scheduled {
+    color: #006400
+}
+.org-org-scheduled-previously {
+    color: #b22222
+}
+.org-org-scheduled-today {
+    color: #006400
+}
+.org-org-sexp-date,
+.org-org-special-keyword {
+    color: #a020f0
+}
+.org-org-table {
+    color: #00f
+}
+.org-org-tag,
+.org-org-tag-group {
+    font-weight: 700
+}
+.org-org-target {
+    text-decoration: underline
+}
+.org-org-time-grid {
+    color: #b8860b
+}
+.org-org-todo {
+    color: red;
+    font-weight: 700
+}
+.org-org-upcoming-deadline {
+    color: #b22222
+}
+.org-org-verbatim,
+.org-org-verse {
+    color: #7f7f7f
+}
+.org-org-warning {
+    color: red;
+    font-weight: 700
+}
+.org-outline-1 {
+    color: #00f
+}
+.org-outline-2 {
+    color: sienna
+}
+.org-outline-3 {
+    color: #a020f0
+}
+.org-outline-4 {
+    color: #b22222
+}
+.org-outline-5 {
+    color: #228b22
+}
+.org-outline-6 {
+    color: #008b8b
+}
+.org-outline-7 {
+    color: #483d8b
+}
+.org-outline-8 {
+    color: #8b2252
+}
+.org-preprocessor {
+    color: #483d8b
+}
+.org-regexp-grouping-backslash,
+.org-regexp-grouping-construct {
+    font-weight: 700
+}
+.org-region {
+    background-color: gtk_selection_bg_color
+}
+.org-secondary-selection {
+    background-color: #ff0
+}
+.org-shadow {
+    color: #7f7f7f
+}
+.org-show-paren-match {
+    background-color: #40e0d0
+}
+.org-show-paren-mismatch {
+    color: #fff;
+    background-color: #a020f0
+}
+.org-string {
+    color: #8b2252
+}
+.org-success {
+    color: #228b22;
+    font-weight: 700
+}
+.org-table-cell {
+    color: #e5e5e5;
+    background-color: #00f
+}
+.org-tooltip {
+    color: #000;
+    background-color: #ffffe0
+}
+.org-trailing-whitespace {
+    background-color: red
+}
+.org-type {
+    color: #228b22
+}
+.org-underline {
+    text-decoration: underline
+}
+.org-variable-name {
+    color: sienna
+}
+.org-warning {
+    color: #ff8c00;
+    font-weight: 700
+}
+.org-warning-1 {
+    color: red;
+    font-weight: 700
+}
+body {
+    width: 95%;
+    margin: 2%;
+    font: normal normal normal 16px/1.6em 'Fira Sans', sans-serif;
+    color: #333
+}
+@media (min-width: 769px) {
+    body {
+        width: 700px;
+        margin-left: 5vw
+    }
+}
+::-moz-selection {
+    background: #d6edff
+}
+::selection {
+    background: #d6edff
+}
+.title {
+    margin: auto;
+    color: #000
+}
+.subtitle,
+.title {
+    text-align: center
+}
+.subtitle {
+    font-size: medium;
+    font-weight: 700
+}
+.abstract {
+    margin: auto;
+    width: 80%;
+    font-style: italic
+}
+.abstract p:last-of-type:before {
+    content: "    ";
+    white-space: pre
+}
+.status {
+    font-size: 90%;
+    margin: 2em auto
+}
+[class^=section-number-] {
+    margin-right: .5em
+}
+[id^=orgheadline] {
+    clear: both
+}
+#footnotes {
+    font-size: 90%
+}
+.footpara {
+    display: inline;
+    margin: .2em auto
+}
+.footdef {
+    margin-bottom: 1em
+}
+.footdef sup {
+    padding-right: .5em
+}
+a {
+    color: #527d9a;
+    text-decoration: none
+}
+a:hover {
+    color: #035;
+    border-bottom: 1px dotted
+}
+figure {
+    padding: 0;
+    margin: 0;
+    text-align: center
+}
+img {
+    max-width: 100%;
+    vertical-align: middle
+}
+.MathJax_Display {
+    font-size: 90%;
+    margin: 0!important;
+    width: 90%!important
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+    color: #a5573e;
+    line-height: 1.6em;
+    font-weight: bold;
+    font-family: 'Crimson Text', serif
+}
+h4,
+h5,
+h6 {
+    font-size: 1em
+}
+dt {
+    font-weight: 700
+}
+table {
+    margin: auto;
+    border-top: 2px solid;
+    border-collapse: collapse
+}
+table,
+thead {
+    border-bottom: 2px solid
+}
+table td+td,
+table th+th {
+    border-left: 1px solid gray
+}
+table tr {
+    border-top: 1px solid #d3d3d3
+}
+td,
+th {
+    padding: 5px 10px;
+    vertical-align: middle
+}
+caption.t-above {
+    caption-side: top
+}
+caption.t-bottom {
+    caption-side: bottom
+}
+th.org-center,
+th.org-left,
+th.org-right {
+    text-align: center
+}
+td.org-right {
+    text-align: right
+}
+td.org-left {
+    text-align: left
+}
+td.org-center {
+    text-align: center
+}
+code {
+    padding: 2px 5px;
+    margin: auto 1px;
+    border: 1px solid #ddd;
+    border-radius: 3px;
+    background-clip: padding-box;
+    color: #333;
+    font-size: 80%
+}
+blockquote {
+    margin: 1em 2em;
+    padding-left: 1em;
+    border-left: 3px solid #ccc
+}
+kbd {
+    background-color: #f7f7f7;
+    font-size: 80%;
+    margin: 0 .1em;
+    padding: .1em .6em
+}
+.todo {
+    background-color: red;
+    padding: 2px
+}
+.done,
+.todo {
+    color: #fff;
+    border-radius: 3px;
+    background-clip: padding-box;
+    font-size: 80%;
+    font-family: Lucida Console, monospace
+}
+.done {
+    background-color: green;
+    padding: 3px
+}
+.priority {
+    color: orange;
+    font-family: Lucida Console, monospace
+}
+#table-of-contents li {
+    clear: both
+}
+.tag {
+    font-family: Lucida Console, monospace;
+    font-size: 70%;
+    font-weight: 400
+}
+.tag span {
+    padding: 0 5px;
+    float: right;
+    margin-right: 5px;
+    border: 1px solid #bbb;
+    border-radius: 3px;
+    background-clip: padding-box;
+    color: #333;
+    background-color: #eee;
+    line-height: 1.6
+}
+.timestamp {
+    color: #bebebe;
+    font-size: 90%
+}
+.timestamp-kwd {
+    color: #5f9ea0
+}
+.org-right {
+    margin-left: auto;
+    margin-right: 0;
+    text-align: right
+}
+.org-left {
+    margin-left: 0;
+    margin-right: auto;
+    text-align: left
+}
+.org-center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center
+}
+.underline {
+    text-decoration: underline
+}
+#postamble p,
+#preamble p {
+    font-size: 90%;
+    margin: .2em
+}
+p.verse {
+    margin-left: 3%
+}
+pre {
+    border: 1px solid #ccc;
+    box-shadow: 3px 3px 3px #eee;
+    font-family: Lucida Console, monospace;
+    margin: 1.2em;
+    padding: 8pt;
+    font-size: 80%;
+    background:  #3f3f3f;
+    color: #dcdccc;
+}
+pre.src {
+    overflow: auto;
+    padding-top: 1.2em;
+    position: relative
+}
+pre.src:hover:before {
+    display: inline
+}
+pre.src-sh:before {
+    content: "sh"
+}
+pre.src-bash:before {
+    content: "bash"
+}
+pre.src-emacs-lisp:before {
+    content: "Emacs Lisp"
+}
+pre.src-R:before {
+    content: "R"
+}
+pre.src-org:before {
+    content: "Org"
+}
+pre.src-cpp:before {
+    content: "C++"
+}
+pre.src-c:before {
+    content: "C"
+}
+pre.src-html:before {
+    content: "HTML"
+}
+pre.src-javascript:before,
+pre.src-js:before {
+    content: "Javascript"
+}
+pre.src-makefile:before {
+    content: "Makefile"
+}
+.inlinetask {
+    background: #ffc;
+    border: 2px solid gray;
+    margin: 10px;
+    padding: 10px
+}
+#org-div-home-and-up {
+    font-size: 70%;
+    text-align: right;
+    white-space: nowrap
+}
+.linenr {
+    font-size: 90%
+}
+.code-highlighted {
+    color: #FFFFE0;
+    background-color: #284F28;
+}
+#bibliography {
+    font-size: 90%
+}
+#bibliography table {
+    width: 100%
+}
+.creator {
+    display: block
+}
+@media (min-width: 769px) {
+    .creator {
+        display: inline;
+        float: right
+    }
+}
+
+.org-src-container > label {
+    font-size: 75%;
+}
+
+.note {
+    padding-left: 2em;
+    border: 1px dashed #00f;
+    position: relative;
+}
+.note:before {
+    display: block;
+    position: absolute;
+    left: 0px;
+    content: "i";
+    background: #00f;
+    border-radius: 0.8em;
+    -moz-border-radius: 0.8em;
+    -webkit-border-radius: 0.8em;
+    color: #ffffff;
+    display: inline-block;
+    font-weight: bold;
+    line-height: 1.6em;
+    margin-right: 5px;
+    text-align: center;
+    width: 1.6em;
+}
+
+@media screen and (min-width: 600px) {
+    h1 {
+        font-size: 2em;
+    }
+    h2 {
+        font-size: 1.5em;
+    }
+    h3 {
+        font-size: 1.3em;
+    }
+    h1,h2,h3 {
+        line-height: 1.4em;
+    }
+    h4,h5,h6 {
+        font-size: 1.1em;
+    }
+}
+
+.question {
+    padding-left: 2em;
+    border: 1px dashed #0f0;
+    position: relative;
+}
+.question:before {
+    display: block;
+    position: absolute;
+    left: 0px;
+    content: "?";
+    background: #00ff00;
+    border-radius: 0.8em;
+    -moz-border-radius: 0.8em;
+    -webkit-border-radius: 0.8em;
+    color: #ffffff;
+    display: inline-block;
+    font-weight: bold;
+    line-height: 1.6em;
+    margin-right: 5px;
+    text-align: center;
+    width: 1.6em;
+}
diff --git a/tuto2/figs/overleaf-v2-editor.png b/tuto2/figs/overleaf-v2-editor.png
new file mode 100644
index 0000000000000000000000000000000000000000..6343372093a8514b887e59b83d0f32d5569fb92f
Binary files /dev/null and b/tuto2/figs/overleaf-v2-editor.png differ
diff --git a/tuto2/figs/simple_compilation.png b/tuto2/figs/simple_compilation.png
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/tuto2/figs/simple_compilation.svg b/tuto2/figs/simple_compilation.svg
new file mode 100644
index 0000000000000000000000000000000000000000..f9a7a2c86d6e874bb4a948920002c9f9a983e769
--- /dev/null
+++ b/tuto2/figs/simple_compilation.svg
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="596px" height="452px" viewBox="-0.5 -0.5 596 452" content="&lt;mxfile modified=&quot;2019-11-28T22:37:51.216Z&quot; host=&quot;www.draw.io&quot; agent=&quot;Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:70.0) Gecko/20100101 Firefox/70.0&quot; etag=&quot;VcwF2yikf7-QsSzdrXRU&quot; version=&quot;12.3.3&quot; type=&quot;device&quot; pages=&quot;1&quot;&gt;&lt;diagram id=&quot;f106602c-feb2-e66a-4537-3a34d633f6aa&quot; name=&quot;Page-1&quot;&gt;7ZpfU+o4FMA/DY86TdIGeASEXWe4i3t1xnufdmIbS6+l6aZBy376TUhKmxYFuSCMgs7QnJz8/52Tk5QWGszyPzhJp99YQOMWdIK8ha5aEAIXwpb6d4KFlrRdoAUhjwKjVApuo/+oETpGOo8CmlmKgrFYRKkt9FmSUF9YMsI5e7HVHllst5qSkDYEtz6Jm9L7KBBTIwW4W2b8SaNwapruwLbOeCD+U8jZPDHttSB6XH509owUdZmBZlMSsJeKCA1baMAZE/pplg9orOa2mDZdbvRK7qrfnCZimwI4H82ze5hfBQ/DX+DvdPjS/3mxWq1MLIoZoYGcIJNkXExZyBISD0tpfzlqqup1ZKrUGTOWSiGQwl9UiIVZbTIXTIqmYhabXNllvvihyl+CtlcIfi4Fq+RVbhrQqUU1dUN5NKOCciPUg1A9f3V2ioGyOffpW1MCkcGQ8JCKNycPrdZR2gdlskd8IUtyGhMRPdt9IQbUcKW3KnrDItlL6BijQp5hz5gUwp5dhe6ZKVUuuXyodKMULUF4DxTFDDyTeG4GMYgjalqrssLmIo4SOlgZp1qMR5aIAYsZX+og+TdSrfdDTgJVS5GXsETRlAnOnui6Ao9RHFfkxrxQPyDZdIXfM+UikvY8Jg80vmFZJCKWyLwHJgSbVRR6cRSqDKEg7ROT8mWHFEZVPNUADLsAFmkzaNUkyVI92scoV/3oS9tOVeYsD5WXvCQvmXvJqWbt2lf96cukfrK1fD2xBcKqszR/G+ImcKZAB1jcwK5xPS+lY8NGNK24tEK2jlCLrXeD5DoNYr68d2l/ee/SPnuXT+BdUBce2bsg9xjeZZ/OADnrZ/x3Tbzr2UsF8VYm3uOcLCpqqVLItm8Hgk5tVXWN+/UfyDn7j0/gP0Cnc2z/0T1ydFKLTTrusYMT9MoK7tsfddsfG3IgcHYZn8BluF332Aea5sm4BXEszJxaLOF/56zIuMiWs9+TCnL8eZkpn0L1fT+Uj87N5Ptdb1zUKLuoK9UqDVarC2yD5YGOO0INFA2f6/mJa7itONrIY4O8LCV+lIR3S494gWsAghqAoGlh3eVnDYehn8LLKc0Ngik3BPpsls4F/YcmobTePZCHiqNr4bJA8ywNAGqyB5zDweceCL6ryeD2bvJ9eAbv+OB5ng2e2276vA8HDx8IvNH1eHgm70TJA8WyH5E8bx15747Z6+GPFY0HPfUWSS1uzPynu2mUaPEoigslO+bXgBUvi6DWNtW7y3zCRSVtBXeN2NCFhluaR0IfCzrQM+nKnaVMlacClVhUEvUzwUnfgLrbv19x1wNbBbJg7zePKK6HLPg9UGNaj6txRGlU5G2qaE93L26nFqBg581+1fU96NbM8xB3NV7zrvdsv1/HfvGH2a/n2HjDzo72izdVdCL2C7r4A+wXN+9a9xP5DSbfbq7HvbvryV/n2O/0Yr9TOO7idXctn33vsHcOfSO869ZR2zgA3mXnWI6omKbVBaeUmTna++6Ct91d8Csvzw6wu9Rjp+6OmwvYVNGhL8LxuiukA9mUgaU0J+dsTrY5Vb1O1ab2/Zq52MVP6sSFgf07FIjhjhFbrSKEtnvbvT+jOl9SfOFDzgduQ249Squ/6Nr+kmJDRTubjEyWP2nW6uXvxtHwfw==&lt;/diagram&gt;&lt;/mxfile&gt;"><defs/><g><path d="M 60 174 L 160 174 L 160 214 L 272.63 214" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 277.88 214 L 270.88 217.5 L 272.63 214 L 270.88 210.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 144 L 60 144 L 60 204 L 0 204 Z" fill="#ffffff" stroke="none" pointer-events="all"/><path d="M 37.98 189.84 C 37.27 189.84 36.7 190.29 36.7 190.84 L 36.7 192.75 C 36.7 193.31 37.27 193.75 37.98 193.75 L 48.95 193.75 C 49.66 193.75 50.23 193.31 50.23 192.75 L 50.23 190.84 C 50.23 190.29 49.66 189.84 48.95 189.84 Z M 9.51 187.84 L 50.51 187.84 C 51.46 187.84 52.17 188.54 52.17 189.38 L 52.17 194.18 C 52.17 195.01 51.46 195.71 50.51 195.71 L 9.51 195.71 C 8.54 195.71 7.84 195.01 7.84 194.18 L 7.84 189.38 C 7.84 188.54 8.54 187.84 9.51 187.84 Z M 9.51 186.05 C 7.63 186.05 6.05 187.52 6.05 189.38 L 6.05 194.18 C 6.05 196.03 7.63 197.5 9.51 197.5 L 50.51 197.5 C 52.38 197.5 53.96 196.03 53.96 194.18 L 53.96 189.38 C 53.96 187.52 52.38 186.05 50.51 186.05 Z M 11.64 156.14 L 48.34 156.14 L 48.34 178.44 L 11.64 178.44 Z M 10.77 154.35 C 10.77 154.35 10.27 154.5 10.27 154.5 C 10.27 154.5 10.17 154.58 10.13 154.61 C 10.1 154.65 10.07 154.69 10.05 154.71 C 9.96 154.83 9.94 154.9 9.92 154.95 C 9.88 155.05 9.88 155.1 9.87 155.15 C 9.86 155.24 9.85 155.29 9.85 155.37 L 9.85 179.21 C 9.85 179.28 9.86 179.34 9.87 179.43 C 9.88 179.48 9.88 179.52 9.92 179.62 C 9.94 179.67 9.96 179.75 10.05 179.86 C 10.07 179.89 10.1 179.93 10.13 179.96 C 10.17 180 10.27 180.07 10.27 180.07 C 10.27 180.08 10.77 180.23 10.77 180.23 L 49.21 180.23 C 49.22 180.23 49.71 180.07 49.71 180.07 C 49.71 180.07 49.82 180 49.85 179.96 C 49.89 179.93 49.91 179.89 49.94 179.86 C 50.03 179.75 50.04 179.67 50.07 179.62 C 50.11 179.52 50.11 179.48 50.12 179.43 C 50.13 179.34 50.13 179.28 50.13 179.21 L 50.13 155.37 C 50.13 155.29 50.13 155.24 50.12 155.15 C 50.11 155.1 50.11 155.05 50.07 154.95 C 50.04 154.9 50.03 154.83 49.94 154.71 C 49.91 154.69 49.89 154.65 49.85 154.61 C 49.82 154.58 49.71 154.5 49.71 154.5 C 49.71 154.5 49.22 154.35 49.21 154.35 Z M 8.65 152.29 L 51.35 152.29 C 51.81 152.29 52.22 152.69 52.22 153.29 L 52.22 181.24 C 52.22 181.84 51.81 182.23 51.35 182.23 L 8.65 182.23 C 8.2 182.23 7.79 181.84 7.79 181.24 L 7.79 153.29 C 7.79 152.69 8.2 152.29 8.65 152.29 Z M 8.65 150.5 C 7.16 150.5 6 151.79 6 153.29 L 6 181.24 C 6 182.73 7.16 184.02 8.65 184.02 L 51.35 184.02 C 52.84 184.02 54 182.73 54 181.24 L 54 153.29 C 54 151.79 52.84 150.5 51.35 150.5 Z" fill="#232f3e" stroke="none" pointer-events="all"/><g transform="translate(13.5,211.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="32" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(35, 47, 62); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Client</div></div></foreignObject><text x="16" y="12" fill="#232F3E" text-anchor="middle" font-size="12px" font-family="Helvetica">Client</text></switch></g><path d="M 60 276 L 160 276 L 160 214 L 272.63 214" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 277.88 214 L 270.88 217.5 L 272.63 214 L 270.88 210.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 246 L 60 246 L 60 306 L 0 306 Z" fill="#ffffff" stroke="none" pointer-events="all"/><path d="M 37.98 291.84 C 37.27 291.84 36.7 292.29 36.7 292.84 L 36.7 294.75 C 36.7 295.31 37.27 295.75 37.98 295.75 L 48.95 295.75 C 49.66 295.75 50.23 295.31 50.23 294.75 L 50.23 292.84 C 50.23 292.29 49.66 291.84 48.95 291.84 Z M 9.51 289.84 L 50.51 289.84 C 51.46 289.84 52.17 290.54 52.17 291.38 L 52.17 296.18 C 52.17 297.01 51.46 297.71 50.51 297.71 L 9.51 297.71 C 8.54 297.71 7.84 297.01 7.84 296.18 L 7.84 291.38 C 7.84 290.54 8.54 289.84 9.51 289.84 Z M 9.51 288.05 C 7.63 288.05 6.05 289.52 6.05 291.38 L 6.05 296.18 C 6.05 298.03 7.63 299.5 9.51 299.5 L 50.51 299.5 C 52.38 299.5 53.96 298.03 53.96 296.18 L 53.96 291.38 C 53.96 289.52 52.38 288.05 50.51 288.05 Z M 11.64 258.14 L 48.34 258.14 L 48.34 280.44 L 11.64 280.44 Z M 10.77 256.35 C 10.77 256.35 10.27 256.5 10.27 256.5 C 10.27 256.5 10.17 256.58 10.13 256.61 C 10.1 256.65 10.07 256.69 10.05 256.71 C 9.96 256.83 9.94 256.9 9.92 256.95 C 9.88 257.05 9.88 257.1 9.87 257.15 C 9.86 257.24 9.85 257.29 9.85 257.37 L 9.85 281.21 C 9.85 281.28 9.86 281.34 9.87 281.43 C 9.88 281.48 9.88 281.52 9.92 281.62 C 9.94 281.67 9.96 281.75 10.05 281.86 C 10.07 281.89 10.1 281.93 10.13 281.96 C 10.17 282 10.27 282.07 10.27 282.07 C 10.27 282.08 10.77 282.23 10.77 282.23 L 49.21 282.23 C 49.22 282.23 49.71 282.07 49.71 282.07 C 49.71 282.07 49.82 282 49.85 281.96 C 49.89 281.93 49.91 281.89 49.94 281.86 C 50.03 281.75 50.04 281.67 50.07 281.62 C 50.11 281.52 50.11 281.48 50.12 281.43 C 50.13 281.34 50.13 281.28 50.13 281.21 L 50.13 257.37 C 50.13 257.29 50.13 257.24 50.12 257.15 C 50.11 257.1 50.11 257.05 50.07 256.95 C 50.04 256.9 50.03 256.83 49.94 256.71 C 49.91 256.69 49.89 256.65 49.85 256.61 C 49.82 256.58 49.71 256.5 49.71 256.5 C 49.71 256.5 49.22 256.35 49.21 256.35 Z M 8.65 254.29 L 51.35 254.29 C 51.81 254.29 52.22 254.69 52.22 255.29 L 52.22 283.24 C 52.22 283.84 51.81 284.23 51.35 284.23 L 8.65 284.23 C 8.2 284.23 7.79 283.84 7.79 283.24 L 7.79 255.29 C 7.79 254.69 8.2 254.29 8.65 254.29 Z M 8.65 252.5 C 7.16 252.5 6 253.79 6 255.29 L 6 283.24 C 6 284.73 7.16 286.02 8.65 286.02 L 51.35 286.02 C 52.84 286.02 54 284.73 54 283.24 L 54 255.29 C 54 253.79 52.84 252.5 51.35 252.5 Z" fill="#232f3e" stroke="none" pointer-events="all"/><g transform="translate(13.5,313.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="32" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(35, 47, 62); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Client</div></div></foreignObject><text x="16" y="12" fill="#232F3E" text-anchor="middle" font-size="12px" font-family="Helvetica">Client</text></switch></g><path d="M 60 72 L 314 72 L 314 173.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 314 178.88 L 310.5 171.88 L 314 173.63 L 317.5 171.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 42 L 60 42 L 60 102 L 0 102 Z" fill="#ffffff" stroke="none" pointer-events="all"/><path d="M 37.98 87.84 C 37.27 87.84 36.7 88.29 36.7 88.84 L 36.7 90.75 C 36.7 91.31 37.27 91.75 37.98 91.75 L 48.95 91.75 C 49.66 91.75 50.23 91.31 50.23 90.75 L 50.23 88.84 C 50.23 88.29 49.66 87.84 48.95 87.84 Z M 9.51 85.84 L 50.51 85.84 C 51.46 85.84 52.17 86.54 52.17 87.38 L 52.17 92.18 C 52.17 93.01 51.46 93.71 50.51 93.71 L 9.51 93.71 C 8.54 93.71 7.84 93.01 7.84 92.18 L 7.84 87.38 C 7.84 86.54 8.54 85.84 9.51 85.84 Z M 9.51 84.05 C 7.63 84.05 6.05 85.52 6.05 87.38 L 6.05 92.18 C 6.05 94.03 7.63 95.5 9.51 95.5 L 50.51 95.5 C 52.38 95.5 53.96 94.03 53.96 92.18 L 53.96 87.38 C 53.96 85.52 52.38 84.05 50.51 84.05 Z M 11.64 54.14 L 48.34 54.14 L 48.34 76.44 L 11.64 76.44 Z M 10.77 52.35 C 10.77 52.35 10.27 52.5 10.27 52.5 C 10.27 52.5 10.17 52.58 10.13 52.61 C 10.1 52.65 10.07 52.69 10.05 52.71 C 9.96 52.83 9.94 52.9 9.92 52.95 C 9.88 53.05 9.88 53.1 9.87 53.15 C 9.86 53.24 9.85 53.29 9.85 53.37 L 9.85 77.21 C 9.85 77.28 9.86 77.34 9.87 77.43 C 9.88 77.48 9.88 77.52 9.92 77.62 C 9.94 77.67 9.96 77.75 10.05 77.86 C 10.07 77.89 10.1 77.93 10.13 77.96 C 10.17 78 10.27 78.07 10.27 78.07 C 10.27 78.08 10.77 78.23 10.77 78.23 L 49.21 78.23 C 49.22 78.23 49.71 78.07 49.71 78.07 C 49.71 78.07 49.82 78 49.85 77.96 C 49.89 77.93 49.91 77.89 49.94 77.86 C 50.03 77.75 50.04 77.67 50.07 77.62 C 50.11 77.52 50.11 77.48 50.12 77.43 C 50.13 77.34 50.13 77.28 50.13 77.21 L 50.13 53.37 C 50.13 53.29 50.13 53.24 50.12 53.15 C 50.11 53.1 50.11 53.05 50.07 52.95 C 50.04 52.9 50.03 52.83 49.94 52.71 C 49.91 52.69 49.89 52.65 49.85 52.61 C 49.82 52.58 49.71 52.5 49.71 52.5 C 49.71 52.5 49.22 52.35 49.21 52.35 Z M 8.65 50.29 L 51.35 50.29 C 51.81 50.29 52.22 50.69 52.22 51.29 L 52.22 79.24 C 52.22 79.84 51.81 80.23 51.35 80.23 L 8.65 80.23 C 8.2 80.23 7.79 79.84 7.79 79.24 L 7.79 51.29 C 7.79 50.69 8.2 50.29 8.65 50.29 Z M 8.65 48.5 C 7.16 48.5 6 49.79 6 51.29 L 6 79.24 C 6 80.73 7.16 82.02 8.65 82.02 L 51.35 82.02 C 52.84 82.02 54 80.73 54 79.24 L 54 51.29 C 54 49.79 52.84 48.5 51.35 48.5 Z" fill="#232f3e" stroke="none" pointer-events="all"/><g transform="translate(13.5,109.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="32" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(35, 47, 62); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Client</div></div></foreignObject><text x="16" y="12" fill="#232F3E" text-anchor="middle" font-size="12px" font-family="Helvetica">Client</text></switch></g><path d="M 60 378 L 314 378 L 314 257.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 314 252.12 L 317.5 259.12 L 314 257.37 L 310.5 259.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 348 L 60 348 L 60 408 L 0 408 Z" fill="#ffffff" stroke="none" pointer-events="all"/><path d="M 37.98 393.84 C 37.27 393.84 36.7 394.29 36.7 394.84 L 36.7 396.75 C 36.7 397.31 37.27 397.75 37.98 397.75 L 48.95 397.75 C 49.66 397.75 50.23 397.31 50.23 396.75 L 50.23 394.84 C 50.23 394.29 49.66 393.84 48.95 393.84 Z M 9.51 391.84 L 50.51 391.84 C 51.46 391.84 52.17 392.54 52.17 393.38 L 52.17 398.18 C 52.17 399.01 51.46 399.71 50.51 399.71 L 9.51 399.71 C 8.54 399.71 7.84 399.01 7.84 398.18 L 7.84 393.38 C 7.84 392.54 8.54 391.84 9.51 391.84 Z M 9.51 390.05 C 7.63 390.05 6.05 391.52 6.05 393.38 L 6.05 398.18 C 6.05 400.03 7.63 401.5 9.51 401.5 L 50.51 401.5 C 52.38 401.5 53.96 400.03 53.96 398.18 L 53.96 393.38 C 53.96 391.52 52.38 390.05 50.51 390.05 Z M 11.64 360.14 L 48.34 360.14 L 48.34 382.44 L 11.64 382.44 Z M 10.77 358.35 C 10.77 358.35 10.27 358.5 10.27 358.5 C 10.27 358.5 10.17 358.58 10.13 358.61 C 10.1 358.65 10.07 358.69 10.05 358.71 C 9.96 358.83 9.94 358.9 9.92 358.95 C 9.88 359.05 9.88 359.1 9.87 359.15 C 9.86 359.24 9.85 359.29 9.85 359.37 L 9.85 383.21 C 9.85 383.28 9.86 383.34 9.87 383.43 C 9.88 383.48 9.88 383.52 9.92 383.62 C 9.94 383.67 9.96 383.75 10.05 383.86 C 10.07 383.89 10.1 383.93 10.13 383.96 C 10.17 384 10.27 384.07 10.27 384.07 C 10.27 384.08 10.77 384.23 10.77 384.23 L 49.21 384.23 C 49.22 384.23 49.71 384.07 49.71 384.07 C 49.71 384.07 49.82 384 49.85 383.96 C 49.89 383.93 49.91 383.89 49.94 383.86 C 50.03 383.75 50.04 383.67 50.07 383.62 C 50.11 383.52 50.11 383.48 50.12 383.43 C 50.13 383.34 50.13 383.28 50.13 383.21 L 50.13 359.37 C 50.13 359.29 50.13 359.24 50.12 359.15 C 50.11 359.1 50.11 359.05 50.07 358.95 C 50.04 358.9 50.03 358.83 49.94 358.71 C 49.91 358.69 49.89 358.65 49.85 358.61 C 49.82 358.58 49.71 358.5 49.71 358.5 C 49.71 358.5 49.22 358.35 49.21 358.35 Z M 8.65 356.29 L 51.35 356.29 C 51.81 356.29 52.22 356.69 52.22 357.29 L 52.22 385.24 C 52.22 385.84 51.81 386.23 51.35 386.23 L 8.65 386.23 C 8.2 386.23 7.79 385.84 7.79 385.24 L 7.79 357.29 C 7.79 356.69 8.2 356.29 8.65 356.29 Z M 8.65 354.5 C 7.16 354.5 6 355.79 6 357.29 L 6 385.24 C 6 386.73 7.16 388.02 8.65 388.02 L 51.35 388.02 C 52.84 388.02 54 386.73 54 385.24 L 54 357.29 C 54 355.79 52.84 354.5 51.35 354.5 Z" fill="#232f3e" stroke="none" pointer-events="all"/><g transform="translate(13.5,415.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="32" height="12" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(35, 47, 62); line-height: 1.2; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">Client</div></div></foreignObject><text x="16" y="12" fill="#232F3E" text-anchor="middle" font-size="12px" font-family="Helvetica">Client</text></switch></g><path d="M 300.57 248 C 298.05 248 295.63 246.61 294.37 244 L 279.55 217.33 C 278.21 215 278.42 212.29 279.55 210.35 L 294.5 183.68 C 295.76 181.25 298.02 180 300.32 180 L 330.33 180 C 332.57 180 334.78 181.13 336.1 183.4 L 350.99 210.06 C 352.79 212.87 352.17 215.87 351.16 217.54 L 336.34 244.04 C 335.35 246.19 333.11 248 330.23 248 Z" fill="#5184f3" stroke="none" pointer-events="all"/><path d="M 327.76 248 L 301.23 220.98 L 305.47 219.2 L 301.15 215.01 L 305.25 213.23 L 301.27 209.15 L 306.99 206.13 L 310.91 199.29 L 315.1 203.89 L 316.48 199.4 L 321.33 204.61 L 322.16 199.33 L 346.92 225.11 L 336.34 244.04 C 335.36 246.19 333.11 248 330.23 248 Z" fill-opacity="0.07" fill="#000000" stroke="none" pointer-events="all"/><rect x="278.21" y="180" width="0" height="0" fill="none" stroke="none" pointer-events="all"/><path d="M 319.51 217.25 C 319.51 217.94 319.35 218.24 318.51 218.2 L 312.21 218.2 C 311.65 218.2 311.27 217.86 311.27 217.26 L 311.27 210.71 C 311.27 210.23 311.49 209.8 312.03 209.8 L 318.77 209.8 C 319.2 209.8 319.51 210.04 319.51 210.45 Z M 323.4 222.24 L 323.4 205.82 L 307.43 205.82 L 307.43 222.24 Z M 311.11 224.93 L 311.11 227.87 C 311.11 228.39 310.81 228.84 310.44 228.84 L 309.19 228.84 C 308.82 228.84 308.5 228.48 308.5 228.07 L 308.5 224.93 L 305.68 224.93 C 305.22 224.93 304.91 224.6 304.91 224.11 L 304.91 221.19 L 301.91 221.19 C 301.44 221.19 301.15 220.88 301.15 220.35 L 301.15 219.33 C 301.15 218.75 301.47 218.49 301.92 218.49 L 304.91 218.49 L 304.91 215.28 L 301.71 215.28 C 301.35 215.28 301.15 214.93 301.15 214.5 L 301.15 213.48 C 301.15 213.03 301.31 212.76 301.74 212.76 L 304.91 212.76 L 304.91 209.49 L 301.88 209.49 C 301.55 209.49 301.15 209.15 301.15 208.72 L 301.15 207.55 C 301.15 207.1 301.36 206.82 301.72 206.82 L 304.91 206.82 L 304.91 203.73 C 304.91 203.36 305.13 203.04 305.54 203.04 L 308.5 203.04 L 308.5 199.89 C 308.5 199.44 308.75 199.16 309.07 199.16 L 310.53 199.16 C 310.91 199.16 311.11 199.4 311.11 199.92 L 311.11 203.04 L 314.23 203.04 L 314.23 199.83 C 314.23 199.4 314.46 199.16 314.94 199.16 L 316.03 199.16 C 316.33 199.16 316.64 199.48 316.64 199.8 L 316.64 203.04 L 319.91 203.04 L 319.91 199.81 C 319.91 199.46 320.23 199.16 320.72 199.16 L 321.76 199.16 C 322.06 199.16 322.35 199.41 322.35 199.77 L 322.35 203.04 L 325.34 203.04 C 325.97 203.04 326.1 203.49 326.1 203.98 L 326.1 206.82 L 328.94 206.82 C 329.49 206.82 329.85 207.21 329.85 207.69 L 329.85 208.92 C 329.85 209.19 329.6 209.49 329.2 209.49 L 326.1 209.49 L 326.1 212.76 L 329.34 212.76 C 329.72 212.76 329.85 213.02 329.85 213.33 L 329.85 214.55 C 329.85 214.96 329.66 215.28 329.23 215.28 L 326.1 215.28 L 326.1 218.49 L 328.88 218.49 C 329.5 218.49 329.85 218.72 329.85 219.29 L 329.85 220.56 C 329.85 220.84 329.59 221.19 329.24 221.19 L 326.1 221.19 L 326.1 223.85 C 326.1 224.52 325.81 224.93 324.96 224.93 L 322.35 224.93 L 322.35 227.87 C 322.35 228.44 322.14 228.84 321.55 228.84 L 320.37 228.84 C 320.09 228.84 319.92 228.56 319.91 228.21 L 319.91 224.93 L 316.64 224.93 L 316.64 228.07 C 316.64 228.42 316.49 228.84 315.97 228.84 L 314.71 228.84 C 314.41 228.84 314.23 228.41 314.23 228.07 L 314.23 224.93 Z" fill="#ffffff" stroke="none" pointer-events="all"/><g transform="translate(249.5,264.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="132" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(153, 153, 153); line-height: 1.2; vertical-align: top; white-space: nowrap; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><font style="font-size: 20px">WEB PORTAL</font></div></div></foreignObject><text x="66" y="17" fill="#999999" text-anchor="middle" font-size="11px" font-family="Helvetica" font-weight="bold">&lt;font style="font-size: 20px"&gt;WEB PORTAL&lt;/font&gt;</text></switch></g><path d="M 510.57 412 C 508.05 412 505.63 410.61 504.37 408 L 489.55 381.33 C 488.21 379 488.42 376.29 489.55 374.35 L 504.5 347.68 C 505.76 345.25 508.02 344 510.32 344 L 540.33 344 C 542.57 344 544.78 345.13 546.1 347.4 L 560.99 374.06 C 562.79 376.87 562.17 379.87 561.16 381.54 L 546.34 408.04 C 545.35 410.19 543.11 412 540.23 412 Z" fill="#5184f3" stroke="none" pointer-events="all"/><path d="M 537.76 412 L 511.23 384.98 L 515.47 383.2 L 511.15 379.01 L 515.25 377.23 L 511.27 373.15 L 516.99 370.13 L 520.91 363.29 L 525.1 367.89 L 526.48 363.4 L 531.33 368.61 L 532.16 363.33 L 556.92 389.11 L 546.34 408.04 C 545.36 410.19 543.11 412 540.23 412 Z" fill-opacity="0.07" fill="#000000" stroke="none" pointer-events="all"/><rect x="488.21" y="344" width="0" height="0" fill="none" stroke="none" pointer-events="all"/><path d="M 529.51 381.25 C 529.51 381.94 529.35 382.24 528.51 382.2 L 522.21 382.2 C 521.65 382.2 521.27 381.86 521.27 381.26 L 521.27 374.71 C 521.27 374.23 521.49 373.8 522.03 373.8 L 528.77 373.8 C 529.2 373.8 529.51 374.04 529.51 374.45 Z M 533.4 386.24 L 533.4 369.82 L 517.43 369.82 L 517.43 386.24 Z M 521.11 388.93 L 521.11 391.87 C 521.11 392.39 520.81 392.84 520.44 392.84 L 519.19 392.84 C 518.82 392.84 518.5 392.48 518.5 392.07 L 518.5 388.93 L 515.68 388.93 C 515.22 388.93 514.91 388.6 514.91 388.11 L 514.91 385.19 L 511.91 385.19 C 511.44 385.19 511.15 384.88 511.15 384.35 L 511.15 383.33 C 511.15 382.75 511.47 382.49 511.92 382.49 L 514.91 382.49 L 514.91 379.28 L 511.71 379.28 C 511.35 379.28 511.15 378.93 511.15 378.5 L 511.15 377.48 C 511.15 377.03 511.31 376.76 511.74 376.76 L 514.91 376.76 L 514.91 373.49 L 511.88 373.49 C 511.55 373.49 511.15 373.15 511.15 372.72 L 511.15 371.55 C 511.15 371.1 511.36 370.82 511.72 370.82 L 514.91 370.82 L 514.91 367.73 C 514.91 367.36 515.13 367.04 515.54 367.04 L 518.5 367.04 L 518.5 363.89 C 518.5 363.44 518.75 363.16 519.07 363.16 L 520.53 363.16 C 520.91 363.16 521.11 363.4 521.11 363.92 L 521.11 367.04 L 524.23 367.04 L 524.23 363.83 C 524.23 363.4 524.46 363.16 524.94 363.16 L 526.03 363.16 C 526.33 363.16 526.64 363.48 526.64 363.8 L 526.64 367.04 L 529.91 367.04 L 529.91 363.81 C 529.91 363.46 530.23 363.16 530.72 363.16 L 531.76 363.16 C 532.06 363.16 532.35 363.41 532.35 363.77 L 532.35 367.04 L 535.34 367.04 C 535.97 367.04 536.1 367.49 536.1 367.98 L 536.1 370.82 L 538.94 370.82 C 539.49 370.82 539.85 371.21 539.85 371.69 L 539.85 372.92 C 539.85 373.19 539.6 373.49 539.2 373.49 L 536.1 373.49 L 536.1 376.76 L 539.34 376.76 C 539.72 376.76 539.85 377.02 539.85 377.33 L 539.85 378.55 C 539.85 378.96 539.66 379.28 539.23 379.28 L 536.1 379.28 L 536.1 382.49 L 538.88 382.49 C 539.5 382.49 539.85 382.72 539.85 383.29 L 539.85 384.56 C 539.85 384.84 539.59 385.19 539.24 385.19 L 536.1 385.19 L 536.1 387.85 C 536.1 388.52 535.81 388.93 534.96 388.93 L 532.35 388.93 L 532.35 391.87 C 532.35 392.44 532.14 392.84 531.55 392.84 L 530.37 392.84 C 530.09 392.84 529.92 392.56 529.91 392.21 L 529.91 388.93 L 526.64 388.93 L 526.64 392.07 C 526.64 392.42 526.49 392.84 525.97 392.84 L 524.71 392.84 C 524.41 392.84 524.23 392.41 524.23 392.07 L 524.23 388.93 Z" fill="#ffffff" stroke="none" pointer-events="all"/><g transform="translate(469.5,428.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="112" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(153, 153, 153); line-height: 1.2; vertical-align: top; white-space: nowrap; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><font style="font-size: 20px">DOCSTORE</font></div></div></foreignObject><text x="56" y="17" fill="#999999" text-anchor="middle" font-size="11px" font-family="Helvetica" font-weight="bold">&lt;font style="font-size: 20px"&gt;DOCSTORE&lt;/font&gt;</text></switch></g><path d="M 510.57 84 C 508.05 84 505.63 82.61 504.37 80 L 489.55 53.33 C 488.21 51 488.42 48.29 489.55 46.35 L 504.5 19.68 C 505.76 17.25 508.02 16 510.32 16 L 540.33 16 C 542.57 16 544.78 17.13 546.1 19.4 L 560.99 46.06 C 562.79 48.87 562.17 51.87 561.16 53.54 L 546.34 80.04 C 545.35 82.19 543.11 84 540.23 84 Z" fill="#5184f3" stroke="none" pointer-events="all"/><path d="M 537.76 84 L 511.23 56.98 L 515.47 55.2 L 511.15 51.01 L 515.25 49.23 L 511.27 45.15 L 516.99 42.13 L 520.91 35.29 L 525.1 39.89 L 526.48 35.4 L 531.33 40.61 L 532.16 35.33 L 556.92 61.11 L 546.34 80.04 C 545.36 82.19 543.11 84 540.23 84 Z" fill-opacity="0.07" fill="#000000" stroke="none" pointer-events="all"/><rect x="488.21" y="16" width="0" height="0" fill="none" stroke="none" pointer-events="all"/><path d="M 529.51 53.25 C 529.51 53.94 529.35 54.24 528.51 54.2 L 522.21 54.2 C 521.65 54.2 521.27 53.86 521.27 53.26 L 521.27 46.71 C 521.27 46.23 521.49 45.8 522.03 45.8 L 528.77 45.8 C 529.2 45.8 529.51 46.04 529.51 46.45 Z M 533.4 58.24 L 533.4 41.82 L 517.43 41.82 L 517.43 58.24 Z M 521.11 60.93 L 521.11 63.87 C 521.11 64.39 520.81 64.84 520.44 64.84 L 519.19 64.84 C 518.82 64.84 518.5 64.48 518.5 64.07 L 518.5 60.93 L 515.68 60.93 C 515.22 60.93 514.91 60.6 514.91 60.11 L 514.91 57.19 L 511.91 57.19 C 511.44 57.19 511.15 56.88 511.15 56.35 L 511.15 55.33 C 511.15 54.75 511.47 54.49 511.92 54.49 L 514.91 54.49 L 514.91 51.28 L 511.71 51.28 C 511.35 51.28 511.15 50.93 511.15 50.5 L 511.15 49.48 C 511.15 49.03 511.31 48.76 511.74 48.76 L 514.91 48.76 L 514.91 45.49 L 511.88 45.49 C 511.55 45.49 511.15 45.15 511.15 44.72 L 511.15 43.55 C 511.15 43.1 511.36 42.82 511.72 42.82 L 514.91 42.82 L 514.91 39.73 C 514.91 39.36 515.13 39.04 515.54 39.04 L 518.5 39.04 L 518.5 35.89 C 518.5 35.44 518.75 35.16 519.07 35.16 L 520.53 35.16 C 520.91 35.16 521.11 35.4 521.11 35.92 L 521.11 39.04 L 524.23 39.04 L 524.23 35.83 C 524.23 35.4 524.46 35.16 524.94 35.16 L 526.03 35.16 C 526.33 35.16 526.64 35.48 526.64 35.8 L 526.64 39.04 L 529.91 39.04 L 529.91 35.81 C 529.91 35.46 530.23 35.16 530.72 35.16 L 531.76 35.16 C 532.06 35.16 532.35 35.41 532.35 35.77 L 532.35 39.04 L 535.34 39.04 C 535.97 39.04 536.1 39.49 536.1 39.98 L 536.1 42.82 L 538.94 42.82 C 539.49 42.82 539.85 43.21 539.85 43.69 L 539.85 44.92 C 539.85 45.19 539.6 45.49 539.2 45.49 L 536.1 45.49 L 536.1 48.76 L 539.34 48.76 C 539.72 48.76 539.85 49.02 539.85 49.33 L 539.85 50.55 C 539.85 50.96 539.66 51.28 539.23 51.28 L 536.1 51.28 L 536.1 54.49 L 538.88 54.49 C 539.5 54.49 539.85 54.72 539.85 55.29 L 539.85 56.56 C 539.85 56.84 539.59 57.19 539.24 57.19 L 536.1 57.19 L 536.1 59.85 C 536.1 60.52 535.81 60.93 534.96 60.93 L 532.35 60.93 L 532.35 63.87 C 532.35 64.44 532.14 64.84 531.55 64.84 L 530.37 64.84 C 530.09 64.84 529.92 64.56 529.91 64.21 L 529.91 60.93 L 526.64 60.93 L 526.64 64.07 C 526.64 64.42 526.49 64.84 525.97 64.84 L 524.71 64.84 C 524.41 64.84 524.23 64.41 524.23 64.07 L 524.23 60.93 Z" fill="#ffffff" stroke="none" pointer-events="all"/><g transform="translate(469.5,100.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="111" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(153, 153, 153); line-height: 1.2; vertical-align: top; white-space: nowrap; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><font style="font-size: 20px">FILESTORE</font></div></div></foreignObject><text x="56" y="17" fill="#999999" text-anchor="middle" font-size="11px" font-family="Helvetica" font-weight="bold">&lt;font style="font-size: 20px"&gt;FILESTORE&lt;/font&gt;</text></switch></g><path d="M 352 214 L 399 214 L 399 378 L 480.76 378" fill="none" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 486.76 378 L 480.76 380 L 480.76 376 Z" fill="#4284f3" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 352 214 L 399 214 L 399 50 L 480.76 50" fill="none" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 486.76 50 L 480.76 52 L 480.76 48 Z" fill="#4284f3" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 510.57 248 C 508.05 248 505.63 246.61 504.37 244 L 489.55 217.33 C 488.21 215 488.42 212.29 489.55 210.35 L 504.5 183.68 C 505.76 181.25 508.02 180 510.32 180 L 540.33 180 C 542.57 180 544.78 181.13 546.1 183.4 L 560.99 210.06 C 562.79 212.87 562.17 215.87 561.16 217.54 L 546.34 244.04 C 545.35 246.19 543.11 248 540.23 248 Z" fill="#5184f3" stroke="none" pointer-events="all"/><path d="M 537.76 248 L 511.23 220.98 L 515.47 219.2 L 511.15 215.01 L 515.25 213.23 L 511.27 209.15 L 516.99 206.13 L 520.91 199.29 L 525.1 203.89 L 526.48 199.4 L 531.33 204.61 L 532.16 199.33 L 556.92 225.11 L 546.34 244.04 C 545.36 246.19 543.11 248 540.23 248 Z" fill-opacity="0.07" fill="#000000" stroke="none" pointer-events="all"/><rect x="488.21" y="180" width="0" height="0" fill="none" stroke="none" pointer-events="all"/><path d="M 529.51 217.25 C 529.51 217.94 529.35 218.24 528.51 218.2 L 522.21 218.2 C 521.65 218.2 521.27 217.86 521.27 217.26 L 521.27 210.71 C 521.27 210.23 521.49 209.8 522.03 209.8 L 528.77 209.8 C 529.2 209.8 529.51 210.04 529.51 210.45 Z M 533.4 222.24 L 533.4 205.82 L 517.43 205.82 L 517.43 222.24 Z M 521.11 224.93 L 521.11 227.87 C 521.11 228.39 520.81 228.84 520.44 228.84 L 519.19 228.84 C 518.82 228.84 518.5 228.48 518.5 228.07 L 518.5 224.93 L 515.68 224.93 C 515.22 224.93 514.91 224.6 514.91 224.11 L 514.91 221.19 L 511.91 221.19 C 511.44 221.19 511.15 220.88 511.15 220.35 L 511.15 219.33 C 511.15 218.75 511.47 218.49 511.92 218.49 L 514.91 218.49 L 514.91 215.28 L 511.71 215.28 C 511.35 215.28 511.15 214.93 511.15 214.5 L 511.15 213.48 C 511.15 213.03 511.31 212.76 511.74 212.76 L 514.91 212.76 L 514.91 209.49 L 511.88 209.49 C 511.55 209.49 511.15 209.15 511.15 208.72 L 511.15 207.55 C 511.15 207.1 511.36 206.82 511.72 206.82 L 514.91 206.82 L 514.91 203.73 C 514.91 203.36 515.13 203.04 515.54 203.04 L 518.5 203.04 L 518.5 199.89 C 518.5 199.44 518.75 199.16 519.07 199.16 L 520.53 199.16 C 520.91 199.16 521.11 199.4 521.11 199.92 L 521.11 203.04 L 524.23 203.04 L 524.23 199.83 C 524.23 199.4 524.46 199.16 524.94 199.16 L 526.03 199.16 C 526.33 199.16 526.64 199.48 526.64 199.8 L 526.64 203.04 L 529.91 203.04 L 529.91 199.81 C 529.91 199.46 530.23 199.16 530.72 199.16 L 531.76 199.16 C 532.06 199.16 532.35 199.41 532.35 199.77 L 532.35 203.04 L 535.34 203.04 C 535.97 203.04 536.1 203.49 536.1 203.98 L 536.1 206.82 L 538.94 206.82 C 539.49 206.82 539.85 207.21 539.85 207.69 L 539.85 208.92 C 539.85 209.19 539.6 209.49 539.2 209.49 L 536.1 209.49 L 536.1 212.76 L 539.34 212.76 C 539.72 212.76 539.85 213.02 539.85 213.33 L 539.85 214.55 C 539.85 214.96 539.66 215.28 539.23 215.28 L 536.1 215.28 L 536.1 218.49 L 538.88 218.49 C 539.5 218.49 539.85 218.72 539.85 219.29 L 539.85 220.56 C 539.85 220.84 539.59 221.19 539.24 221.19 L 536.1 221.19 L 536.1 223.85 C 536.1 224.52 535.81 224.93 534.96 224.93 L 532.35 224.93 L 532.35 227.87 C 532.35 228.44 532.14 228.84 531.55 228.84 L 530.37 228.84 C 530.09 228.84 529.92 228.56 529.91 228.21 L 529.91 224.93 L 526.64 224.93 L 526.64 228.07 C 526.64 228.42 526.49 228.84 525.97 228.84 L 524.71 228.84 C 524.41 228.84 524.23 228.41 524.23 228.07 L 524.23 224.93 Z" fill="#ffffff" stroke="none" pointer-events="all"/><g transform="translate(455.5,264.5)"><switch><foreignObject style="overflow:visible;" pointer-events="all" width="139" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 11px; font-family: Helvetica; color: rgb(153, 153, 153); line-height: 1.2; vertical-align: top; white-space: nowrap; font-weight: bold; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><font style="font-size: 20px">COMPILATION</font></div></div></foreignObject><text x="70" y="17" fill="#999999" text-anchor="middle" font-size="11px" font-family="Helvetica" font-weight="bold">&lt;font style="font-size: 20px"&gt;COMPILATION&lt;/font&gt;</text></switch></g><path d="M 526 84 L 526 171.76" fill="none" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 526 177.76 L 524 171.76 L 528 171.76 Z" fill="#4284f3" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 526 256.24 L 526 344" fill="none" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 526 250.24 L 528 256.24 L 524 256.24 Z" fill="#4284f3" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/><path d="M 352 214 L 480.76 214" fill="none" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 486.76 214 L 480.76 216 L 480.76 212 Z" fill="#4284f3" stroke="#4284f3" stroke-width="2" stroke-miterlimit="10" pointer-events="all"/></g></svg>
\ No newline at end of file
diff --git a/tuto2/index.html b/tuto2/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..daed5641157b88a5364aa4f48bca9bc3ef1a9364
--- /dev/null
+++ b/tuto2/index.html
@@ -0,0 +1,444 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
+<head>
+<!-- 2019-11-29 ven. 00:21 -->
+<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1" />
+<title>Distributed experiments on Grid'5000 &#x2026; and beyond !</title>
+<meta name="generator" content="Org mode" />
+<meta name="author" content="Matthieu Simonin" />
+<style type="text/css">
+ <!--/*--><![CDATA[/*><!--*/
+  .title  { text-align: center;
+             margin-bottom: .2em; }
+  .subtitle { text-align: center;
+              font-size: medium;
+              font-weight: bold;
+              margin-top:0; }
+  .todo   { font-family: monospace; color: red; }
+  .done   { font-family: monospace; color: green; }
+  .priority { font-family: monospace; color: orange; }
+  .tag    { background-color: #eee; font-family: monospace;
+            padding: 2px; font-size: 80%; font-weight: normal; }
+  .timestamp { color: #bebebe; }
+  .timestamp-kwd { color: #5f9ea0; }
+  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
+  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
+  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
+  .underline { text-decoration: underline; }
+  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
+  p.verse { margin-left: 3%; }
+  pre {
+    border: 1px solid #ccc;
+    box-shadow: 3px 3px 3px #eee;
+    padding: 8pt;
+    font-family: monospace;
+    overflow: auto;
+    margin: 1.2em;
+  }
+  pre.src {
+    position: relative;
+    overflow: visible;
+    padding-top: 1.2em;
+  }
+  pre.src:before {
+    display: none;
+    position: absolute;
+    background-color: white;
+    top: -10px;
+    right: 10px;
+    padding: 3px;
+    border: 1px solid black;
+  }
+  pre.src:hover:before { display: inline;}
+  /* Languages per Org manual */
+  pre.src-asymptote:before { content: 'Asymptote'; }
+  pre.src-awk:before { content: 'Awk'; }
+  pre.src-C:before { content: 'C'; }
+  /* pre.src-C++ doesn't work in CSS */
+  pre.src-clojure:before { content: 'Clojure'; }
+  pre.src-css:before { content: 'CSS'; }
+  pre.src-D:before { content: 'D'; }
+  pre.src-ditaa:before { content: 'ditaa'; }
+  pre.src-dot:before { content: 'Graphviz'; }
+  pre.src-calc:before { content: 'Emacs Calc'; }
+  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
+  pre.src-fortran:before { content: 'Fortran'; }
+  pre.src-gnuplot:before { content: 'gnuplot'; }
+  pre.src-haskell:before { content: 'Haskell'; }
+  pre.src-hledger:before { content: 'hledger'; }
+  pre.src-java:before { content: 'Java'; }
+  pre.src-js:before { content: 'Javascript'; }
+  pre.src-latex:before { content: 'LaTeX'; }
+  pre.src-ledger:before { content: 'Ledger'; }
+  pre.src-lisp:before { content: 'Lisp'; }
+  pre.src-lilypond:before { content: 'Lilypond'; }
+  pre.src-lua:before { content: 'Lua'; }
+  pre.src-matlab:before { content: 'MATLAB'; }
+  pre.src-mscgen:before { content: 'Mscgen'; }
+  pre.src-ocaml:before { content: 'Objective Caml'; }
+  pre.src-octave:before { content: 'Octave'; }
+  pre.src-org:before { content: 'Org mode'; }
+  pre.src-oz:before { content: 'OZ'; }
+  pre.src-plantuml:before { content: 'Plantuml'; }
+  pre.src-processing:before { content: 'Processing.js'; }
+  pre.src-python:before { content: 'Python'; }
+  pre.src-R:before { content: 'R'; }
+  pre.src-ruby:before { content: 'Ruby'; }
+  pre.src-sass:before { content: 'Sass'; }
+  pre.src-scheme:before { content: 'Scheme'; }
+  pre.src-screen:before { content: 'Gnu Screen'; }
+  pre.src-sed:before { content: 'Sed'; }
+  pre.src-sh:before { content: 'shell'; }
+  pre.src-sql:before { content: 'SQL'; }
+  pre.src-sqlite:before { content: 'SQLite'; }
+  /* additional languages in org.el's org-babel-load-languages alist */
+  pre.src-forth:before { content: 'Forth'; }
+  pre.src-io:before { content: 'IO'; }
+  pre.src-J:before { content: 'J'; }
+  pre.src-makefile:before { content: 'Makefile'; }
+  pre.src-maxima:before { content: 'Maxima'; }
+  pre.src-perl:before { content: 'Perl'; }
+  pre.src-picolisp:before { content: 'Pico Lisp'; }
+  pre.src-scala:before { content: 'Scala'; }
+  pre.src-shell:before { content: 'Shell Script'; }
+  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
+  /* additional language identifiers per "defun org-babel-execute"
+       in ob-*.el */
+  pre.src-cpp:before  { content: 'C++'; }
+  pre.src-abc:before  { content: 'ABC'; }
+  pre.src-coq:before  { content: 'Coq'; }
+  pre.src-groovy:before  { content: 'Groovy'; }
+  /* additional language identifiers from org-babel-shell-names in
+     ob-shell.el: ob-shell is the only babel language using a lambda to put
+     the execution function name together. */
+  pre.src-bash:before  { content: 'bash'; }
+  pre.src-csh:before  { content: 'csh'; }
+  pre.src-ash:before  { content: 'ash'; }
+  pre.src-dash:before  { content: 'dash'; }
+  pre.src-ksh:before  { content: 'ksh'; }
+  pre.src-mksh:before  { content: 'mksh'; }
+  pre.src-posh:before  { content: 'posh'; }
+  /* Additional Emacs modes also supported by the LaTeX listings package */
+  pre.src-ada:before { content: 'Ada'; }
+  pre.src-asm:before { content: 'Assembler'; }
+  pre.src-caml:before { content: 'Caml'; }
+  pre.src-delphi:before { content: 'Delphi'; }
+  pre.src-html:before { content: 'HTML'; }
+  pre.src-idl:before { content: 'IDL'; }
+  pre.src-mercury:before { content: 'Mercury'; }
+  pre.src-metapost:before { content: 'MetaPost'; }
+  pre.src-modula-2:before { content: 'Modula-2'; }
+  pre.src-pascal:before { content: 'Pascal'; }
+  pre.src-ps:before { content: 'PostScript'; }
+  pre.src-prolog:before { content: 'Prolog'; }
+  pre.src-simula:before { content: 'Simula'; }
+  pre.src-tcl:before { content: 'tcl'; }
+  pre.src-tex:before { content: 'TeX'; }
+  pre.src-plain-tex:before { content: 'Plain TeX'; }
+  pre.src-verilog:before { content: 'Verilog'; }
+  pre.src-vhdl:before { content: 'VHDL'; }
+  pre.src-xml:before { content: 'XML'; }
+  pre.src-nxml:before { content: 'XML'; }
+  /* add a generic configuration mode; LaTeX export needs an additional
+     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
+  pre.src-conf:before { content: 'Configuration File'; }
+
+  table { border-collapse:collapse; }
+  caption.t-above { caption-side: top; }
+  caption.t-bottom { caption-side: bottom; }
+  td, th { vertical-align:top;  }
+  th.org-right  { text-align: center;  }
+  th.org-left   { text-align: center;   }
+  th.org-center { text-align: center; }
+  td.org-right  { text-align: right;  }
+  td.org-left   { text-align: left;   }
+  td.org-center { text-align: center; }
+  dt { font-weight: bold; }
+  .footpara { display: inline; }
+  .footdef  { margin-bottom: 1em; }
+  .figure { padding: 1em; }
+  .figure p { text-align: center; }
+  .inlinetask {
+    padding: 10px;
+    border: 2px solid gray;
+    margin: 10px;
+    background: #ffffcc;
+  }
+  #org-div-home-and-up
+   { text-align: right; font-size: 70%; white-space: nowrap; }
+  textarea { overflow-x: auto; }
+  .linenr { font-size: smaller }
+  .code-highlighted { background-color: #ffff00; }
+  .org-info-js_info-navigation { border-style: none; }
+  #org-info-js_console-label
+    { font-size: 10px; font-weight: bold; white-space: nowrap; }
+  .org-info-js_search-highlight
+    { background-color: #ffff00; color: #000000; font-weight: bold; }
+  .org-svg { width: 90%; }
+  /*]]>*/-->
+</style>
+<link rel="stylesheet" type="text/css" href="timeline.css" />
+<script type="text/javascript">
+/*
+@licstart  The following is the entire license notice for the
+JavaScript code in this tag.
+
+Copyright (C) 2012-2018 Free Software Foundation, Inc.
+
+The JavaScript code in this tag is free software: you can
+redistribute it and/or modify it under the terms of the GNU
+General Public License (GNU GPL) as published by the Free Software
+Foundation, either version 3 of the License, or (at your option)
+any later version.  The code is distributed WITHOUT ANY WARRANTY;
+without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.
+
+As additional permission under GNU GPL version 3 section 7, you
+may distribute non-source (e.g., minimized or compacted) forms of
+that code without the copy of the GNU GPL normally required by
+section 4, provided you include this license notice and a URL
+through which recipients can access the Corresponding Source.
+
+
+@licend  The above is the entire license notice
+for the JavaScript code in this tag.
+*/
+<!--/*--><![CDATA[/*><!--*/
+ function CodeHighlightOn(elem, id)
+ {
+   var target = document.getElementById(id);
+   if(null != target) {
+     elem.cacheClassElem = elem.className;
+     elem.cacheClassTarget = target.className;
+     target.className = "code-highlighted";
+     elem.className   = "code-highlighted";
+   }
+ }
+ function CodeHighlightOff(elem, id)
+ {
+   var target = document.getElementById(id);
+   if(elem.cacheClassElem)
+     elem.className = elem.cacheClassElem;
+   if(elem.cacheClassTarget)
+     target.className = elem.cacheClassTarget;
+ }
+/*]]>*///-->
+</script>
+</head>
+<body>
+<div id="content">
+<h1 class="title">Distributed experiments on Grid'5000 &#x2026; and beyond !</h1>
+<div id="table-of-contents">
+<h2>Table of Contents</h2>
+<div id="text-table-of-contents">
+<ul>
+<li><a href="#orgc38ce74">1. Benchmarking a real application</a></li>
+<li><a href="#org3f66fb1">2. Before you start</a>
+<ul>
+<li><a href="#orga16f997">2.1. Grid'5000 stuffs</a></li>
+<li><a href="#orgfd9377b">2.2. Setup on Grid'5000</a></li>
+</ul>
+</li>
+<li><a href="#orgc0bc76f">3. Deployment time !</a>
+<ul>
+<li><a href="#org1df303b">3.1. Deploy it</a></li>
+<li><a href="#org8a7d969">3.2. Access it</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+
+
+<div id="outline-container-orgc38ce74" class="outline-2">
+<h2 id="orgc38ce74"><span class="section-number-2">1</span> Benchmarking a real application</h2>
+<div class="outline-text-2" id="text-1">
+<p>
+In this tutorial we'll cover some aspects of evaluating the performance of a
+real application. We'll work with <code>overleaf</code>. <code>overleaf</code> is a collaborative
+text editor that uses Latex to produce pdf files. Figure <a href="#org3218667">1</a>
+is an overview of the editing part of the software.
+</p>
+
+
+<div id="org3218667" class="figure">
+<p><a href="./figs/overleaf-v2-editor.png"><img src="./figs/overleaf-v2-editor.png" alt="overleaf-v2-editor.png" /></a>
+</p>
+<p><span class="figure-number">Figure 1: </span>Overview of <code>overleaf</code> editor: on the left users can collaboratively edit the document. On the right the document is rendered.</p>
+</div>
+
+
+<p>
+Here is the plan:
+</p>
+
+<ul class="org-ul">
+<li><b><b>Deployment</b></b> You'll first deploy our own <code>overleaf</code> instance (we don't want to use
+the official/commercial instance).</li>
+<li><b><b>Load generation</b></b> You'll generate compilation of different projects programatically.</li>
+<li><b><b>Observation</b></b> You'll observe the effect of the load in the running system through various metrics.</li>
+<li><b><b>Feedback</b></b> You'll formulate some hypothesis on the load characteristics and the observed effects on the system.</li>
+</ul>
+</div>
+</div>
+
+<div id="outline-container-org3f66fb1" class="outline-2">
+<h2 id="org3f66fb1"><span class="section-number-2">2</span> Before you start</h2>
+<div class="outline-text-2" id="text-2">
+<p>
+Make sure you are ok with the following.
+</p>
+</div>
+
+<div id="outline-container-orga16f997" class="outline-3">
+<h3 id="orga16f997"><span class="section-number-3">2.1</span> Grid'5000 stuffs</h3>
+<div class="outline-text-3" id="text-2-1">
+<div class="note">
+<p>
+Make sure you are familiar with the Grid'5000 architecture. see section 1 &amp; 2 of
+<a href="https://www.grid5000.fr/w/Getting_Started">https://www.grid5000.fr/w/Getting_Started</a>. note that we won't do this tutorial
+we'll prefer to use higher level tools for now.
+</p>
+
+</div>
+</div>
+</div>
+
+
+<div id="outline-container-orgfd9377b" class="outline-3">
+<h3 id="orgfd9377b"><span class="section-number-3">2.2</span> Setup on Grid'5000</h3>
+<div class="outline-text-3" id="text-2-2">
+<p>
+Connect to a Grid'5000 frontend of your choice (e.g rennes, nancy &#x2026;)
+</p>
+
+<ul class="org-ul">
+<li>create a new directory to host all the scripts of the session</li>
+<li>bootstrap a new python3 virtualenv</li>
+<li>install EnOSlib and configure the access to the API</li>
+</ul>
+
+<div class="org-src-container">
+<pre class="src src-bash">$<span style="color: #7590db;">frontend</span>: cp -r ~msimonin/public/ccs-g5k-tuto2 .
+$<span style="color: #7590db;">frontend</span>: cd ccs-g5k-tuto2
+$<span style="color: #7590db;">frontend</span>: virtualenv --python=python3 venv
+$<span style="color: #7590db;">frontend</span>: source venv/bin/activate
+$<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: pip install -r requirements.txt
+$<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: echo <span style="color: #2d9574;">'</span>
+<span style="color: #2d9574;">verify_ssl: False</span>
+<span style="color: #2d9574;">'</span> &gt; ~/.python-grid5000.yaml
+</pre>
+</div>
+</div>
+</div>
+</div>
+
+<div id="outline-container-orgc0bc76f" class="outline-2">
+<h2 id="orgc0bc76f"><span class="section-number-2">3</span> Deployment time !</h2>
+<div class="outline-text-2" id="text-3">
+<p>
+Figure <a href="#org4b6858a">2</a> represents a simplified view of what we'll deploy. In blue
+some services of <code>overleaf</code> are represented. First the Web portal is the entry
+point to all the user requests. The three other services in the picture are
+involved when compiling a document. The compilation service interacts with the
+filestore (where the files of the image of the projects are stored) and the
+docstore (where the text of the project is stored). There are other service
+involved to provide the chat feature, history feature, real-time interaction
+&#x2026; but we'll focus ony on the compilation process.
+</p>
+
+
+<div id="org4b6858a" class="figure">
+<p><a href="./figs/simple_compilation.png"><object type="image/svg+xml" data="./figs/simple_compilation.svg" class="org-svg">
+Sorry, your browser does not support SVG.</object></a>
+</p>
+<p><span class="figure-number">Figure 2: </span>Simplified architecture of the system under study (blue) and the generated users (black). Overleaf is composed of a dozen services ony four are represented here.</p>
+</div>
+
+<div class="note">
+<p>
+After the deployment you'll be able to:
+</p>
+<ul class="org-ul">
+<li>access the web portal and play with your own overleaf instance</li>
+<li>access the web portal of your friends and collaborate on a document 
+(that's not the main objective of the tutorial but that's fun)</li>
+</ul>
+
+</div>
+</div>
+
+<div id="outline-container-org1df303b" class="outline-3">
+<h3 id="org1df303b"><span class="section-number-3">3.1</span> Deploy it</h3>
+<div class="outline-text-3" id="text-3-1">
+<div class="org-src-container">
+<pre class="src src-bash">$<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: python overleaf.py deploy --cluster=paravance
+</pre>
+</div>
+
+<div class="note">
+<ul class="org-ul">
+<li>You can change the cluster name with any cluster on Grid'5000: see <a href="https://www.grid5000.fr/w/Hardware">https://www.grid5000.fr/w/Hardware</a></li>
+<li>This can take several minutes&#x2026;</li>
+</ul>
+
+</div>
+</div>
+</div>
+
+<div id="outline-container-org8a7d969" class="outline-3">
+<h3 id="org8a7d969"><span class="section-number-3">3.2</span> Access it</h3>
+<div class="outline-text-3" id="text-3-2">
+<p>
+To know where your services is installed you can run: 
+</p>
+
+<div class="org-src-container">
+<pre class="src src-bash">  $<span style="color: #7590db;">frontend</span><span style="color: #4f97d7;">(</span>venv<span style="color: #4f97d7;">)</span>: python overleaf.py describe
+
+  <span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Possible outputp</span>
+&#9554;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9572;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9572;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9557;
+&#9474; Name                 &#9474; Address    &#9474; Port   &#9474;
+&#9566;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9578;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9578;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9569;
+&#9474; Web portal           &#9474; <span style="color: #a45bad;">10.144.0.2</span> &#9474; <span style="color: #a45bad;">3000</span>   &#9474;
+&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
+&#9474; Monitoring portal    &#9474; <span style="color: #a45bad;">10.144.0.2</span> &#9474; <span style="color: #a45bad;">2000</span>   &#9474;
+&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
+&#9474; Benchmark portal     &#9474; <span style="color: #a45bad;">10.144.0.3</span> &#9474; <span style="color: #a45bad;">8089</span>   &#9474;
+&#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9532;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
+&#9474; Compilation machines &#9474; <span style="color: #a45bad;">10.144.0.4</span> &#9474; -      &#9474;
+&#9560;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9575;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9575;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9552;&#9563;
+</pre>
+</div>
+
+<div class="note">
+<p>
+To access the web portal you can create a tunnel from your local machine to
+the machine running the web portal as follows
+</p>
+
+<div class="org-src-container">
+<pre class="src src-bash"><span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Adapt the node names with the node where the portal has been installed</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">Replace &lt;login&gt; by your Grid'5000 login</span>
+$<span style="color: #7590db;">yourmachine</span>: ssh -NL <span style="color: #a45bad;">3000:10.144.0.2:3000</span> &lt;login&gt;@access.grid5000.fr
+
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">point your browser to localhost:3000</span>
+<span style="color: #2aa1ae; background-color: #292e34;"># </span><span style="color: #2aa1ae; background-color: #292e34;">username/mdp: toto@toto.com / toto4242</span>
+</pre>
+</div>
+
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="postamble" class="status">
+<p class="author">Author: Matthieu Simonin</p>
+<p class="date">Created: 2019-11-29 ven. 00:21</p>
+<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
+</div>
+</body>
+</html>
diff --git a/tuto2/index.org b/tuto2/index.org
new file mode 100644
index 0000000000000000000000000000000000000000..f915d1e07a48fc6fd0e05922ea0b8fe845d5a6f1
--- /dev/null
+++ b/tuto2/index.org
@@ -0,0 +1,147 @@
+#+TITLE: Distributed experiments on Grid'5000 ... and beyond !
+#+DATE: 
+#+AUTHOR: Matthieu Simonin
+
+#+HTML_HEAD: <link rel="stylesheet" type="text/css" href="timeline.css" />
+
+#+MACRO: enoslib EnOSlib
+#+MACRO: src_host https://gitlab.inria.fr/discovery/enoslib/blob/v4.8.1/enoslib/host.py#L8-14
+#+MACRO: doc_external_access https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html#accessing-http-services-inside-grid-5000
+#+MACRO: src_provider https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra
+#+MACRO: doc_provider https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html
+#+MACRO: doc_tasks https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html
+#+MACRO: doc_g5k_schema https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html#g5k-schema
+#+MACRO: doc_api https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html
+#+MACRO: doc_services https://discovery.gitlabpages.inria.fr/enoslib/apidoc/service.html
+
+
+* Benchmarking a real application
+  
+  In this tutorial we'll cover some aspects of evaluating the performance of a
+  real application. We'll work with ~overleaf~. ~overleaf~ is a collaborative
+  text editor that uses Latex to produce pdf files. Figure [[overleaf]]
+  is an overview of the editing part of the software.
+  
+  #+NAME: overleaf
+  #+CAPTION: Overview of ~overleaf~ editor: on the left users can collaboratively edit the document.
+  #+CAPTION: On the right the document is rendered.
+  [[file:./figs/overleaf-v2-editor.png][file:./figs/overleaf-v2-editor.png]]
+
+
+  Here is the plan:
+
+  - **Deployment** You'll first deploy our own ~overleaf~ instance (we don't want to use
+    the official/commercial instance).
+  - **Load generation** You'll generate compilation of different projects programatically.
+  - **Observation** You'll observe the effect of the load in the running system through various metrics.
+  - **Feedback** You'll formulate some hypothesis on the load characteristics and the observed effects on the system.
+
+* Before you start
+  
+  Make sure you are ok with the following.
+
+** Grid'5000 stuffs
+
+   #+begin_note
+   Make sure you are familiar with the Grid'5000 architecture. see section 1 & 2 of
+   https://www.grid5000.fr/w/Getting_Started. note that we won't do this tutorial
+   we'll prefer to use higher level tools for now.
+   #+end_note
+
+
+** Setup on Grid'5000
+
+   Connect to a Grid'5000 frontend of your choice (e.g rennes, nancy ...)
+
+   - create a new directory to host all the scripts of the session
+   - bootstrap a new python3 virtualenv 
+   - install {{{enoslib}}} and configure the access to the API
+
+   #+BEGIN_SRC bash :noeval
+   $frontend: cp -r ~msimonin/public/ccs-g5k-tuto2 .
+   $frontend: cd ccs-g5k-tuto2
+   $frontend: virtualenv --python=python3 venv
+   $frontend: source venv/bin/activate
+   $frontend(venv): pip install -r requirements.txt
+   $frontend(venv): echo '
+   verify_ssl: False
+   ' > ~/.python-grid5000.yaml
+   #+END_SRC
+
+* Deployment time !
+  
+  Figure [[architecture]] represents a simplified view of what we'll deploy. In blue
+  some services of ~overleaf~ are represented. First the Web portal is the entry
+  point to all the user requests. The three other services in the picture are
+  involved when compiling a document. The compilation service interacts with the
+  filestore (where the files of the image of the projects are stored) and the
+  docstore (where the text of the project is stored). There are other service
+  involved to provide the chat feature, history feature, real-time interaction
+  ... but we'll focus ony on the compilation process.
+
+  #+NAME: architecture
+  #+CAPTION: Simplified architecture of the system under study (blue) and the generated users (black).
+  #+CAPTION: Overleaf is composed of a dozen services ony four are represented here.
+  [[file:./figs/simple_compilation.png][file:./figs/simple_compilation.svg]]
+
+  #+begin_note
+  After the deployment you'll be able to:
+  - access the web portal and play with your own overleaf instance
+  - access the web portal of your friends and collaborate on a document 
+   (that's not the main objective of the tutorial but that's fun)
+  #+end_note
+
+** Deploy it  
+
+  #+BEGIN_SRC bash :noeval
+  $frontend(venv): python overleaf.py deploy --cluster=paravance
+  #+END_SRC
+
+  #+begin_note
+  - You can change the cluster name with any cluster on Grid'5000: see https://www.grid5000.fr/w/Hardware
+  - This can take several minutes...
+  #+end_note
+
+** Access it
+
+  To know where your services is installed you can run: 
+
+  #+BEGIN_SRC bash :noeval
+  $frontend(venv): python overleaf.py describe
+
+  # Possible outputp
+╒══════════════════════╤════════════╤════════╕
+│ Name                 │ Address    │ Port   │
+╞══════════════════════╪════════════╪════════╡
+│ Web portal           │ 10.144.0.2 │ 3000   │
+├──────────────────────┼────────────┼────────┤
+│ Monitoring portal    │ 10.144.0.2 │ 2000   │
+├──────────────────────┼────────────┼────────┤
+│ Benchmark portal     │ 10.144.0.3 │ 8089   │
+├──────────────────────┼────────────┼────────┤
+│ Compilation machines │ 10.144.0.4 │ -      │
+╘══════════════════════╧════════════╧════════╛
+  #+END_SRC
+
+  #+BEGIN_note
+  To access the web portal you can create a tunnel from your local machine to
+  the machine running the web portal as follows
+
+  #+BEGIN_SRC bash :noeval
+  # Adapt the node names with the node where the portal has been installed
+  # Replace <login> by your Grid'5000 login
+  $yourmachine: ssh -NL 3000:10.144.0.2:3000 <login>@access.grid5000.fr
+
+  # point your browser to localhost:3000
+  # username/mdp: toto@toto.com / toto4242
+  #+END_SRC
+  #+END_note
+
+
+* Benchmark the system
+
+** Deploy the benchmark nodes
+** Prepare the monitoring stack
+** Observations
+
+* Scale the system
diff --git a/tuto2/index.tex b/tuto2/index.tex
new file mode 100644
index 0000000000000000000000000000000000000000..2525d89f1cfa5aa88c321dfeee22a0bd2c90ca34
--- /dev/null
+++ b/tuto2/index.tex
@@ -0,0 +1,569 @@
+% Created 2019-10-17 jeu. 01:05
+% Intended LaTeX compiler: pdflatex
+\documentclass[11pt]{article}
+\usepackage[utf8]{inputenc}
+\usepackage[T1]{fontenc}
+\usepackage{graphicx}
+\usepackage{grffile}
+\usepackage{longtable}
+\usepackage{wrapfig}
+\usepackage{rotating}
+\usepackage[normalem]{ulem}
+\usepackage{amsmath}
+\usepackage{textcomp}
+\usepackage{amssymb}
+\usepackage{capt-of}
+\usepackage{hyperref}
+\author{Matthieu Simonin}
+\date{}
+\title{Distributed experiments on Grid'5000 \ldots{} and beyond !}
+\hypersetup{
+ pdfauthor={Matthieu Simonin},
+ pdftitle={Distributed experiments on Grid'5000 \ldots{} and beyond !},
+ pdfkeywords={},
+ pdfsubject={},
+ pdfcreator={Emacs 26.1 (Org mode 9.1.9)}, 
+ pdflang={English}}
+\begin{document}
+
+\maketitle
+\tableofcontents
+
+
+\section{Foreword}
+\label{sec:org40b18b0}
+
+\section{Setup on Grid'5000}
+\label{sec:orgec7b370}
+
+Connect to a Grid'5000 frontend of your choice.
+
+\begin{itemize}
+\item create a new directory to host all the scripts of the session
+\item bootstrap a new python3 virtualenv
+\item install EnOSlib and configure the access to the API
+\item you'll also want to have ipython and ipdb installed
+\end{itemize}
+
+\begin{verbatim}
+$frontend: mkdir enoslib_seminar
+$frontend: cd enoslib_seminar
+$frontend: virtualenv --python=python3 venv
+$frontend: source venv/bin/activate
+$frontend(venv): pip install enoslib ipython ipdb
+$frontend(venv): echo '
+verify_ssl: False
+' > ~/.python-grid5000.yaml
+
+\end{verbatim}
+
+\section{EnOSlib warmup on Grid'5000}
+\label{sec:org54c7eac}
+
+Learn how to get 2 nodes from Grid'5000 and start launching commands.
+
+\subsection{Reserve 2 nodes}
+\label{sec:org543c543}
+
+\begin{note}
+With EnOSlib you first describe your resource requirements using an abstract
+resource description. 
+Note that the network should be explictly stated.
+\end{note}
+
+Write the following python script in a file \texttt{run.py}. If needed adapt the
+\texttt{CLUSTER} and \texttt{SITE} variables.
+
+\begin{verbatim}
+from enoslib.api import run, run_command, gather_facts
+from enoslib.infra.enos_g5k.provider import G5k
+from enoslib.infra.enos_g5k.configuration import Configuration, NetworkConfiguration
+
+import logging
+
+
+logging.basicConfig(level=logging.INFO)
+
+
+SITE = "rennes"
+CLUSTER = "paravance"
+
+network = NetworkConfiguration(id="n1",
+                               type="prod",
+                               roles=["my_network"],
+                               site=SITE)
+
+conf = Configuration.from_settings(job_name="enoslib_tutorial",
+                                   job_type="allow_classic_ssh")\
+    .add_network_conf(network)\
+    .add_machine(roles=["server"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .add_machine(roles=["client"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .finalize()
+
+provider = G5k(conf)
+roles, networks =  provider.init()
+\end{verbatim}
+
+For the sake of curiosity let's inspect the roles and networks data
+structures using ipython.
+
+\begin{verbatim}
+$frontend (venv): ipython
+In [1]: run run.py
+# ...
+# ...
+In [2]: roles
+# ...
+In [3]: networks
+\end{verbatim}
+
+\begin{note}
+The abstract resource description is concretized by the call to the
+\texttt{provider.init} method. \texttt{roles} and \texttt{networks} contains the concrete machines
+and networks given by Grid'5000.
+Check the attributes of the Host data structure in the code: \url{https://gitlab.inria.fr/discovery/enoslib/blob/v4.8.1/enoslib/host.py\#L8-14}
+\end{note}
+
+\subsection{Using the run command and its variants}
+\label{sec:org4f0ed16}
+
+For this part you have two choices to run the examples:
+\begin{itemize}
+\item (prefered) append it in the previous file and re-run the file (yes this is safe to do so)
+\item write the example in the previously open ipython console
+\end{itemize}
+
+\subsubsection{Basics usages}
+\label{sec:org7f40ca6}
+
+Before proceeding you can add this util function to your code. It only used
+to pretty print a python dictionnary.
+\begin{verbatim}
+def pprint(d):
+    import json
+    print(json.dumps(d, indent=4))
+\end{verbatim}
+
+And use the \texttt{enoslib.api.run} function 
+\begin{verbatim}
+server = roles["server"][0]
+# ---
+# Using run
+# --------------------------------------------------------------------
+result = run(f"ping -c 5 {server.address}", roles["client"])
+pprint(result)
+\end{verbatim}
+
+Or the \texttt{enoslib.api.run\_command} function
+\begin{verbatim}
+# ---
+# Using run_command 1/2
+# --------------------------------------------------------------------
+result = run_command(f"ping -c 5 {server.address}",
+                     pattern_hosts="client",
+                     roles=roles)
+pprint(result)
+\end{verbatim}
+
+\begin{note}
+\texttt{enoslib.api.run} is a specialisation of \texttt{enoslib.api.run\_command}. 
+The latter let's you use \href{https://docs.ansible.com/ansible/latest/user\_guide/intro\_patterns.html}{some fancy patterns} to determine the list of hosts to run the command on.
+
+And yes, it uses Ansible behind the scene.
+\end{note}
+
+\subsubsection{Advanced usages}
+\label{sec:org0e02fbb}
+
+\begin{note}
+For all the remote interactions, EnOSlib relies on \href{https://docs.ansible.com/ansible/latest/index.html}{Ansible}. Ansible
+has it own variables management system.
+For instance the task \texttt{Gather Facts} at the beginning of the previous tasks
+gathers informations about all/some remote hosts and store them in the
+Ansible management system.
+\end{note}
+
+Let's see what Ansible is gathering about the hosts:
+\begin{verbatim}
+# ---
+# Gather facts
+# --------------------------------------------------------------------
+result = gather_facts(roles=roles)
+pprint(result)
+\end{verbatim}
+\begin{note}
+\texttt{enoslib.api.gather\_facts} is a way to get, in python, the variables known
+by Ansible about each host.
+\end{note}
+
+\begin{note}
+EnOSlib sits in between two worlds: the Python world and the Ansible
+world. One common need is to pass a variables from one world to another.
+\begin{itemize}
+\item \texttt{enoslib.api.gather\_facts} is a way to get, in Python, the variables known
+by Ansible about each host.
+\item \texttt{extra\_vars} keyword argument of \texttt{enoslib.api.run} or \texttt{enoslib.api.run\_command} will 
+pass variables from Python world to Ansible world (global variable)
+\item Injecting a key/value in a \texttt{Host.extra} attribute will make the variable \texttt{key} available to Ansible.
+This makes the variables Host specific.
+\end{itemize}
+\end{note}
+
+The following inject a global variable in the Ansible world
+\begin{verbatim}
+# ---
+# Passing a variable to the Ansible World using a global level variable
+# --------------------------------------------------------------------
+server = roles["server"][0]
+extra_vars={"server_ip": server.address}
+result = run("ping -c 5 {{ server_ip }}", roles["client"], extra_vars=extra_vars)
+\end{verbatim}
+
+\subsubsection{Ninja level}
+\label{sec:org0edd362}
+
+The following is valid and inject in the client host a specific variable to
+keep of the server IP.
+
+\begin{verbatim}
+# ---
+# Passing a variable to the Ansible World using a host level variable
+# --------------------------------------------------------------------
+server = roles["server"][0]
+client.extra.update(server_ip=server.address)
+result = run("ping -c 5 {{ server_ip }}", roles["client"])
+\end{verbatim}
+
+\begin{note}
+Host level variables are interesting to introduce some dissymetry between
+hosts using the same intruction in your Python Code.
+\end{note}
+
+\begin{question}
+How to perform simultaneously the ping to the other machine in calling only
+once \texttt{run} or \texttt{run\_command} and using host level variables?
+\end{question}
+
+\subsubsection{All together}
+\label{sec:org31aadd8}
+Access the full file: \url{exercices/run.py}
+
+\subsubsection{Some references}
+\label{sec:orga6331bb}
+
+\begin{itemize}
+\item G5k configuration schema: \url{https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html\#g5k-schema}
+\item API Reference: \url{https://discovery.gitlabpages.inria.fr/enoslib/apidoc/api.html}
+\end{itemize}
+\section{Iperf3 playground}
+\label{sec:org6a4417e}
+
+Let's experiment with \href{https://iperf.fr/}{iperf3}: a network bandwidth measuring tool. The goal is
+to deploy a simple benchmark between two hosts. 
+
+We'll also instrument the deployment in order to visualize in real-time the
+network traffic between the hosts. Since this is super common, EnOSlib
+exposes a \texttt{monitoring service} that lets you deploy very quickly what is
+needed.
+
+\subsection{First attempt}
+\label{sec:orgbfbe8c2}
+
+We adapt the previous example in the following script:
+\begin{verbatim}
+from enoslib.api import run_command, wait_ssh
+from enoslib.infra.enos_g5k.provider import G5k
+from enoslib.infra.enos_g5k.configuration import Configuration, NetworkConfiguration
+from enoslib.service import Monitoring
+
+import logging
+
+
+def pprint(d):
+    import json
+    print(json.dumps(d, indent=4))
+
+
+logging.basicConfig(level=logging.INFO)
+
+
+SITE = "rennes"
+CLUSTER = "paravance"
+
+network = NetworkConfiguration(id="n1",
+                               type="prod",
+                               roles=["my_network"],
+                               site=SITE)
+
+conf = Configuration.from_settings(job_name="enoslib_tutorial",
+                                   job_type="allow_classic_ssh")\
+    .add_network_conf(network)\
+    .add_machine(roles=["server"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .add_machine(roles=["client"],
+                 cluster=CLUSTER,
+                 nodes=1,
+                 primary_network=network)\
+    .finalize()
+
+provider = G5k(conf)
+roles, networks =  provider.init()
+wait_ssh(roles)
+
+# This deploys a monitoring stack
+m = Monitoring(collector=roles["server"],
+               agent=roles["server"] + roles["client"],
+               ui=roles["server"])
+m.deploy()
+
+
+# Below is the experimentation logic
+# It installs the bare minimum to run iperf3
+# The machine with the role 'server' is used to run a iperf3 server
+#     started in the background in a tmux
+# The machine with the role 'client' connects to that server
+# Report is printed in stdout
+server = roles["server"][0]
+run_command("apt update && apt install -y iperf3 tmux", roles=roles)
+run_command("tmux new-session -d 'exec iperf3 -s'", pattern_hosts="server", roles=roles)
+result = run_command(f"iperf3 -c {server.address} -t 30", pattern_hosts="client", roles=roles)
+pprint(result)
+\end{verbatim}
+
+Now, let's visualize the network traffic in real-time !
+\begin{note}
+Usually I follow this to access services running inside Grid'5000:
+\url{https://discovery.gitlabpages.inria.fr/enoslib/tutorials/grid5000.html\#accessing-http-services-inside-grid-5000}
+
+So to access the monitoring dashboard you need to connect using your browser
+to the machine `server` on the port 3000.
+\end{note}
+
+You should be able to visualize such a thing (after a bit of point and clicks).
+
+\href{./iperf3.png}{\begin{figure}[htbp]
+\centering
+\includegraphics[width=.9\linewidth]{./figs/iperf3.png}
+\caption{\label{fig:orgd2b4ea5}
+iperf3 / monitoring}
+\end{figure}}
+
+\subsection{Discussion}
+\label{sec:org8354e5d}
+
+\begin{itemize}
+\item What's good is: \ldots{}
+\item What's wrong is: \ldots{}
+\end{itemize}
+
+\subsection{A better approach (maybe)}
+\label{sec:org16d8bce}
+Access the full file: \url{exercices/iperf3\_better.py}
+
+\section{{\bfseries\sffamily TODO} Partial wrap-up}
+\label{sec:orgb35f46e}
+
+\begin{itemize}
+\item Configuration for G5k
+\begin{itemize}
+\item non deploy / deploy
+\item prod network / kavlan
+\end{itemize}
+\item Services
+\end{itemize}
+
+\section{Modules: for safer remote actions}
+\label{sec:org1ae5927}
+
+In this section we'll discover the idiomatic way of managing resources on the
+remote hosts. A resource can be anything: a user, a file, a line in a file, a
+repo on Gitlab, a firewall rule \ldots{}
+
+
+\subsection{Idempotency}
+\label{sec:org81e26b7}
+
+Let's assume you want to create a user (\texttt{foo}). With the \texttt{run\_command} this would look like:
+
+\begin{verbatim}
+run_command("useradd -m foo", roles=role)
+\end{verbatim}
+
+The main issue with this code is that it is not \textbf{idempotent}. Running it once
+will applied the effect (create the user). But, as soon as the user exist in
+the system, this will raise an error.
+
+\subsection{One reason why idempotency is important}
+\label{sec:org53c14cb}
+
+Let's consider the following snippet (mispelling the second command is intentional)
+\begin{verbatim}
+run_command("useradd -m foo", roles=role)
+run_command("mkdirz plop")
+\end{verbatim}
+Executing the above leads the system with the user \texttt{foo} created but the the
+directory \texttt{plop} not created since the second command fails.
+
+So what you want to do is to fix the second command and re-run the snippet again.
+But, you can't do that because \texttt{useradd} isn't idempotent.
+
+\subsection{Idempotency trick}
+\label{sec:orgb15c5ef}
+
+One easy solution is to protect your call to non idempotent commands with
+some ad'hoc tricks
+
+Here it can look like this:
+
+\begin{verbatim}
+run_command("id foo || useradd -m foo", roles=role)
+run_command("mkdir -p plop")
+\end{verbatim}
+
+\textbf{What's wrong with that}
+
+\begin{itemize}
+\item The trick depends on the command
+\item Re-reading the code is more complex: the code focus on the \textbf{\textbf{how}} not the \textbf{\textbf{what}}
+\end{itemize}
+
+\subsection{General idempotency}
+\label{sec:org4061e60}
+
+The idiomatic solution is to use modules (inherited from the Ansible
+Modules). The modules are specified in a \textbf{declarative} way and they ensure
+\textbf{idempotency} for most of them.
+
+So rewriting the example with modules looks like:
+\begin{verbatim}
+with play_on(roles=roles) as p:
+    p.user(name="foo", state="present", create_home="yes")
+    p.file(name="plop", state="directory")
+\end{verbatim}
+
+You can run this code as many times as you want without any error. You'll
+eventually find one user \texttt{foo} and one directory \texttt{plop} in your target
+systems.
+
+
+They are more than 2500 modules: \url{https://docs.ansible.com/ansible/latest/modules/list\_of\_all\_modules.html}
+
+If you can't find what you want you must know that:
+\begin{itemize}
+\item Writing your own module is possible
+\item Falling back to the idempotency trick is reasonable
+\end{itemize}
+
+\section{Providers: to replicate your experiment}
+\label{sec:orgfc2ec82}
+
+The resources that are used for your experiment are acquired through a
+provider. Providers are a mean to decouple the infrastructure code (the code
+that get the resources) from the code that runs the experiment. Changing the
+provider allows to replicate the experiment on another testbed.
+
+Originally it was used to iterate on the code locally (using the Vagrant
+provider) and to only test on Grid'5000 when necessary.
+
+We now have couple of providers that you may picked or mixed.
+
+\subsection{iperf3 on virtual machines on Grid'5000}
+\label{sec:org162cac9}
+
+We'll adapt the initial iperf3 example to use virtual machines instead of
+bare-metal machine. 
+
+Note that:
+
+\begin{itemize}
+\item The configuration object is different
+\item The experimentation logic is the same (rewritten using modules when it applies)
+\end{itemize}
+
+\begin{verbatim}
+from enoslib.api import play_on, wait_ssh
+from enoslib.infra.enos_vmong5k.provider import VMonG5k
+from enoslib.infra.enos_vmong5k.configuration import Configuration
+
+import logging
+import os
+
+logging.basicConfig(level=logging.DEBUG)
+
+CLUSTER = "paravance"
+
+# path to the inventory
+inventory = os.path.join(os.getcwd(), "hosts")
+
+# claim the resources
+conf = Configuration.from_settings(job_name="enoslib_tutorial", gateway=True)\
+                    .add_machine(roles=["server"],
+                                 cluster=CLUSTER,
+                                 number=1,
+                                 flavour="large")\
+                    .add_machine(roles=["client"],
+                                 cluster=CLUSTER,
+                                 number=1,
+                                 flavour="medium")\
+                    .finalize()
+
+provider = VMonG5k(conf)
+
+roles, networks = provider.init()
+wait_ssh(roles)
+
+# Below is the experimentation logic
+# It installs the bare minimum to run iperf3
+# The machine with the role 'server' is used to run a iperf3 server
+#     started in the background in a tmux
+# The machine with the role 'client' connects to that server
+# Report is printed in stdout
+server = roles["server"][0]
+
+with play_on(roles=roles) as p:
+    p.apt(name=["iperf3", "tmux"], state="present")
+
+with play_on(pattern_hosts="server", roles=roles) as p:
+    p.shell("tmux new-session -d 'exec iperf3 -s'")
+
+with play_on(pattern_hosts="client", roles=roles) as p:
+    p.shell(f"iperf3 -c {server.address} -t 30")
+
+with play_on(pattern_hosts="client", roles=roles) as p:
+    p.shell(f"iperf3 -c {server.address} -t 30 --logfile iperf3.out")
+    p.fetch(src="iperf3.out", dest="iperf3.out")
+\end{verbatim}
+
+Using module using the \texttt{play\_on} context manager does not bring back the
+results of the commands. Iperf3 let's you write the result of the command on
+a file. We just need to scp the file back to our local machine using the
+\texttt{fetch} module.
+
+\subsection{Ninja level}
+\label{sec:orge484eb8}
+
+Creates 5 \texttt{server} machines and 5 \texttt{client} machines and start 5 \textbf{parallel}
+streams of data using \texttt{iperf3}.
+
+\subsection{References}
+\label{sec:org9c0017b}
+
+\begin{itemize}
+\item Doc: \url{https://discovery.gitlabpages.inria.fr/enoslib/apidoc/infra.html}
+\item Sources: \url{https://gitlab.inria.fr/discovery/enoslib/tree/v4.8.1/enoslib/infra}
+\end{itemize}
+
+\section{Tasks: to organize your experiment}
+\label{sec:org7f002c7}
+
+To discover the Task API, head to \url{https://discovery.gitlabpages.inria.fr/enoslib/tutorials/using-tasks.html}.
+The examples are written for Vagrant but may be changed to whatever provider you like/have.
+\end{document}
diff --git a/tuto2/timeline.css b/tuto2/timeline.css
new file mode 100644
index 0000000000000000000000000000000000000000..268b0deaebe45d42a32888682272253296930629
--- /dev/null
+++ b/tuto2/timeline.css
@@ -0,0 +1,1035 @@
+@import url('https://fonts.googleapis.com/css?family=Crimson+Text:700|Fira+Sans:400,700');
+html {
+    font-family: sans-serif;
+    line-height: 1.15;
+    -ms-text-size-adjust: 100%;
+    -webkit-text-size-adjust: 100%
+}
+body {
+    margin: 0
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+    display: block
+}
+audio,
+canvas,
+progress,
+video {
+    display: inline-block
+}
+audio:not([controls]) {
+    display: none;
+    height: 0
+}
+progress {
+    vertical-align: baseline
+}
+[hidden],
+template {
+    display: none
+}
+a {
+    background-color: transparent;
+    -webkit-text-decoration-skip: objects
+}
+a:active,
+a:hover {
+    outline-width: 0
+}
+abbr[title] {
+    border-bottom: none;
+    text-decoration: underline;
+    text-decoration: underline dotted
+}
+b,
+strong {
+    font-weight: inherit;
+    font-weight: bolder
+}
+dfn {
+    font-style: italic
+}
+h1 {
+    font-size: 2em;
+    margin: .67em 0
+}
+mark {
+    background-color: #ff0;
+    color: #000
+}
+small {
+    font-size: 80%
+}
+sub,
+sup {
+    font-size: 75%;
+    line-height: 0;
+    position: relative;
+    vertical-align: baseline
+}
+sub {
+    bottom: -.25em
+}
+sup {
+    top: -.5em
+}
+img {
+    border-style: none
+}
+svg:not(:root) {
+    overflow: hidden
+}
+code,
+kbd,
+pre,
+samp {
+    font-family: monospace, monospace;
+    font-size: 1em
+}
+figure {
+    margin: 1em 40px
+}
+hr {
+    box-sizing: content-box;
+    height: 0;
+    overflow: visible
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+    font: inherit;
+    margin: 0
+}
+optgroup {
+    font-weight: 700
+}
+button,
+input {
+    overflow: visible
+}
+button,
+select {
+    text-transform: none
+}
+[type=reset],
+[type=submit],
+button,
+html [type=button] {
+    -webkit-appearance: button
+}
+[type=button]::-moz-focus-inner,
+[type=reset]::-moz-focus-inner,
+[type=submit]::-moz-focus-inner,
+button::-moz-focus-inner {
+    border-style: none;
+    padding: 0
+}
+[type=button]:-moz-focusring,
+[type=reset]:-moz-focusring,
+[type=submit]:-moz-focusring,
+button:-moz-focusring {
+    outline: 1px dotted ButtonText
+}
+fieldset {
+    border: 1px solid silver;
+    margin: 0 2px;
+    padding: .35em .625em .75em
+}
+legend {
+    box-sizing: border-box;
+    color: inherit;
+    display: table;
+    max-width: 100%;
+    padding: 0;
+    white-space: normal
+}
+textarea {
+    overflow: auto
+}
+[type=checkbox],
+[type=radio] {
+    box-sizing: border-box;
+    padding: 0
+}
+[type=number]::-webkit-inner-spin-button,
+[type=number]::-webkit-outer-spin-button {
+    height: auto
+}
+[type=search] {
+    -webkit-appearance: textfield;
+    outline-offset: -2px
+}
+[type=search]::-webkit-search-cancel-button,
+[type=search]::-webkit-search-decoration {
+    -webkit-appearance: none
+}
+::-webkit-input-placeholder {
+    color: inherit;
+    opacity: .54
+}
+::-webkit-file-upload-button {
+    -webkit-appearance: button;
+    font: inherit
+}
+.org-bold {
+    font-weight: 700
+}
+.org-bold-italic {
+    font-weight: 700;
+    font-style: italic
+}
+.org-buffer-menu-buffer {
+    font-weight: 700
+}
+.org-builtin {
+    color: #483d8b
+}
+.org-button {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-calendar-month-header {
+    color: #00f
+}
+.org-calendar-today {
+    text-decoration: underline
+}
+.org-calendar-weekday-header {
+    color: #008b8b
+}
+.org-calendar-weekend-header {
+    color: #b22222
+}
+.org-comint-highlight-input {
+    font-weight: 700
+}
+.org-comint-highlight-prompt {
+    color: #0000cd
+}
+.org-comment,
+.org-comment-delimiter {
+    color: #b22222
+}
+.org-constant {
+    color: #008b8b
+}
+.org-diary {
+    color: red
+}
+.org-doc {
+    color: #8b2252
+}
+.org-error {
+    color: red;
+    font-weight: 700
+}
+.org-escape-glyph {
+    color: brown
+}
+.org-file-name-shadow {
+    color: #7f7f7f
+}
+.org-fringe {
+    background-color: #f2f2f2
+}
+.org-function-name {
+    color: #00f
+}
+.org-glyphless-char {
+    font-size: 60%
+}
+.org-header-line {
+    color: #333;
+    background-color: #e5e5e5
+}
+.org-help-argument-name {
+    font-style: italic
+}
+.org-highlight {
+    background-color: #b4eeb4
+}
+.org-holiday {
+    background-color: pink
+}
+.org-info-header-node {
+    color: brown;
+    font-weight: 700;
+    font-style: italic
+}
+.org-info-header-xref {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-info-index-match {
+    background-color: #ff0
+}
+.org-info-menu-header {
+    font-weight: 700
+}
+.org-info-menu-star {
+    color: red
+}
+.org-info-node {
+    color: brown;
+    font-weight: 700;
+    font-style: italic
+}
+.org-info-title-1 {
+    font-size: 172%;
+    font-weight: 700
+}
+.org-info-title-2 {
+    font-size: 144%;
+    font-weight: 700
+}
+.org-info-title-3 {
+    font-size: 120%;
+    font-weight: 700
+}
+.org-info-title-4 {
+    font-weight: 700
+}
+.org-info-xref {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-italic {
+    font-style: italic
+}
+.org-keyword {
+    color: #a020f0
+}
+.org-lazy-highlight {
+    background-color: #afeeee
+}
+.org-link {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-link-visited {
+    color: #8b008b;
+    text-decoration: underline
+}
+.org-makefile-makepp-perl {
+    background-color: #bfefff
+}
+.org-makefile-space {
+    background-color: #ff69b4
+}
+.org-makefile-targets {
+    color: #00f
+}
+.org-match {
+    background-color: #ff0
+}
+.org-next-error {
+    background-color: gtk_selection_bg_color
+}
+.org-nobreak-space {
+    color: brown;
+    text-decoration: underline
+}
+.org-org-agenda-calendar-event,
+.org-org-agenda-calendar-sexp {
+    color: #000;
+    background-color: #fff
+}
+.org-org-agenda-clocking {
+    background-color: #ff0
+}
+.org-org-agenda-column-dateline {
+    background-color: #e5e5e5
+}
+.org-org-agenda-current-time {
+    color: #b8860b
+}
+.org-org-agenda-date {
+    color: #00f
+}
+.org-org-agenda-date-today {
+    color: #00f;
+    font-weight: 700;
+    font-style: italic
+}
+.org-org-agenda-date-weekend {
+    color: #00f;
+    font-weight: 700
+}
+.org-org-agenda-diary {
+    color: #000;
+    background-color: #fff
+}
+.org-org-agenda-dimmed-todo {
+    color: #7f7f7f
+}
+.org-org-agenda-done {
+    color: #228b22
+}
+.org-org-agenda-filter-category,
+.org-org-agenda-filter-effort,
+.org-org-agenda-filter-regexp,
+.org-org-agenda-filter-tags {
+    color: #000;
+    background-color: #bfbfbf
+}
+.org-org-agenda-restriction-lock {
+    background-color: #eee
+}
+.org-org-agenda-structure {
+    color: #00f
+}
+.org-org-archived,
+.org-org-block {
+    color: #7f7f7f
+}
+.org-org-block-begin-line,
+.org-org-block-end-line {
+    color: #b22222
+}
+.org-org-checkbox {
+    font-weight: 700
+}
+.org-org-checkbox-statistics-done {
+    color: #228b22;
+    font-weight: 700
+}
+.org-org-checkbox-statistics-todo {
+    color: red;
+    font-weight: 700
+}
+.org-org-clock-overlay {
+    color: #000;
+    background-color: #d3d3d3
+}
+.org-org-code {
+    color: #7f7f7f
+}
+.org-org-column,
+.org-org-column-title {
+    background-color: #e5e5e5
+}
+.org-org-column-title {
+    font-weight: 700;
+    text-decoration: underline
+}
+.org-org-date {
+    color: #a020f0;
+    text-decoration: underline
+}
+.org-org-date-selected {
+    color: red
+}
+.org-org-default {
+    color: #000;
+    background-color: #fff
+}
+.org-org-document-info {
+    color: #191970
+}
+.org-org-document-info-keyword {
+    color: #7f7f7f
+}
+.org-org-document-title {
+    color: #191970;
+    font-weight: 700
+}
+.org-org-done {
+    color: #228b22;
+    font-weight: 700
+}
+.org-org-drawer {
+    color: #00f
+}
+.org-org-ellipsis {
+    color: #b8860b;
+    text-decoration: underline
+}
+.org-org-footnote {
+    color: #a020f0;
+    text-decoration: underline
+}
+.org-org-formula {
+    color: #b22222
+}
+.org-org-headline-done {
+    color: #bc8f8f
+}
+.org-org-hide {
+    color: #fff
+}
+.org-org-latex-and-related {
+    color: #8b4513
+}
+.org-org-level-1 {
+    color: #00f
+}
+.org-org-level-2 {
+    color: sienna
+}
+.org-org-level-3 {
+    color: #a020f0
+}
+.org-org-level-4 {
+    color: #b22222
+}
+.org-org-level-5 {
+    color: #228b22
+}
+.org-org-level-6 {
+    color: #008b8b
+}
+.org-org-level-7 {
+    color: #483d8b
+}
+.org-org-level-8 {
+    color: #8b2252
+}
+.org-org-link {
+    color: #3a5fcd;
+    text-decoration: underline
+}
+.org-org-list-dt {
+    font-weight: 700
+}
+.org-org-macro {
+    color: #8b4513
+}
+.org-org-meta-line {
+    color: #b22222
+}
+.org-org-mode-line-clock {
+    color: #000;
+    background-color: #bfbfbf
+}
+.org-org-mode-line-clock-overrun {
+    color: #000;
+    background-color: red
+}
+.org-org-priority {
+    color: #a020f0
+}
+.org-org-quote {
+    color: #7f7f7f
+}
+.org-org-scheduled {
+    color: #006400
+}
+.org-org-scheduled-previously {
+    color: #b22222
+}
+.org-org-scheduled-today {
+    color: #006400
+}
+.org-org-sexp-date,
+.org-org-special-keyword {
+    color: #a020f0
+}
+.org-org-table {
+    color: #00f
+}
+.org-org-tag,
+.org-org-tag-group {
+    font-weight: 700
+}
+.org-org-target {
+    text-decoration: underline
+}
+.org-org-time-grid {
+    color: #b8860b
+}
+.org-org-todo {
+    color: red;
+    font-weight: 700
+}
+.org-org-upcoming-deadline {
+    color: #b22222
+}
+.org-org-verbatim,
+.org-org-verse {
+    color: #7f7f7f
+}
+.org-org-warning {
+    color: red;
+    font-weight: 700
+}
+.org-outline-1 {
+    color: #00f
+}
+.org-outline-2 {
+    color: sienna
+}
+.org-outline-3 {
+    color: #a020f0
+}
+.org-outline-4 {
+    color: #b22222
+}
+.org-outline-5 {
+    color: #228b22
+}
+.org-outline-6 {
+    color: #008b8b
+}
+.org-outline-7 {
+    color: #483d8b
+}
+.org-outline-8 {
+    color: #8b2252
+}
+.org-preprocessor {
+    color: #483d8b
+}
+.org-regexp-grouping-backslash,
+.org-regexp-grouping-construct {
+    font-weight: 700
+}
+.org-region {
+    background-color: gtk_selection_bg_color
+}
+.org-secondary-selection {
+    background-color: #ff0
+}
+.org-shadow {
+    color: #7f7f7f
+}
+.org-show-paren-match {
+    background-color: #40e0d0
+}
+.org-show-paren-mismatch {
+    color: #fff;
+    background-color: #a020f0
+}
+.org-string {
+    color: #8b2252
+}
+.org-success {
+    color: #228b22;
+    font-weight: 700
+}
+.org-table-cell {
+    color: #e5e5e5;
+    background-color: #00f
+}
+.org-tooltip {
+    color: #000;
+    background-color: #ffffe0
+}
+.org-trailing-whitespace {
+    background-color: red
+}
+.org-type {
+    color: #228b22
+}
+.org-underline {
+    text-decoration: underline
+}
+.org-variable-name {
+    color: sienna
+}
+.org-warning {
+    color: #ff8c00;
+    font-weight: 700
+}
+.org-warning-1 {
+    color: red;
+    font-weight: 700
+}
+body {
+    width: 95%;
+    margin: 2%;
+    font: normal normal normal 16px/1.6em 'Fira Sans', sans-serif;
+    color: #333
+}
+@media (min-width: 769px) {
+    body {
+        width: 700px;
+        margin-left: 5vw
+    }
+}
+::-moz-selection {
+    background: #d6edff
+}
+::selection {
+    background: #d6edff
+}
+.title {
+    margin: auto;
+    color: #000
+}
+.subtitle,
+.title {
+    text-align: center
+}
+.subtitle {
+    font-size: medium;
+    font-weight: 700
+}
+.abstract {
+    margin: auto;
+    width: 80%;
+    font-style: italic
+}
+.abstract p:last-of-type:before {
+    content: "    ";
+    white-space: pre
+}
+.status {
+    font-size: 90%;
+    margin: 2em auto
+}
+[class^=section-number-] {
+    margin-right: .5em
+}
+[id^=orgheadline] {
+    clear: both
+}
+#footnotes {
+    font-size: 90%
+}
+.footpara {
+    display: inline;
+    margin: .2em auto
+}
+.footdef {
+    margin-bottom: 1em
+}
+.footdef sup {
+    padding-right: .5em
+}
+a {
+    color: #527d9a;
+    text-decoration: none
+}
+a:hover {
+    color: #035;
+    border-bottom: 1px dotted
+}
+figure {
+    padding: 0;
+    margin: 0;
+    text-align: center
+}
+img {
+    max-width: 100%;
+    vertical-align: middle
+}
+.MathJax_Display {
+    font-size: 90%;
+    margin: 0!important;
+    width: 90%!important
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+    color: #a5573e;
+    line-height: 1.6em;
+    font-weight: bold;
+    font-family: 'Crimson Text', serif
+}
+h4,
+h5,
+h6 {
+    font-size: 1em
+}
+dt {
+    font-weight: 700
+}
+table {
+    margin: auto;
+    border-top: 2px solid;
+    border-collapse: collapse
+}
+table,
+thead {
+    border-bottom: 2px solid
+}
+table td+td,
+table th+th {
+    border-left: 1px solid gray
+}
+table tr {
+    border-top: 1px solid #d3d3d3
+}
+td,
+th {
+    padding: 5px 10px;
+    vertical-align: middle
+}
+caption.t-above {
+    caption-side: top
+}
+caption.t-bottom {
+    caption-side: bottom
+}
+th.org-center,
+th.org-left,
+th.org-right {
+    text-align: center
+}
+td.org-right {
+    text-align: right
+}
+td.org-left {
+    text-align: left
+}
+td.org-center {
+    text-align: center
+}
+code {
+    padding: 2px 5px;
+    margin: auto 1px;
+    border: 1px solid #ddd;
+    border-radius: 3px;
+    background-clip: padding-box;
+    color: #333;
+    font-size: 80%
+}
+blockquote {
+    margin: 1em 2em;
+    padding-left: 1em;
+    border-left: 3px solid #ccc
+}
+kbd {
+    background-color: #f7f7f7;
+    font-size: 80%;
+    margin: 0 .1em;
+    padding: .1em .6em
+}
+.todo {
+    background-color: red;
+    padding: 2px
+}
+.done,
+.todo {
+    color: #fff;
+    border-radius: 3px;
+    background-clip: padding-box;
+    font-size: 80%;
+    font-family: Lucida Console, monospace
+}
+.done {
+    background-color: green;
+    padding: 3px
+}
+.priority {
+    color: orange;
+    font-family: Lucida Console, monospace
+}
+#table-of-contents li {
+    clear: both
+}
+.tag {
+    font-family: Lucida Console, monospace;
+    font-size: 70%;
+    font-weight: 400
+}
+.tag span {
+    padding: 0 5px;
+    float: right;
+    margin-right: 5px;
+    border: 1px solid #bbb;
+    border-radius: 3px;
+    background-clip: padding-box;
+    color: #333;
+    background-color: #eee;
+    line-height: 1.6
+}
+.timestamp {
+    color: #bebebe;
+    font-size: 90%
+}
+.timestamp-kwd {
+    color: #5f9ea0
+}
+.org-right {
+    margin-left: auto;
+    margin-right: 0;
+    text-align: right
+}
+.org-left {
+    margin-left: 0;
+    margin-right: auto;
+    text-align: left
+}
+.org-center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center
+}
+.underline {
+    text-decoration: underline
+}
+#postamble p,
+#preamble p {
+    font-size: 90%;
+    margin: .2em
+}
+p.verse {
+    margin-left: 3%
+}
+pre {
+    border: 1px solid #ccc;
+    box-shadow: 3px 3px 3px #eee;
+    font-family: Lucida Console, monospace;
+    margin: 1.2em;
+    padding: 8pt;
+    font-size: 80%;
+    background:  #3f3f3f;
+    color: #dcdccc;
+}
+pre.src {
+    overflow: auto;
+    padding-top: 1.2em;
+    position: relative
+}
+pre.src:hover:before {
+    display: inline
+}
+pre.src-sh:before {
+    content: "sh"
+}
+pre.src-bash:before {
+    content: "bash"
+}
+pre.src-emacs-lisp:before {
+    content: "Emacs Lisp"
+}
+pre.src-R:before {
+    content: "R"
+}
+pre.src-org:before {
+    content: "Org"
+}
+pre.src-cpp:before {
+    content: "C++"
+}
+pre.src-c:before {
+    content: "C"
+}
+pre.src-html:before {
+    content: "HTML"
+}
+pre.src-javascript:before,
+pre.src-js:before {
+    content: "Javascript"
+}
+pre.src-makefile:before {
+    content: "Makefile"
+}
+.inlinetask {
+    background: #ffc;
+    border: 2px solid gray;
+    margin: 10px;
+    padding: 10px
+}
+#org-div-home-and-up {
+    font-size: 70%;
+    text-align: right;
+    white-space: nowrap
+}
+.linenr {
+    font-size: 90%
+}
+.code-highlighted {
+    color: #FFFFE0;
+    background-color: #284F28;
+}
+#bibliography {
+    font-size: 90%
+}
+#bibliography table {
+    width: 100%
+}
+.creator {
+    display: block
+}
+@media (min-width: 769px) {
+    .creator {
+        display: inline;
+        float: right
+    }
+}
+
+.org-src-container > label {
+    font-size: 75%;
+}
+
+.note {
+    padding-left: 2em;
+    border: 1px dashed #00f;
+    position: relative;
+}
+.note:before {
+    display: block;
+    position: absolute;
+    left: 0px;
+    content: "i";
+    background: #00f;
+    border-radius: 0.8em;
+    -moz-border-radius: 0.8em;
+    -webkit-border-radius: 0.8em;
+    color: #ffffff;
+    display: inline-block;
+    font-weight: bold;
+    line-height: 1.6em;
+    margin-right: 5px;
+    text-align: center;
+    width: 1.6em;
+}
+
+@media screen and (min-width: 600px) {
+    h1 {
+        font-size: 2em;
+    }
+    h2 {
+        font-size: 1.5em;
+    }
+    h3 {
+        font-size: 1.3em;
+    }
+    h1,h2,h3 {
+        line-height: 1.4em;
+    }
+    h4,h5,h6 {
+        font-size: 1.1em;
+    }
+}
+
+.question {
+    padding-left: 2em;
+    border: 1px dashed #0f0;
+    position: relative;
+}
+.question:before {
+    display: block;
+    position: absolute;
+    left: 0px;
+    content: "?";
+    background: #00ff00;
+    border-radius: 0.8em;
+    -moz-border-radius: 0.8em;
+    -webkit-border-radius: 0.8em;
+    color: #ffffff;
+    display: inline-block;
+    font-weight: bold;
+    line-height: 1.6em;
+    margin-right: 5px;
+    text-align: center;
+    width: 1.6em;
+}