--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <title>nepi.execution.ec — NEPI 3.2 documentation</title>
+
+ <link rel="stylesheet" href="../../../_static/sphinxdoc.css" type="text/css" />
+ <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
+
+ <script type="text/javascript">
+ var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: '../../../',
+ VERSION: '3.2',
+ COLLAPSE_INDEX: false,
+ FILE_SUFFIX: '.html',
+ HAS_SOURCE: true
+ };
+ </script>
+ <script type="text/javascript" src="../../../_static/jquery.js"></script>
+ <script type="text/javascript" src="../../../_static/underscore.js"></script>
+ <script type="text/javascript" src="../../../_static/doctools.js"></script>
+ <link rel="top" title="NEPI 3.2 documentation" href="../../../index.html" />
+ <link rel="up" title="Module code" href="../../index.html" />
+ </head>
+ <body>
+ <div class="related">
+ <h3>Navigation</h3>
+ <ul>
+ <li class="right" style="margin-right: 10px">
+ <a href="../../../genindex.html" title="General Index"
+ accesskey="I">index</a></li>
+ <li class="right" >
+ <a href="../../../py-modindex.html" title="Python Module Index"
+ >modules</a> |</li>
+ <li><a href="../../../index.html">NEPI 3.2 documentation</a> »</li>
+ <li><a href="../../index.html" accesskey="U">Module code</a> »</li>
+ </ul>
+ </div>
+ <div class="sphinxsidebar">
+ <div class="sphinxsidebarwrapper">
+<div id="searchbox" style="display: none">
+ <h3>Quick search</h3>
+ <form class="search" action="../../../search.html" method="get">
+ <input type="text" name="q" />
+ <input type="submit" value="Go" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ <p class="searchtip" style="font-size: 90%">
+ Enter search terms or a module, class or function name.
+ </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+ </div>
+ </div>
+
+ <div class="document">
+ <div class="documentwrapper">
+ <div class="bodywrapper">
+ <div class="body">
+
+ <h1>Source code for nepi.execution.ec</h1><div class="highlight"><pre>
+<span class="c">#</span>
+<span class="c"># NEPI, a framework to manage network experiments</span>
+<span class="c"># Copyright (C) 2013 INRIA</span>
+<span class="c">#</span>
+<span class="c"># This program is free software: you can redistribute it and/or modify</span>
+<span class="c"># it under the terms of the GNU General Public License version 2 as</span>
+<span class="c"># published by the Free Software Foundation;</span>
+<span class="c">#</span>
+<span class="c"># This program is distributed in the hope that it will be useful,</span>
+<span class="c"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
+<span class="c"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
+<span class="c"># GNU General Public License for more details.</span>
+<span class="c">#</span>
+<span class="c"># You should have received a copy of the GNU General Public License</span>
+<span class="c"># along with this program. If not, see <http://www.gnu.org/licenses/>.</span>
+<span class="c">#</span>
+<span class="c"># Author: Alina Quereilhac <alina.quereilhac@inria.fr></span>
+
+<span class="kn">from</span> <span class="nn">nepi.util</span> <span class="kn">import</span> <span class="n">guid</span>
+<span class="kn">from</span> <span class="nn">nepi.util.parallel</span> <span class="kn">import</span> <span class="n">ParallelRun</span>
+<span class="kn">from</span> <span class="nn">nepi.util.timefuncs</span> <span class="kn">import</span> <span class="n">tnow</span><span class="p">,</span> <span class="n">tdiffsec</span><span class="p">,</span> <span class="n">stabsformat</span><span class="p">,</span> <span class="n">tsformat</span>
+<span class="kn">from</span> <span class="nn">nepi.execution.resource</span> <span class="kn">import</span> <span class="n">ResourceFactory</span><span class="p">,</span> <span class="n">ResourceAction</span><span class="p">,</span> \
+ <span class="n">ResourceState</span><span class="p">,</span> <span class="n">ResourceState2str</span>
+<span class="kn">from</span> <span class="nn">nepi.execution.scheduler</span> <span class="kn">import</span> <span class="n">HeapScheduler</span><span class="p">,</span> <span class="n">Task</span><span class="p">,</span> <span class="n">TaskStatus</span>
+<span class="kn">from</span> <span class="nn">nepi.execution.trace</span> <span class="kn">import</span> <span class="n">TraceAttr</span>
+<span class="kn">from</span> <span class="nn">nepi.util.serializer</span> <span class="kn">import</span> <span class="n">ECSerializer</span><span class="p">,</span> <span class="n">SFormats</span>
+<span class="kn">from</span> <span class="nn">nepi.util.plotter</span> <span class="kn">import</span> <span class="n">ECPlotter</span><span class="p">,</span> <span class="n">PFormats</span>
+<span class="kn">from</span> <span class="nn">nepi.util.netgraph</span> <span class="kn">import</span> <span class="n">NetGraph</span><span class="p">,</span> <span class="n">TopologyType</span>
+
+<span class="c"># TODO: use multiprocessing instead of threading</span>
+<span class="c"># TODO: Allow to reconnect to a running experiment instance! (reconnect mode vs deploy mode)</span>
+
+<span class="kn">import</span> <span class="nn">functools</span>
+<span class="kn">import</span> <span class="nn">logging</span>
+<span class="kn">import</span> <span class="nn">os</span>
+<span class="kn">import</span> <span class="nn">sys</span>
+<span class="kn">import</span> <span class="nn">tempfile</span>
+<span class="kn">import</span> <span class="nn">time</span>
+<span class="kn">import</span> <span class="nn">threading</span>
+<span class="kn">import</span> <span class="nn">weakref</span>
+
+<div class="viewcode-block" id="FailureLevel"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.FailureLevel">[docs]</a><span class="k">class</span> <span class="nc">FailureLevel</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+ <span class="sd">""" Possible failure states for the experiment """</span>
+ <span class="n">OK</span> <span class="o">=</span> <span class="mi">1</span>
+ <span class="n">RM_FAILURE</span> <span class="o">=</span> <span class="mi">2</span>
+ <span class="n">EC_FAILURE</span> <span class="o">=</span> <span class="mi">3</span>
+</div>
+<div class="viewcode-block" id="FailureManager"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.FailureManager">[docs]</a><span class="k">class</span> <span class="nc">FailureManager</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+ <span class="sd">""" The FailureManager is responsible for handling errors</span>
+<span class="sd"> and deciding whether an experiment should be aborted or not</span>
+<span class="sd"> """</span>
+
+ <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_ec</span> <span class="o">=</span> <span class="bp">None</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_failure_level</span> <span class="o">=</span> <span class="n">FailureLevel</span><span class="o">.</span><span class="n">OK</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_abort</span> <span class="o">=</span> <span class="bp">False</span>
+
+<div class="viewcode-block" id="FailureManager.set_ec"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.FailureManager.set_ec">[docs]</a> <span class="k">def</span> <span class="nf">set_ec</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ec</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_ec</span> <span class="o">=</span> <span class="n">weakref</span><span class="o">.</span><span class="n">ref</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="FailureManager.ec"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.FailureManager.ec">[docs]</a> <span class="k">def</span> <span class="nf">ec</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the ExperimentController associated to this FailureManager </span>
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ec</span><span class="p">()</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="FailureManager.abort"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.FailureManager.abort">[docs]</a> <span class="k">def</span> <span class="nf">abort</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_abort</span>
+</div>
+<div class="viewcode-block" id="FailureManager.eval_failure"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.FailureManager.eval_failure">[docs]</a> <span class="k">def</span> <span class="nf">eval_failure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Implements failure policy and sets the abort state of the</span>
+<span class="sd"> experiment based on the failure state and criticality of</span>
+<span class="sd"> the RM</span>
+
+<span class="sd"> :param guid: Guid of the RM upon which the failure of the experiment</span>
+<span class="sd"> is evaluated</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> """</span>
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_failure_level</span> <span class="o">==</span> <span class="n">FailureLevel</span><span class="o">.</span><span class="n">OK</span><span class="p">:</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ec</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="n">state</span> <span class="o">=</span> <span class="n">rm</span><span class="o">.</span><span class="n">state</span>
+ <span class="n">critical</span> <span class="o">=</span> <span class="n">rm</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"critical"</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="n">state</span> <span class="o">==</span> <span class="n">ResourceState</span><span class="o">.</span><span class="n">FAILED</span> <span class="ow">and</span> <span class="n">critical</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_failure_level</span> <span class="o">=</span> <span class="n">FailureLevel</span><span class="o">.</span><span class="n">RM_FAILURE</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_abort</span> <span class="o">=</span> <span class="bp">True</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">ec</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"RM critical failure occurred on guid </span><span class="si">%d</span><span class="s">."</span> \
+ <span class="s">" Setting EC FAILURE LEVEL to RM_FAILURE"</span> <span class="o">%</span> <span class="n">guid</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="FailureManager.set_ec_failure"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.FailureManager.set_ec_failure">[docs]</a> <span class="k">def</span> <span class="nf">set_ec_failure</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_failure_level</span> <span class="o">=</span> <span class="n">FailureLevel</span><span class="o">.</span><span class="n">EC_FAILURE</span>
+</div></div>
+<div class="viewcode-block" id="ECState"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ECState">[docs]</a><span class="k">class</span> <span class="nc">ECState</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+ <span class="sd">""" Possible states of the ExperimentController</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="n">RUNNING</span> <span class="o">=</span> <span class="mi">1</span>
+ <span class="n">FAILED</span> <span class="o">=</span> <span class="mi">2</span>
+ <span class="n">RELEASED</span> <span class="o">=</span> <span class="mi">3</span>
+ <span class="n">TERMINATED</span> <span class="o">=</span> <span class="mi">4</span>
+</div>
+<div class="viewcode-block" id="ExperimentController"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController">[docs]</a><span class="k">class</span> <span class="nc">ExperimentController</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+ <span class="sd">"""</span>
+<span class="sd"> .. note::</span>
+
+<span class="sd"> An experiment, or scenario, is defined by a concrete set of resources,</span>
+<span class="sd"> and the behavior, configuration and interconnection of those resources. </span>
+<span class="sd"> The Experiment Description (ED) is a detailed representation of a</span>
+<span class="sd"> single experiment. It contains all the necessary information to </span>
+<span class="sd"> allow repeating the experiment. NEPI allows to describe</span>
+<span class="sd"> experiments by registering components (resources), configuring them</span>
+<span class="sd"> and interconnecting them.</span>
+<span class="sd"> </span>
+<span class="sd"> A same experiment (scenario) can be executed many times, generating </span>
+<span class="sd"> different results. We call an experiment execution (instance) a 'run'.</span>
+
+<span class="sd"> The ExperimentController (EC), is the entity responsible of</span>
+<span class="sd"> managing an experiment run. The same scenario can be </span>
+<span class="sd"> recreated (and re-run) by instantiating an EC and recreating </span>
+<span class="sd"> the same experiment description. </span>
+
+<span class="sd"> An experiment is represented as a graph of interconnected</span>
+<span class="sd"> resources. A resource is a generic concept in the sense that any</span>
+<span class="sd"> component taking part of an experiment, whether physical of</span>
+<span class="sd"> virtual, is considered a resource. A resources could be a host, </span>
+<span class="sd"> a virtual machine, an application, a simulator, a IP address.</span>
+
+<span class="sd"> A ResourceManager (RM), is the entity responsible for managing a </span>
+<span class="sd"> single resource. ResourceManagers are specific to a resource</span>
+<span class="sd"> type (i.e. An RM to control a Linux application will not be</span>
+<span class="sd"> the same as the RM used to control a ns-3 simulation).</span>
+<span class="sd"> To support a new type of resource, a new RM must be implemented. </span>
+<span class="sd"> NEPI already provides a variety of RMs to control basic resources, </span>
+<span class="sd"> and new can be extended from the existing ones.</span>
+
+<span class="sd"> Through the EC interface the user can create ResourceManagers (RMs),</span>
+<span class="sd"> configure them and interconnect them, to describe an experiment.</span>
+<span class="sd"> Describing an experiment through the EC does not run the experiment.</span>
+<span class="sd"> Only when the 'deploy()' method is invoked on the EC, the EC will take </span>
+<span class="sd"> actions to transform the 'described' experiment into a 'running' experiment.</span>
+
+<span class="sd"> While the experiment is running, it is possible to continue to</span>
+<span class="sd"> create/configure/connect RMs, and to deploy them to involve new</span>
+<span class="sd"> resources in the experiment (this is known as 'interactive' deployment).</span>
+<span class="sd"> </span>
+<span class="sd"> An experiments in NEPI is identified by a string id, </span>
+<span class="sd"> which is either given by the user, or automatically generated by NEPI. </span>
+<span class="sd"> The purpose of this identifier is to separate files and results that </span>
+<span class="sd"> belong to different experiment scenarios. </span>
+<span class="sd"> However, since a same 'experiment' can be run many times, the experiment</span>
+<span class="sd"> id is not enough to identify an experiment instance (run).</span>
+<span class="sd"> For this reason, the ExperimentController has two identifier, the </span>
+<span class="sd"> exp_id, which can be re-used in different ExperimentController,</span>
+<span class="sd"> and the run_id, which is unique to one ExperimentController instance, and</span>
+<span class="sd"> is automatically generated by NEPI.</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+
+ <span class="nd">@classmethod</span>
+<div class="viewcode-block" id="ExperimentController.load"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.load">[docs]</a> <span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">filepath</span><span class="p">,</span> <span class="n">format</span> <span class="o">=</span> <span class="n">SFormats</span><span class="o">.</span><span class="n">XML</span><span class="p">):</span>
+ <span class="n">serializer</span> <span class="o">=</span> <span class="n">ECSerializer</span><span class="p">()</span>
+ <span class="n">ec</span> <span class="o">=</span> <span class="n">serializer</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">filepath</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">ec</span>
+</div>
+ <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exp_id</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">local_dir</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">persist</span> <span class="o">=</span> <span class="bp">False</span><span class="p">,</span>
+ <span class="n">fm</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">add_node_callback</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">add_edge_callback</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
+ <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+ <span class="sd">""" ExperimentController entity to model an execute a network </span>
+<span class="sd"> experiment.</span>
+<span class="sd"> </span>
+<span class="sd"> :param exp_id: Human readable name to identify the experiment</span>
+<span class="sd"> :type exp_id: str</span>
+
+<span class="sd"> :param local_dir: Path to local directory where to store experiment</span>
+<span class="sd"> related files</span>
+<span class="sd"> :type local_dir: str</span>
+
+<span class="sd"> :param persist: Save an XML description of the experiment after </span>
+<span class="sd"> completion at local_dir</span>
+<span class="sd"> :type persist: bool</span>
+
+<span class="sd"> :param fm: FailureManager object. If None is given, the default </span>
+<span class="sd"> FailureManager class will be used</span>
+<span class="sd"> :type fm: FailureManager</span>
+
+<span class="sd"> :param add_node_callback: Callback to invoke for node instantiation</span>
+<span class="sd"> when automatic topology creation mode is used </span>
+<span class="sd"> :type add_node_callback: function</span>
+
+<span class="sd"> :param add_edge_callback: Callback to invoke for edge instantiation </span>
+<span class="sd"> when automatic topology creation mode is used </span>
+<span class="sd"> :type add_edge_callback: function</span>
+
+<span class="sd"> """</span>
+ <span class="nb">super</span><span class="p">(</span><span class="n">ExperimentController</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
+
+ <span class="c"># Logging</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s">"ExperimentController"</span><span class="p">)</span>
+
+ <span class="c"># Run identifier. It identifies a concrete execution instance (run) </span>
+ <span class="c"># of an experiment.</span>
+ <span class="c"># Since a same experiment (same configuration) can be executed many </span>
+ <span class="c"># times, this run_id permits to separate result files generated on </span>
+ <span class="c"># different experiment executions</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_run_id</span> <span class="o">=</span> <span class="n">tsformat</span><span class="p">()</span>
+
+ <span class="c"># Experiment identifier. Usually assigned by the user</span>
+ <span class="c"># Identifies the experiment scenario (i.e. configuration, </span>
+ <span class="c"># resources used, etc)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_exp_id</span> <span class="o">=</span> <span class="n">exp_id</span> <span class="ow">or</span> <span class="s">"exp-</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">os</span><span class="o">.</span><span class="n">urandom</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)</span>
+
+ <span class="c"># Local path where to store experiment related files (results, etc)</span>
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">local_dir</span><span class="p">:</span>
+ <span class="n">local_dir</span> <span class="o">=</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">gettempdir</span><span class="p">()</span> <span class="c"># /tmp</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">_local_dir</span> <span class="o">=</span> <span class="n">local_dir</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_exp_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">local_dir</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">exp_id</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_run_dir</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">exp_dir</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">run_id</span><span class="p">)</span>
+
+ <span class="c"># If True persist the experiment controller in XML format, after completion</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_persist</span> <span class="o">=</span> <span class="n">persist</span>
+
+ <span class="c"># generator of globally unique ids</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_guid_generator</span> <span class="o">=</span> <span class="n">guid</span><span class="o">.</span><span class="n">GuidGenerator</span><span class="p">()</span>
+
+ <span class="c"># Resource managers</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
+
+ <span class="c"># Scheduler. It a queue that holds tasks scheduled for</span>
+ <span class="c"># execution, and yields the next task to be executed </span>
+ <span class="c"># ordered by execution and arrival time</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span> <span class="o">=</span> <span class="n">HeapScheduler</span><span class="p">()</span>
+
+ <span class="c"># Tasks</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_tasks</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
+
+ <span class="c"># RM groups (for deployment) </span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_groups</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
+
+ <span class="c"># generator of globally unique id for groups</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_group_id_generator</span> <span class="o">=</span> <span class="n">guid</span><span class="o">.</span><span class="n">GuidGenerator</span><span class="p">()</span>
+
+ <span class="c"># Flag to stop processing thread</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_stop</span> <span class="o">=</span> <span class="bp">False</span>
+
+ <span class="c"># Entity in charge of managing system failures</span>
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">fm</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_fm</span> <span class="o">=</span> <span class="n">FailureManager</span><span class="p">()</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_fm</span><span class="o">.</span><span class="n">set_ec</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
+
+ <span class="c"># EC state</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">=</span> <span class="n">ECState</span><span class="o">.</span><span class="n">RUNNING</span>
+
+ <span class="c"># Automatically construct experiment description </span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_netgraph</span> <span class="o">=</span> <span class="bp">None</span>
+ <span class="k">if</span> <span class="n">add_node_callback</span> <span class="ow">or</span> <span class="n">add_edge_callback</span> <span class="ow">or</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"topology"</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_build_from_netgraph</span><span class="p">(</span><span class="n">add_node_callback</span><span class="p">,</span> <span class="n">add_edge_callback</span><span class="p">,</span>
+ <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+
+ <span class="c"># The runner is a pool of threads used to parallelize </span>
+ <span class="c"># execution of tasks</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_nthreads</span> <span class="o">=</span> <span class="mi">20</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_runner</span> <span class="o">=</span> <span class="bp">None</span>
+
+ <span class="c"># Event processing thread</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Condition</span><span class="p">()</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_process</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_thread</span><span class="o">.</span><span class="n">setDaemon</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.logger"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.logger">[docs]</a> <span class="k">def</span> <span class="nf">logger</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the logger instance of the Experiment Controller</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_logger</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.fm"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.fm">[docs]</a> <span class="k">def</span> <span class="nf">fm</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the failure manager</span>
+
+<span class="sd"> """</span>
+
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fm</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.failure_level"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.failure_level">[docs]</a> <span class="k">def</span> <span class="nf">failure_level</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the level of FAILURE of th experiment</span>
+
+<span class="sd"> """</span>
+
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fm</span><span class="o">.</span><span class="n">_failure_level</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.ecstate"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.ecstate">[docs]</a> <span class="k">def</span> <span class="nf">ecstate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the state of the Experiment Controller</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.exp_id"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.exp_id">[docs]</a> <span class="k">def</span> <span class="nf">exp_id</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the experiment id assigned by the user</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_exp_id</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.run_id"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.run_id">[docs]</a> <span class="k">def</span> <span class="nf">run_id</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the experiment instance (run) identifier (automatically </span>
+<span class="sd"> generated)</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_run_id</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.nthreads"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.nthreads">[docs]</a> <span class="k">def</span> <span class="nf">nthreads</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the number of processing nthreads used</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_nthreads</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.local_dir"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.local_dir">[docs]</a> <span class="k">def</span> <span class="nf">local_dir</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Root local directory for experiment files</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_local_dir</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.exp_dir"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.exp_dir">[docs]</a> <span class="k">def</span> <span class="nf">exp_dir</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Local directory to store results and other files related to the </span>
+<span class="sd"> experiment.</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_exp_dir</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.run_dir"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.run_dir">[docs]</a> <span class="k">def</span> <span class="nf">run_dir</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Local directory to store results and other files related to the </span>
+<span class="sd"> experiment run.</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_run_dir</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.persist"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.persist">[docs]</a> <span class="k">def</span> <span class="nf">persist</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" If True, persists the ExperimentController to XML format upon </span>
+<span class="sd"> experiment completion</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_persist</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.netgraph"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.netgraph">[docs]</a> <span class="k">def</span> <span class="nf">netgraph</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Return NetGraph instance if experiment description was automatically </span>
+<span class="sd"> generated</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_netgraph</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.abort"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.abort">[docs]</a> <span class="k">def</span> <span class="nf">abort</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns True if the experiment has failed and should be interrupted,</span>
+<span class="sd"> False otherwise.</span>
+
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fm</span><span class="o">.</span><span class="n">abort</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.inform_failure"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.inform_failure">[docs]</a> <span class="k">def</span> <span class="nf">inform_failure</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Reports a failure in a RM to the EC for evaluation</span>
+
+<span class="sd"> :param guid: Resource id</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> """</span>
+
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fm</span><span class="o">.</span><span class="n">eval_failure</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.wait_finished"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.wait_finished">[docs]</a> <span class="k">def</span> <span class="nf">wait_finished</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids</span><span class="p">):</span>
+ <span class="sd">""" Blocking method that waits until all RMs in the 'guids' list </span>
+<span class="sd"> have reached a state >= STOPPED (i.e. STOPPED, FAILED or </span>
+<span class="sd"> RELEASED ), or until a failure in the experiment occurs </span>
+<span class="sd"> (i.e. abort == True) </span>
+<span class="sd"> </span>
+<span class="sd"> :param guids: List of guids</span>
+<span class="sd"> :type guids: list</span>
+
+<span class="sd"> """</span>
+
+ <span class="k">def</span> <span class="nf">quit</span><span class="p">():</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">abort</span>
+
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">guids</span><span class="p">,</span> <span class="n">state</span> <span class="o">=</span> <span class="n">ResourceState</span><span class="o">.</span><span class="n">STOPPED</span><span class="p">,</span>
+ <span class="n">quit</span> <span class="o">=</span> <span class="n">quit</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.wait_started"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.wait_started">[docs]</a> <span class="k">def</span> <span class="nf">wait_started</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids</span><span class="p">):</span>
+ <span class="sd">""" Blocking method that waits until all RMs in the 'guids' list </span>
+<span class="sd"> have reached a state >= STARTED, or until a failure in the </span>
+<span class="sd"> experiment occurs (i.e. abort == True) </span>
+<span class="sd"> </span>
+<span class="sd"> :param guids: List of guids</span>
+<span class="sd"> :type guids: list</span>
+
+<span class="sd"> """</span>
+
+ <span class="k">def</span> <span class="nf">quit</span><span class="p">():</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">abort</span>
+
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">guids</span><span class="p">,</span> <span class="n">state</span> <span class="o">=</span> <span class="n">ResourceState</span><span class="o">.</span><span class="n">STARTED</span><span class="p">,</span>
+ <span class="n">quit</span> <span class="o">=</span> <span class="n">quit</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.wait_released"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.wait_released">[docs]</a> <span class="k">def</span> <span class="nf">wait_released</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids</span><span class="p">):</span>
+ <span class="sd">""" Blocking method that waits until all RMs in the 'guids' list </span>
+<span class="sd"> have reached a state == RELEASED, or until the EC fails </span>
+<span class="sd"> </span>
+<span class="sd"> :param guids: List of guids</span>
+<span class="sd"> :type guids: list</span>
+
+<span class="sd"> """</span>
+
+ <span class="k">def</span> <span class="nf">quit</span><span class="p">():</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">==</span> <span class="n">ECState</span><span class="o">.</span><span class="n">FAILED</span>
+
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">guids</span><span class="p">,</span> <span class="n">state</span> <span class="o">=</span> <span class="n">ResourceState</span><span class="o">.</span><span class="n">RELEASED</span><span class="p">,</span>
+ <span class="n">quit</span> <span class="o">=</span> <span class="n">quit</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.wait_deployed"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.wait_deployed">[docs]</a> <span class="k">def</span> <span class="nf">wait_deployed</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids</span><span class="p">):</span>
+ <span class="sd">""" Blocking method that waits until all RMs in the 'guids' list </span>
+<span class="sd"> have reached a state >= READY, or until a failure in the </span>
+<span class="sd"> experiment occurs (i.e. abort == True) </span>
+<span class="sd"> </span>
+<span class="sd"> :param guids: List of guids</span>
+<span class="sd"> :type guids: list</span>
+
+<span class="sd"> """</span>
+
+ <span class="k">def</span> <span class="nf">quit</span><span class="p">():</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">abort</span>
+
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">guids</span><span class="p">,</span> <span class="n">state</span> <span class="o">=</span> <span class="n">ResourceState</span><span class="o">.</span><span class="n">READY</span><span class="p">,</span>
+ <span class="n">quit</span> <span class="o">=</span> <span class="n">quit</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.wait"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.wait">[docs]</a> <span class="k">def</span> <span class="nf">wait</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">quit</span><span class="p">):</span>
+ <span class="sd">""" Blocking method that waits until all RMs in the 'guids' list </span>
+<span class="sd"> have reached a state >= 'state', or until the 'quit' callback</span>
+<span class="sd"> yields True</span>
+<span class="sd"> </span>
+<span class="sd"> :param guids: List of guids</span>
+<span class="sd"> :type guids: list</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">guids</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+ <span class="n">guids</span> <span class="o">=</span> <span class="p">[</span><span class="n">guids</span><span class="p">]</span>
+
+ <span class="c"># Make a copy to avoid modifying the original guids list</span>
+ <span class="n">guids</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">guids</span><span class="p">)</span>
+
+ <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
+ <span class="c"># If there are no more guids to wait for</span>
+ <span class="c"># or the quit function returns True, exit the loop</span>
+ <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">guids</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">quit</span><span class="p">():</span>
+ <span class="k">break</span>
+
+ <span class="c"># If a guid reached one of the target states, remove it from list</span>
+ <span class="n">guid</span> <span class="o">=</span> <span class="n">guids</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="n">rstate</span> <span class="o">=</span> <span class="n">rm</span><span class="o">.</span><span class="n">state</span>
+
+ <span class="k">if</span> <span class="n">rstate</span> <span class="o">>=</span> <span class="n">state</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">" </span><span class="si">%s</span><span class="s"> guid </span><span class="si">%d</span><span class="s"> DONE - state is </span><span class="si">%s</span><span class="s">, required is >= </span><span class="si">%s</span><span class="s"> "</span> <span class="o">%</span> <span class="p">(</span>
+ <span class="n">rm</span><span class="o">.</span><span class="n">get_rtype</span><span class="p">(),</span> <span class="n">guid</span><span class="p">,</span> <span class="n">rstate</span><span class="p">,</span> <span class="n">state</span><span class="p">))</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="c"># Debug...</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">" WAITING FOR guid </span><span class="si">%d</span><span class="s"> - state is </span><span class="si">%s</span><span class="s">, required is >= </span><span class="si">%s</span><span class="s"> "</span> <span class="o">%</span> <span class="p">(</span>
+ <span class="n">guid</span><span class="p">,</span> <span class="n">rstate</span><span class="p">,</span> <span class="n">state</span><span class="p">))</span>
+
+ <span class="n">guids</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+
+ <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.plot"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.plot">[docs]</a> <span class="k">def</span> <span class="nf">plot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dirpath</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">format</span><span class="o">=</span> <span class="n">PFormats</span><span class="o">.</span><span class="n">FIGURE</span><span class="p">,</span> <span class="n">show</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
+ <span class="n">plotter</span> <span class="o">=</span> <span class="n">ECPlotter</span><span class="p">()</span>
+ <span class="n">fpath</span> <span class="o">=</span> <span class="n">plotter</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dirpath</span> <span class="o">=</span> <span class="n">dirpath</span><span class="p">,</span> <span class="n">format</span><span class="o">=</span> <span class="n">format</span><span class="p">,</span>
+ <span class="n">show</span> <span class="o">=</span> <span class="n">show</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">fpath</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.serialize"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.serialize">[docs]</a> <span class="k">def</span> <span class="nf">serialize</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">format</span> <span class="o">=</span> <span class="n">SFormats</span><span class="o">.</span><span class="n">XML</span><span class="p">):</span>
+ <span class="n">serializer</span> <span class="o">=</span> <span class="n">ECSerializer</span><span class="p">()</span>
+ <span class="n">sec</span> <span class="o">=</span> <span class="n">serializer</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">format</span> <span class="o">=</span> <span class="n">format</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">sec</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.save"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.save">[docs]</a> <span class="k">def</span> <span class="nf">save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dirpath</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">format</span> <span class="o">=</span> <span class="n">SFormats</span><span class="o">.</span><span class="n">XML</span><span class="p">):</span>
+ <span class="k">if</span> <span class="n">dirpath</span> <span class="o">==</span> <span class="bp">None</span><span class="p">:</span>
+ <span class="n">dirpath</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">run_dir</span>
+
+ <span class="k">try</span><span class="p">:</span>
+ <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">dirpath</span><span class="p">)</span>
+ <span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
+ <span class="k">pass</span>
+
+ <span class="n">serializer</span> <span class="o">=</span> <span class="n">ECSerializer</span><span class="p">()</span>
+ <span class="n">path</span> <span class="o">=</span> <span class="n">serializer</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dirpath</span><span class="p">,</span> <span class="n">format</span> <span class="o">=</span> <span class="n">format</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">path</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_task"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_task">[docs]</a> <span class="k">def</span> <span class="nf">get_task</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tid</span><span class="p">):</span>
+ <span class="sd">""" Returns a task by its id</span>
+
+<span class="sd"> :param tid: Id of the task</span>
+<span class="sd"> :type tid: int</span>
+<span class="sd"> </span>
+<span class="sd"> :rtype: Task</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tasks</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">tid</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_resource"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_resource">[docs]</a> <span class="k">def</span> <span class="nf">get_resource</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns a registered ResourceManager by its guid</span>
+
+<span class="sd"> :param guid: Id of the resource</span>
+<span class="sd"> :type guid: int</span>
+<span class="sd"> </span>
+<span class="sd"> :rtype: ResourceManager</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_resources_by_type"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_resources_by_type">[docs]</a> <span class="k">def</span> <span class="nf">get_resources_by_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rtype</span><span class="p">):</span>
+ <span class="sd">""" Returns the ResourceManager objects of type rtype</span>
+
+<span class="sd"> :param rtype: Resource type</span>
+<span class="sd"> :type rtype: string</span>
+<span class="sd"> </span>
+<span class="sd"> :rtype: list of ResourceManagers</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="n">rms</span> <span class="o">=</span> <span class="p">[]</span>
+ <span class="k">for</span> <span class="n">guid</span><span class="p">,</span> <span class="n">rm</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
+ <span class="k">if</span> <span class="n">rm</span><span class="o">.</span><span class="n">get_rtype</span><span class="p">()</span> <span class="o">==</span> <span class="n">rtype</span><span class="p">:</span>
+ <span class="n">rms</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">rm</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rms</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.remove_resource"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.remove_resource">[docs]</a> <span class="k">def</span> <span class="nf">remove_resource</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span><span class="p">[</span><span class="n">guid</span><span class="p">]</span>
+</div>
+ <span class="nd">@property</span>
+<div class="viewcode-block" id="ExperimentController.resources"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.resources">[docs]</a> <span class="k">def</span> <span class="nf">resources</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Returns the guids of all ResourceManagers </span>
+
+<span class="sd"> :return: Set of all RM guids</span>
+<span class="sd"> :rtype: list</span>
+
+<span class="sd"> """</span>
+ <span class="n">keys</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
+
+ <span class="k">return</span> <span class="n">keys</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.filter_resources"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.filter_resources">[docs]</a> <span class="k">def</span> <span class="nf">filter_resources</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rtype</span><span class="p">):</span>
+ <span class="sd">""" Returns the guids of all ResourceManagers of type rtype</span>
+
+<span class="sd"> :param rtype: Resource type</span>
+<span class="sd"> :type rtype: string</span>
+<span class="sd"> </span>
+<span class="sd"> :rtype: list of guids</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="n">rms</span> <span class="o">=</span> <span class="p">[]</span>
+ <span class="k">for</span> <span class="n">guid</span><span class="p">,</span> <span class="n">rm</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
+ <span class="k">if</span> <span class="n">rm</span><span class="o">.</span><span class="n">get_rtype</span><span class="p">()</span> <span class="o">==</span> <span class="n">rtype</span><span class="p">:</span>
+ <span class="n">rms</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">rm</span><span class="o">.</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rms</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.register_resource"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.register_resource">[docs]</a> <span class="k">def</span> <span class="nf">register_resource</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rtype</span><span class="p">,</span> <span class="n">guid</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
+ <span class="sd">""" Registers a new ResourceManager of type 'rtype' in the experiment</span>
+<span class="sd"> </span>
+<span class="sd"> This method will assign a new 'guid' for the RM, if no guid</span>
+<span class="sd"> is specified.</span>
+
+<span class="sd"> :param rtype: Type of the RM</span>
+<span class="sd"> :type rtype: str</span>
+
+<span class="sd"> :return: Guid of the RM</span>
+<span class="sd"> :rtype: int</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="c"># Get next available guid</span>
+ <span class="n">guid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_guid_generator</span><span class="o">.</span><span class="n">next</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+
+ <span class="c"># Instantiate RM</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="n">ResourceFactory</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">rtype</span><span class="p">,</span> <span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">)</span>
+
+ <span class="c"># Store RM</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span><span class="p">[</span><span class="n">guid</span><span class="p">]</span> <span class="o">=</span> <span class="n">rm</span>
+
+ <span class="k">return</span> <span class="n">guid</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_attributes"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_attributes">[docs]</a> <span class="k">def</span> <span class="nf">get_attributes</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns all the attributes of the RM with guid 'guid'</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :return: List of attributes</span>
+<span class="sd"> :rtype: list</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">get_attributes</span><span class="p">()</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_attribute"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_attribute">[docs]</a> <span class="k">def</span> <span class="nf">get_attribute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+ <span class="sd">""" Returns the attribute 'name' of the RM with guid 'guid'</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :param name: Name of the attribute</span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> :return: The attribute with name 'name'</span>
+<span class="sd"> :rtype: Attribute</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">get_attribute</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.register_connection"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.register_connection">[docs]</a> <span class="k">def</span> <span class="nf">register_connection</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid1</span><span class="p">,</span> <span class="n">guid2</span><span class="p">):</span>
+ <span class="sd">""" Registers a connection between a RM with guid 'guid1'</span>
+<span class="sd"> and another RM with guid 'guid2'. </span>
+<span class="sd"> </span>
+<span class="sd"> The order of the in which the two guids are provided is not</span>
+<span class="sd"> important, since the connection relationship is symmetric.</span>
+
+<span class="sd"> :param guid1: First guid to connect</span>
+<span class="sd"> :type guid1: ResourceManager</span>
+
+<span class="sd"> :param guid2: Second guid to connect</span>
+<span class="sd"> :type guid: ResourceManager</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm1</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid1</span><span class="p">)</span>
+ <span class="n">rm2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid2</span><span class="p">)</span>
+
+ <span class="n">rm1</span><span class="o">.</span><span class="n">register_connection</span><span class="p">(</span><span class="n">guid2</span><span class="p">)</span>
+ <span class="n">rm2</span><span class="o">.</span><span class="n">register_connection</span><span class="p">(</span><span class="n">guid1</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.register_condition"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.register_condition">[docs]</a> <span class="k">def</span> <span class="nf">register_condition</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids1</span><span class="p">,</span> <span class="n">action</span><span class="p">,</span> <span class="n">guids2</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span>
+ <span class="n">time</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
+ <span class="sd">""" Registers an action START, STOP or DEPLOY for all RM on list</span>
+<span class="sd"> guids1 to occur at time 'time' after all elements in list guids2 </span>
+<span class="sd"> have reached state 'state'.</span>
+
+<span class="sd"> :param guids1: List of guids of RMs subjected to action</span>
+<span class="sd"> :type guids1: list</span>
+
+<span class="sd"> :param action: Action to perform (either START, STOP or DEPLOY)</span>
+<span class="sd"> :type action: ResourceAction</span>
+
+<span class="sd"> :param guids2: List of guids of RMs to we waited for</span>
+<span class="sd"> :type guids2: list</span>
+
+<span class="sd"> :param state: State to wait for on RMs of list guids2 (STARTED,</span>
+<span class="sd"> STOPPED, etc)</span>
+<span class="sd"> :type state: ResourceState</span>
+
+<span class="sd"> :param time: Time to wait after guids2 has reached status </span>
+<span class="sd"> :type time: string</span>
+
+<span class="sd"> """</span>
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">guids1</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+ <span class="n">guids1</span> <span class="o">=</span> <span class="p">[</span><span class="n">guids1</span><span class="p">]</span>
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">guids2</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+ <span class="n">guids2</span> <span class="o">=</span> <span class="p">[</span><span class="n">guids2</span><span class="p">]</span>
+
+ <span class="k">for</span> <span class="n">guid1</span> <span class="ow">in</span> <span class="n">guids1</span><span class="p">:</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid1</span><span class="p">)</span>
+ <span class="n">rm</span><span class="o">.</span><span class="n">register_condition</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">guids2</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">time</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.enable_trace"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.enable_trace">[docs]</a> <span class="k">def</span> <span class="nf">enable_trace</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+ <span class="sd">""" Enables a trace to be collected during the experiment run</span>
+
+<span class="sd"> :param name: Name of the trace</span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="n">rm</span><span class="o">.</span><span class="n">enable_trace</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.trace_enabled"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.trace_enabled">[docs]</a> <span class="k">def</span> <span class="nf">trace_enabled</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+ <span class="sd">""" Returns True if the trace of name 'name' is enabled</span>
+
+<span class="sd"> :param name: Name of the trace</span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">trace_enabled</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.trace"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.trace">[docs]</a> <span class="k">def</span> <span class="nf">trace</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">attr</span> <span class="o">=</span> <span class="n">TraceAttr</span><span class="o">.</span><span class="n">ALL</span><span class="p">,</span> <span class="n">block</span> <span class="o">=</span> <span class="mi">512</span><span class="p">,</span> <span class="n">offset</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
+ <span class="sd">""" Returns information on a collected trace, the trace stream or </span>
+<span class="sd"> blocks (chunks) of the trace stream</span>
+
+<span class="sd"> :param name: Name of the trace</span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> :param attr: Can be one of:</span>
+<span class="sd"> - TraceAttr.ALL (complete trace content), </span>
+<span class="sd"> - TraceAttr.STREAM (block in bytes to read starting </span>
+<span class="sd"> at offset),</span>
+<span class="sd"> - TraceAttr.PATH (full path to the trace file),</span>
+<span class="sd"> - TraceAttr.SIZE (size of trace file). </span>
+<span class="sd"> :type attr: str</span>
+
+<span class="sd"> :param block: Number of bytes to retrieve from trace, when attr is </span>
+<span class="sd"> TraceAttr.STREAM </span>
+<span class="sd"> :type name: int</span>
+
+<span class="sd"> :param offset: Number of 'blocks' to skip, when attr is TraceAttr.STREAM </span>
+<span class="sd"> :type name: int</span>
+
+<span class="sd"> :rtype: str</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">trace</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="n">block</span><span class="p">,</span> <span class="n">offset</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_traces"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_traces">[docs]</a> <span class="k">def</span> <span class="nf">get_traces</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the list of the trace names of the RM with guid 'guid'</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :return: List of trace names</span>
+<span class="sd"> :rtype: list</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">get_traces</span><span class="p">()</span>
+
+</div>
+<div class="viewcode-block" id="ExperimentController.discover"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.discover">[docs]</a> <span class="k">def</span> <span class="nf">discover</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Discovers an available resource matching the criteria defined</span>
+<span class="sd"> by the RM with guid 'guid', and associates that resource to the RM</span>
+
+<span class="sd"> Not all RM types require (or are capable of) performing resource </span>
+<span class="sd"> discovery. For the RM types which are not capable of doing so, </span>
+<span class="sd"> invoking this method does not have any consequences. </span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">discover</span><span class="p">()</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.provision"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.provision">[docs]</a> <span class="k">def</span> <span class="nf">provision</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Provisions the resource associated to the RM with guid 'guid'.</span>
+
+<span class="sd"> Provisioning means making a resource 'accessible' to the user. </span>
+<span class="sd"> Not all RM types require (or are capable of) performing resource </span>
+<span class="sd"> provisioning. For the RM types which are not capable of doing so, </span>
+<span class="sd"> invoking this method does not have any consequences. </span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">provision</span><span class="p">()</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get">[docs]</a> <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+ <span class="sd">""" Returns the value of the attribute with name 'name' on the</span>
+<span class="sd"> RM with guid 'guid'</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :param name: Name of the attribute </span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> :return: The value of the attribute with name 'name'</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.set"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.set">[docs]</a> <span class="k">def</span> <span class="nf">set</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+ <span class="sd">""" Modifies the value of the attribute with name 'name' on the </span>
+<span class="sd"> RM with guid 'guid'.</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :param name: Name of the attribute</span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> :param value: Value of the attribute</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="n">rm</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_global"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_global">[docs]</a> <span class="k">def</span> <span class="nf">get_global</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rtype</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+ <span class="sd">""" Returns the value of the global attribute with name 'name' on the</span>
+<span class="sd"> RMs of rtype 'rtype'.</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :param name: Name of the attribute </span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> :return: The value of the attribute with name 'name'</span>
+
+<span class="sd"> """</span>
+ <span class="n">rclass</span> <span class="o">=</span> <span class="n">ResourceFactory</span><span class="o">.</span><span class="n">get_resource_type</span><span class="p">(</span><span class="n">rtype</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rclass</span><span class="o">.</span><span class="n">get_global</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.set_global"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.set_global">[docs]</a> <span class="k">def</span> <span class="nf">set_global</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rtype</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+ <span class="sd">""" Modifies the value of the global attribute with name 'name' on the </span>
+<span class="sd"> RMs of with rtype 'rtype'.</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :param name: Name of the attribute</span>
+<span class="sd"> :type name: str</span>
+
+<span class="sd"> :param value: Value of the attribute</span>
+
+<span class="sd"> """</span>
+ <span class="n">rclass</span> <span class="o">=</span> <span class="n">ResourceFactory</span><span class="o">.</span><span class="n">get_resource_type</span><span class="p">(</span><span class="n">rtype</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rclass</span><span class="o">.</span><span class="n">set_global</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.state"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.state">[docs]</a> <span class="k">def</span> <span class="nf">state</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">,</span> <span class="n">hr</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
+ <span class="sd">""" Returns the state of a resource</span>
+
+<span class="sd"> :param guid: Resource guid</span>
+<span class="sd"> :type guid: integer</span>
+
+<span class="sd"> :param hr: Human readable. Forces return of a </span>
+<span class="sd"> status string instead of a number </span>
+<span class="sd"> :type hr: boolean</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="n">state</span> <span class="o">=</span> <span class="n">rm</span><span class="o">.</span><span class="n">state</span>
+
+ <span class="k">if</span> <span class="n">hr</span><span class="p">:</span>
+ <span class="k">return</span> <span class="n">ResourceState2str</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
+
+ <span class="k">return</span> <span class="n">state</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.stop"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.stop">[docs]</a> <span class="k">def</span> <span class="nf">stop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Stops the RM with guid 'guid'</span>
+
+<span class="sd"> Stopping a RM means that the resource it controls will</span>
+<span class="sd"> no longer take part of the experiment.</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.start"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.start">[docs]</a> <span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Starts the RM with guid 'guid'</span>
+
+<span class="sd"> Starting a RM means that the resource it controls will</span>
+<span class="sd"> begin taking part of the experiment.</span>
+
+<span class="sd"> :param guid: Guid of the RM</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_start_time"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_start_time">[docs]</a> <span class="k">def</span> <span class="nf">get_start_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the start time of the RM as a timestamp """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">start_time</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_stop_time"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_stop_time">[docs]</a> <span class="k">def</span> <span class="nf">get_stop_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the stop time of the RM as a timestamp """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">stop_time</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_discover_time"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_discover_time">[docs]</a> <span class="k">def</span> <span class="nf">get_discover_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the discover time of the RM as a timestamp """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">discover_time</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_provision_time"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_provision_time">[docs]</a> <span class="k">def</span> <span class="nf">get_provision_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the provision time of the RM as a timestamp """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">provision_time</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_ready_time"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_ready_time">[docs]</a> <span class="k">def</span> <span class="nf">get_ready_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the deployment time of the RM as a timestamp """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">ready_time</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_release_time"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_release_time">[docs]</a> <span class="k">def</span> <span class="nf">get_release_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the release time of the RM as a timestamp """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">release_time</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.get_failed_time"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.get_failed_time">[docs]</a> <span class="k">def</span> <span class="nf">get_failed_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guid</span><span class="p">):</span>
+ <span class="sd">""" Returns the time failure occured for the RM as a timestamp """</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="k">return</span> <span class="n">rm</span><span class="o">.</span><span class="n">failed_time</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.set_with_conditions"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.set_with_conditions">[docs]</a> <span class="k">def</span> <span class="nf">set_with_conditions</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">guids1</span><span class="p">,</span> <span class="n">guids2</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span>
+ <span class="n">time</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
+ <span class="sd">""" Modifies the value of attribute with name 'name' on all RMs </span>
+<span class="sd"> on the guids1 list when time 'time' has elapsed since all </span>
+<span class="sd"> elements in guids2 list have reached state 'state'.</span>
+
+<span class="sd"> :param name: Name of attribute to set in RM</span>
+<span class="sd"> :type name: string</span>
+
+<span class="sd"> :param value: Value of attribute to set in RM</span>
+<span class="sd"> :type name: string</span>
+
+<span class="sd"> :param guids1: List of guids of RMs subjected to action</span>
+<span class="sd"> :type guids1: list</span>
+
+<span class="sd"> :param action: Action to register (either START or STOP)</span>
+<span class="sd"> :type action: ResourceAction</span>
+
+<span class="sd"> :param guids2: List of guids of RMs to we waited for</span>
+<span class="sd"> :type guids2: list</span>
+
+<span class="sd"> :param state: State to wait for on RMs (STARTED, STOPPED, etc)</span>
+<span class="sd"> :type state: ResourceState</span>
+
+<span class="sd"> :param time: Time to wait after guids2 has reached status </span>
+<span class="sd"> :type time: string</span>
+
+<span class="sd"> """</span>
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">guids1</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+ <span class="n">guids1</span> <span class="o">=</span> <span class="p">[</span><span class="n">guids1</span><span class="p">]</span>
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">guids2</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+ <span class="n">guids2</span> <span class="o">=</span> <span class="p">[</span><span class="n">guids2</span><span class="p">]</span>
+
+ <span class="k">for</span> <span class="n">guid1</span> <span class="ow">in</span> <span class="n">guids1</span><span class="p">:</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="n">rm</span><span class="o">.</span><span class="n">set_with_conditions</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">guids2</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">time</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.deploy"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.deploy">[docs]</a> <span class="k">def</span> <span class="nf">deploy</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">wait_all_ready</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="n">group</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
+ <span class="sd">""" Deploys all ResourceManagers in the guids list. </span>
+<span class="sd"> </span>
+<span class="sd"> If the argument 'guids' is not given, all RMs with state NEW</span>
+<span class="sd"> are deployed.</span>
+
+<span class="sd"> :param guids: List of guids of RMs to deploy</span>
+<span class="sd"> :type guids: list</span>
+
+<span class="sd"> :param wait_all_ready: Wait until all RMs are ready in</span>
+<span class="sd"> order to start the RMs</span>
+<span class="sd"> :type guid: int</span>
+
+<span class="sd"> :param group: Id of deployment group in which to deploy RMs</span>
+<span class="sd"> :type group: int</span>
+
+<span class="sd"> """</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">" ------- DEPLOY START ------ "</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">guids</span><span class="p">:</span>
+ <span class="c"># If no guids list was passed, all 'NEW' RMs will be deployed</span>
+ <span class="n">guids</span> <span class="o">=</span> <span class="p">[]</span>
+ <span class="k">for</span> <span class="n">guid</span><span class="p">,</span> <span class="n">rm</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_resources</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
+ <span class="k">if</span> <span class="n">rm</span><span class="o">.</span><span class="n">state</span> <span class="o">==</span> <span class="n">ResourceState</span><span class="o">.</span><span class="n">NEW</span><span class="p">:</span>
+ <span class="n">guids</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">guids</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+ <span class="n">guids</span> <span class="o">=</span> <span class="p">[</span><span class="n">guids</span><span class="p">]</span>
+
+ <span class="c"># Create deployment group</span>
+ <span class="c"># New guids can be added to a same deployment group later on</span>
+ <span class="n">new_group</span> <span class="o">=</span> <span class="bp">False</span>
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">group</span><span class="p">:</span>
+ <span class="n">new_group</span> <span class="o">=</span> <span class="bp">True</span>
+ <span class="n">group</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_group_id_generator</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
+
+ <span class="k">if</span> <span class="n">group</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_groups</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_groups</span><span class="p">[</span><span class="n">group</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">_groups</span><span class="p">[</span><span class="n">group</span><span class="p">]</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">guids</span><span class="p">)</span>
+
+ <span class="k">def</span> <span class="nf">wait_all_and_start</span><span class="p">(</span><span class="n">group</span><span class="p">):</span>
+ <span class="c"># Function that checks if all resources are READY</span>
+ <span class="c"># before scheduling a start_with_conditions for each RM</span>
+ <span class="n">reschedule</span> <span class="o">=</span> <span class="bp">False</span>
+
+ <span class="c"># Get all guids in group</span>
+ <span class="n">guids</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_groups</span><span class="p">[</span><span class="n">group</span><span class="p">]</span>
+
+ <span class="k">for</span> <span class="n">guid</span> <span class="ow">in</span> <span class="n">guids</span><span class="p">:</span>
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">state</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span> <span class="o"><</span> <span class="n">ResourceState</span><span class="o">.</span><span class="n">READY</span><span class="p">:</span>
+ <span class="n">reschedule</span> <span class="o">=</span> <span class="bp">True</span>
+ <span class="k">break</span>
+
+ <span class="k">if</span> <span class="n">reschedule</span><span class="p">:</span>
+ <span class="n">callback</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">wait_all_and_start</span><span class="p">,</span> <span class="n">group</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"1s"</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="c"># If all resources are ready, we schedule the start</span>
+ <span class="k">for</span> <span class="n">guid</span> <span class="ow">in</span> <span class="n">guids</span><span class="p">:</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"0s"</span><span class="p">,</span> <span class="n">rm</span><span class="o">.</span><span class="n">start_with_conditions</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="n">rm</span><span class="o">.</span><span class="n">conditions</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ResourceAction</span><span class="o">.</span><span class="n">STOP</span><span class="p">):</span>
+ <span class="c"># Only if the RM has STOP conditions we</span>
+ <span class="c"># schedule a stop. Otherwise the RM will stop immediately</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"0s"</span><span class="p">,</span> <span class="n">rm</span><span class="o">.</span><span class="n">stop_with_conditions</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="n">wait_all_ready</span> <span class="ow">and</span> <span class="n">new_group</span><span class="p">:</span>
+ <span class="c"># Schedule a function to check that all resources are</span>
+ <span class="c"># READY, and only then schedule the start.</span>
+ <span class="c"># This aims at reducing the number of tasks looping in the </span>
+ <span class="c"># scheduler. </span>
+ <span class="c"># Instead of having many start tasks, we will have only one for </span>
+ <span class="c"># the whole group.</span>
+ <span class="n">callback</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">wait_all_and_start</span><span class="p">,</span> <span class="n">group</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"0s"</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
+
+ <span class="k">for</span> <span class="n">guid</span> <span class="ow">in</span> <span class="n">guids</span><span class="p">:</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="n">rm</span><span class="o">.</span><span class="n">deployment_group</span> <span class="o">=</span> <span class="n">group</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"0s"</span><span class="p">,</span> <span class="n">rm</span><span class="o">.</span><span class="n">deploy_with_conditions</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">wait_all_ready</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"0s"</span><span class="p">,</span> <span class="n">rm</span><span class="o">.</span><span class="n">start_with_conditions</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="n">rm</span><span class="o">.</span><span class="n">conditions</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">ResourceAction</span><span class="o">.</span><span class="n">STOP</span><span class="p">):</span>
+ <span class="c"># Only if the RM has STOP conditions we</span>
+ <span class="c"># schedule a stop. Otherwise the RM will stop immediately</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"0s"</span><span class="p">,</span> <span class="n">rm</span><span class="o">.</span><span class="n">stop_with_conditions</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.release"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.release">[docs]</a> <span class="k">def</span> <span class="nf">release</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">guids</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
+ <span class="sd">""" Releases all ResourceManagers in the guids list.</span>
+
+<span class="sd"> If the argument 'guids' is not given, all RMs registered</span>
+<span class="sd"> in the experiment are released.</span>
+
+<span class="sd"> :param guids: List of RM guids</span>
+<span class="sd"> :type guids: list</span>
+
+<span class="sd"> """</span>
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">==</span> <span class="n">ECState</span><span class="o">.</span><span class="n">RELEASED</span><span class="p">:</span>
+ <span class="k">return</span>
+
+ <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">guids</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+ <span class="n">guids</span> <span class="o">=</span> <span class="p">[</span><span class="n">guids</span><span class="p">]</span>
+
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">guids</span><span class="p">:</span>
+ <span class="n">guids</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">resources</span>
+
+ <span class="k">for</span> <span class="n">guid</span> <span class="ow">in</span> <span class="n">guids</span><span class="p">:</span>
+ <span class="n">rm</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="s">"0s"</span><span class="p">,</span> <span class="n">rm</span><span class="o">.</span><span class="n">release</span><span class="p">)</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">wait_released</span><span class="p">(</span><span class="n">guids</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">persist</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
+
+ <span class="k">for</span> <span class="n">guid</span> <span class="ow">in</span> <span class="n">guids</span><span class="p">:</span>
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">guid</span><span class="p">,</span> <span class="s">"hardRelease"</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">remove_resource</span><span class="p">(</span><span class="n">guid</span><span class="p">)</span>\
+
+ <span class="c"># Mark the EC state as RELEASED</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">=</span> <span class="n">ECState</span><span class="o">.</span><span class="n">RELEASED</span>
+ </div>
+<div class="viewcode-block" id="ExperimentController.shutdown"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.shutdown">[docs]</a> <span class="k">def</span> <span class="nf">shutdown</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Releases all resources and stops the ExperimentController</span>
+
+<span class="sd"> """</span>
+ <span class="c"># If there was a major failure we can't exit gracefully</span>
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">==</span> <span class="n">ECState</span><span class="o">.</span><span class="n">FAILED</span><span class="p">:</span>
+ <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">"EC failure. Can not exit gracefully"</span><span class="p">)</span>
+
+ <span class="c"># Remove all pending tasks from the scheduler queue</span>
+ <span class="k">for</span> <span class="n">tid</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span><span class="o">.</span><span class="n">pending</span><span class="p">):</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">tid</span><span class="p">)</span>
+
+ <span class="c"># Remove pending tasks from the workers queue</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_runner</span><span class="o">.</span><span class="n">empty</span><span class="p">()</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
+
+ <span class="c"># Mark the EC state as TERMINATED</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">=</span> <span class="n">ECState</span><span class="o">.</span><span class="n">TERMINATED</span>
+
+ <span class="c"># Stop processing thread</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_stop</span> <span class="o">=</span> <span class="bp">True</span>
+
+ <span class="c"># Notify condition to wake up the processing thread</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_notify</span><span class="p">()</span>
+
+ <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_thread</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_thread</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
+</div>
+<div class="viewcode-block" id="ExperimentController.schedule"><a class="viewcode-back" href="../../../_layout/nepi.execution.html#nepi.execution.ec.ExperimentController.schedule">[docs]</a> <span class="k">def</span> <span class="nf">schedule</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">date</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">track</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
+ <span class="sd">""" Schedules a callback to be executed at time 'date'.</span>
+
+<span class="sd"> :param date: string containing execution time for the task.</span>
+<span class="sd"> It can be expressed as an absolute time, using</span>
+<span class="sd"> timestamp format, or as a relative time matching</span>
+<span class="sd"> ^\d+.\d+(h|m|s|ms|us)$</span>
+
+<span class="sd"> :param callback: code to be executed for the task. Must be a</span>
+<span class="sd"> Python function, and receives args and kwargs</span>
+<span class="sd"> as arguments.</span>
+
+<span class="sd"> :param track: if set to True, the task will be retrievable with</span>
+<span class="sd"> the get_task() method</span>
+
+<span class="sd"> :return : The Id of the task</span>
+<span class="sd"> :rtype: int</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="n">timestamp</span> <span class="o">=</span> <span class="n">stabsformat</span><span class="p">(</span><span class="n">date</span><span class="p">)</span>
+ <span class="n">task</span> <span class="o">=</span> <span class="n">Task</span><span class="p">(</span><span class="n">timestamp</span><span class="p">,</span> <span class="n">callback</span><span class="p">)</span>
+ <span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="n">track</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_tasks</span><span class="p">[</span><span class="n">task</span><span class="o">.</span><span class="n">id</span><span class="p">]</span> <span class="o">=</span> <span class="n">task</span>
+
+ <span class="c"># Notify condition to wake up the processing thread</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_notify</span><span class="p">()</span>
+
+ <span class="k">return</span> <span class="n">task</span><span class="o">.</span><span class="n">id</span>
+ </div>
+ <span class="k">def</span> <span class="nf">_process</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Process scheduled tasks.</span>
+
+<span class="sd"> .. note::</span>
+<span class="sd"> </span>
+<span class="sd"> Tasks are scheduled by invoking the schedule method with a target </span>
+<span class="sd"> callback and an execution time. </span>
+<span class="sd"> The schedule method creates a new Task object with that callback </span>
+<span class="sd"> and execution time, and pushes it into the '_scheduler' queue. </span>
+<span class="sd"> The execution time and the order of arrival of tasks are used </span>
+<span class="sd"> to order the tasks in the queue.</span>
+
+<span class="sd"> The _process method is executed in an independent thread held by </span>
+<span class="sd"> the ExperimentController for as long as the experiment is running.</span>
+<span class="sd"> This method takes tasks from the '_scheduler' queue in a loop </span>
+<span class="sd"> and processes them in parallel using multithreading. </span>
+<span class="sd"> The environmental variable NEPI_NTHREADS can be used to control</span>
+<span class="sd"> the number of threads used to process tasks. The default value is </span>
+<span class="sd"> 50.</span>
+
+<span class="sd"> To execute tasks in parallel, a ParallelRunner (PR) object is used.</span>
+<span class="sd"> This object keeps a pool of threads (workers), and a queue of tasks</span>
+<span class="sd"> scheduled for 'immediate' execution. </span>
+<span class="sd"> </span>
+<span class="sd"> On each iteration, the '_process' loop will take the next task that </span>
+<span class="sd"> is scheduled for 'future' execution from the '_scheduler' queue, </span>
+<span class="sd"> and if the execution time of that task is >= to the current time, </span>
+<span class="sd"> it will push that task into the PR for 'immediate execution'. </span>
+<span class="sd"> As soon as a worker is free, the PR will assign the next task to</span>
+<span class="sd"> that worker.</span>
+
+<span class="sd"> Upon receiving a task to execute, each PR worker (thread) will </span>
+<span class="sd"> invoke the _execute method of the EC, passing the task as </span>
+<span class="sd"> argument. </span>
+<span class="sd"> The _execute method will then invoke task.callback inside a </span>
+<span class="sd"> try/except block. If an exception is raised by the tasks.callback, </span>
+<span class="sd"> it will be trapped by the try block, logged to standard error </span>
+<span class="sd"> (usually the console), and the task will be marked as failed.</span>
+
+<span class="sd"> """</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">_nthreads</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"NEPI_NTHREADS"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_nthreads</span><span class="p">)))</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_runner</span> <span class="o">=</span> <span class="n">ParallelRun</span><span class="p">(</span><span class="n">maxthreads</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nthreads</span><span class="p">)</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_runner</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+
+ <span class="k">while</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stop</span><span class="p">:</span>
+ <span class="k">try</span><span class="p">:</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
+
+ <span class="n">task</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
+
+ <span class="k">if</span> <span class="ow">not</span> <span class="n">task</span><span class="p">:</span>
+ <span class="c"># No task to execute. Wait for a new task to be scheduled.</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
+ <span class="k">else</span><span class="p">:</span>
+ <span class="c"># The task timestamp is in the future. Wait for timeout </span>
+ <span class="c"># or until another task is scheduled.</span>
+ <span class="n">now</span> <span class="o">=</span> <span class="n">tnow</span><span class="p">()</span>
+ <span class="k">if</span> <span class="n">now</span> <span class="o"><</span> <span class="n">task</span><span class="o">.</span><span class="n">timestamp</span><span class="p">:</span>
+ <span class="c"># Calculate timeout in seconds</span>
+ <span class="n">timeout</span> <span class="o">=</span> <span class="n">tdiffsec</span><span class="p">(</span><span class="n">task</span><span class="o">.</span><span class="n">timestamp</span><span class="p">,</span> <span class="n">now</span><span class="p">)</span>
+
+ <span class="c"># Re-schedule task with the same timestamp</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_scheduler</span><span class="o">.</span><span class="n">schedule</span><span class="p">(</span><span class="n">task</span><span class="p">)</span>
+
+ <span class="n">task</span> <span class="o">=</span> <span class="bp">None</span>
+
+ <span class="c"># Wait timeout or until a new task awakes the condition</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
+
+ <span class="k">if</span> <span class="n">task</span><span class="p">:</span>
+ <span class="c"># Process tasks in parallel</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_runner</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_execute</span><span class="p">,</span> <span class="n">task</span><span class="p">)</span>
+ <span class="k">except</span><span class="p">:</span>
+ <span class="kn">import</span> <span class="nn">traceback</span>
+ <span class="n">err</span> <span class="o">=</span> <span class="n">traceback</span><span class="o">.</span><span class="n">format_exc</span><span class="p">()</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Error while processing tasks in the EC: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">err</span><span class="p">)</span>
+
+ <span class="c"># Set the EC to FAILED state </span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_state</span> <span class="o">=</span> <span class="n">ECState</span><span class="o">.</span><span class="n">FAILED</span>
+
+ <span class="c"># Set the FailureManager failure level to EC failure</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_fm</span><span class="o">.</span><span class="n">set_ec_failure</span><span class="p">()</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">"Exiting the task processing loop ... "</span><span class="p">)</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">_runner</span><span class="o">.</span><span class="n">sync</span><span class="p">()</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_runner</span><span class="o">.</span><span class="n">destroy</span><span class="p">()</span>
+
+ <span class="k">def</span> <span class="nf">_execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">task</span><span class="p">):</span>
+ <span class="sd">""" Executes a single task. </span>
+
+<span class="sd"> :param task: Object containing the callback to execute</span>
+<span class="sd"> :type task: Task</span>
+
+<span class="sd"> """</span>
+ <span class="k">try</span><span class="p">:</span>
+ <span class="c"># Invoke callback</span>
+ <span class="n">task</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">task</span><span class="o">.</span><span class="n">callback</span><span class="p">()</span>
+ <span class="n">task</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">DONE</span>
+ <span class="k">except</span><span class="p">:</span>
+ <span class="kn">import</span> <span class="nn">traceback</span>
+ <span class="n">err</span> <span class="o">=</span> <span class="n">traceback</span><span class="o">.</span><span class="n">format_exc</span><span class="p">()</span>
+ <span class="n">task</span><span class="o">.</span><span class="n">result</span> <span class="o">=</span> <span class="n">err</span>
+ <span class="n">task</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">TaskStatus</span><span class="o">.</span><span class="n">ERROR</span>
+
+ <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">"Error occurred while executing task: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">err</span><span class="p">)</span>
+
+ <span class="k">def</span> <span class="nf">_notify</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+ <span class="sd">""" Awakes the processing thread if it is blocked waiting </span>
+<span class="sd"> for new tasks to arrive</span>
+<span class="sd"> </span>
+<span class="sd"> """</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span><span class="o">.</span><span class="n">notify</span><span class="p">()</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_cond</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
+
+ <span class="k">def</span> <span class="nf">_build_from_netgraph</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">add_node_callback</span><span class="p">,</span> <span class="n">add_edge_callback</span><span class="p">,</span>
+ <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+ <span class="sd">""" Automates experiment description using a NetGraph instance.</span>
+<span class="sd"> """</span>
+ <span class="bp">self</span><span class="o">.</span><span class="n">_netgraph</span> <span class="o">=</span> <span class="n">NetGraph</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="n">add_node_callback</span><span class="p">:</span>
+ <span class="c">### Add resources to the EC</span>
+ <span class="k">for</span> <span class="n">nid</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">netgraph</span><span class="o">.</span><span class="n">nodes</span><span class="p">():</span>
+ <span class="n">add_node_callback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nid</span><span class="p">)</span>
+
+ <span class="k">if</span> <span class="n">add_edge_callback</span><span class="p">:</span>
+ <span class="c">#### Add connections between resources</span>
+ <span class="k">for</span> <span class="n">nid1</span><span class="p">,</span> <span class="n">nid2</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">netgraph</span><span class="o">.</span><span class="n">edges</span><span class="p">():</span>
+ <span class="n">add_edge_callback</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nid1</span><span class="p">,</span> <span class="n">nid2</span><span class="p">)</span>
+</pre></div></div>
+
+ </div>
+ </div>
+ </div>
+ <div class="clearer"></div>
+ </div>
+ <div class="related">
+ <h3>Navigation</h3>
+ <ul>
+ <li class="right" style="margin-right: 10px">
+ <a href="../../../genindex.html" title="General Index"
+ >index</a></li>
+ <li class="right" >
+ <a href="../../../py-modindex.html" title="Python Module Index"
+ >modules</a> |</li>
+ <li><a href="../../../index.html">NEPI 3.2 documentation</a> »</li>
+ <li><a href="../../index.html" >Module code</a> »</li>
+ </ul>
+ </div>
+ <div class="footer">
+ © Copyright 2014, Alina Quereilhac, Lucia Guevgeozian Odizzio, Julien Tribino.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.3.
+ </div>
+ </body>
+</html>
\ No newline at end of file