from nepi.execution.scheduler import HeapScheduler, Task, TaskStatus
from nepi.execution.trace import TraceAttr
from nepi.util.serializer import ECSerializer, SFormats
+from nepi.util.plotter import ECPlotter, PFormats
# TODO: use multiprocessing instead of threading
# TODO: Allow to reconnect to a running experiment instance! (reconnect mode vs deploy mode)
time.sleep(0.5)
+ def plot(self, fpath = None, format= PFormats.FIGURE, persist = False):
+ plotter = ECPlotter()
+ fpath = plotter.plot(self, fpath = fpath, format= format,
+ persist = persist)
+ return fpath
+
def serialize(self, format = SFormats.XML):
serializer = ECSerializer()
sec = serializer.load(self, format = format)
--- /dev/null
+#
+# NEPI, a framework to manage network experiments
+# Copyright (C) 2013 INRIA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
+
+import networkx
+import os
+
+class PFormats:
+ DOT = "dot"
+ FIGURE = "figure"
+
+class ECPlotter(object):
+ def plot(self, ec, fpath = None, format= PFormats.FIGURE, persist = False):
+ graph, labels = self._ec2graph(ec)
+
+ add_extension = False
+
+ if persist and not fpath:
+ import tempfile
+ dirpath = tempfile.mkdtemp()
+ fpath = os.path.join(dirpath, "%s_%s" % (ec.exp_id, ec.run_id))
+ add_extension = True
+
+ if format == PFormats.FIGURE:
+ import matplotlib.pyplot as plt
+ pos = networkx.graphviz_layout(graph, prog="neato")
+ networkx.draw(graph, pos = pos, node_color="white",
+ node_size = 500, with_labels=True)
+
+ label = "\n".join(map(lambda v: "%s: %s" % (v[0], v[1]), labels.iteritems()))
+ plt.annotate(label, xy=(0.0, 0.95), xycoords='axes fraction')
+
+ if persist:
+ if add_extension:
+ fpath += ".png"
+
+ plt.savefig(fpath, bbox_inches="tight")
+ else:
+ plt.show()
+
+ elif format == PFormats.DOT:
+ if persist:
+ if add_extension:
+ fpath += ".dot"
+
+ networkx.write_dot(graph, fpath)
+ else:
+ import subprocess
+ subprocess.call(["dot", "-Tps", fpath, "-o", "%s.ps" % fpath])
+ subprocess.call(["evince","%s.ps" % fpath])
+
+ return fpath
+
+ def _ec2graph(self, ec):
+ graph = networkx.Graph(graph = dict(overlap = "false"))
+
+ labels = dict()
+ connections = set()
+
+ for guid, rm in ec._resources.iteritems():
+ label = rm.get_rtype()
+
+ graph.add_node(guid,
+ label = "%d %s" % (guid, label),
+ width = 50/72.0, # 1 inch = 72 points
+ height = 50/72.0,
+ shape = "circle")
+
+ labels[guid] = label
+
+ for guid2 in rm.connections:
+ # Avoid adding a same connection twice
+ if (guid2, guid) not in connections:
+ connections.add((guid, guid2))
+
+ for (guid1, guid2) in connections:
+ graph.add_edge(guid1, guid2)
+
+ return graph, labels
+++ /dev/null
-#!/usr/bin/env python
-#
-# NEPI, a framework to manage network experiments
-# Copyright (C) 2013 INRIA
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
-
-
-from nepi.design.box import Box
-from nepi.util.plot import Plotter
-
-import subprocess
-import unittest
-
-class BoxPlotTestCase(unittest.TestCase):
- def xtest_plot(self):
- """ XXX: This test is interactive, it will open an evince instance,
- so it should not run automatically """
- node1 = Box(label="node1")
- ping1 = Box(label="ping")
- mobility1 = Box(label="mob1")
- node2 = Box(label="node2")
- mobility2 = Box(label="mob2")
- iface1 = Box(label="iface1")
- iface2 = Box(label="iface2")
- channel = Box(label="chan")
-
- node1.connect(ping1)
- node1.connect(mobility1)
- node1.connect(iface1)
- channel.connect(iface1)
- channel.connect(iface2)
- node2.connect(iface2)
- node2.connect(mobility2)
-
- plotter = Plotter(node1)
- fname = plotter.plot()
- subprocess.call(["dot", "-Tps", fname, "-o", "%s.ps"%fname])
- subprocess.call(["evince","%s.ps"%fname])
-
-if __name__ == '__main__':
- unittest.main()
-
--- /dev/null
+#!/usr/bin/env python
+#
+# NEPI, a framework to manage network experiments
+# Copyright (C) 2013 INRIA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
+
+from nepi.execution.ec import ExperimentController
+from nepi.execution.resource import ResourceManager, ResourceState, \
+ clsinit_copy, ResourceAction, ResourceFactory
+from nepi.util.plotter import PFormats
+
+import os
+import tempfile
+import time
+import unittest
+
+reschedule_delay = "0.5s"
+deploy_time = 0
+run_time = 0
+
+class Link(ResourceManager):
+ _rtype = "dummy::Link"
+ def do_deploy(self):
+ time.sleep(deploy_time)
+ super(Link, self).do_deploy()
+ self.logger.debug(" -------- DEPLOYED ------- ")
+
+class Interface(ResourceManager):
+ _rtype = "dummy::Interface"
+
+ def do_deploy(self):
+ node = self.get_connected(Node.get_rtype())[0]
+ link = self.get_connected(Link.get_rtype())[0]
+
+ if node.state < ResourceState.READY or \
+ link.state < ResourceState.READY:
+ self.ec.schedule(reschedule_delay, self.deploy)
+ self.logger.debug(" -------- RESCHEDULING ------- ")
+ else:
+ time.sleep(deploy_time)
+ super(Interface, self).do_deploy()
+ self.logger.debug(" -------- DEPLOYED ------- ")
+
+class Node(ResourceManager):
+ _rtype = "dummy::Node"
+
+ def do_deploy(self):
+ self.logger.debug(" -------- DO_DEPLOY ------- ")
+ time.sleep(deploy_time)
+ super(Node, self).do_deploy()
+ self.logger.debug(" -------- DEPLOYED ------- ")
+
+class Application(ResourceManager):
+ _rtype = "dummy::Application"
+
+ def do_deploy(self):
+ node = self.get_connected(Node.get_rtype())[0]
+
+ if node.state < ResourceState.READY:
+ self.ec.schedule(reschedule_delay, self.deploy)
+ self.logger.debug(" -------- RESCHEDULING ------- ")
+ else:
+ time.sleep(deploy_time)
+ super(Application, self).do_deploy()
+ self.logger.debug(" -------- DEPLOYED ------- ")
+
+ def do_start(self):
+ super(Application, self).do_start()
+ time.sleep(run_time)
+ self.ec.schedule("0s", self.stop)
+
+ResourceFactory.register_type(Application)
+ResourceFactory.register_type(Node)
+ResourceFactory.register_type(Interface)
+ResourceFactory.register_type(Link)
+
+class PlotterTestCase(unittest.TestCase):
+ def test_serialize(self):
+ node_count = 4
+ app_count = 2
+
+ ec = ExperimentController(exp_id = "plotter-test")
+
+ # Add simulated nodes and applications
+ nodes = list()
+ apps = list()
+ ifaces = list()
+
+ for i in xrange(node_count):
+ node = ec.register_resource("dummy::Node")
+ nodes.append(node)
+
+ iface = ec.register_resource("dummy::Interface")
+ ec.register_connection(node, iface)
+ ifaces.append(iface)
+
+ for i in xrange(app_count):
+ app = ec.register_resource("dummy::Application")
+ ec.register_connection(node, app)
+ apps.append(app)
+
+ link = ec.register_resource("dummy::Link")
+
+ for iface in ifaces:
+ ec.register_connection(link, iface)
+
+ fpath = ec.plot(persist = True)
+ statinfo = os.stat(fpath)
+ size = statinfo.st_size
+ self.assertTrue(size > 0)
+ self.assertTrue(fpath.endswith(".png"))
+
+ fpath = ec.plot(persist = True, format = PFormats.DOT)
+ statinfo = os.stat(fpath)
+ size = statinfo.st_size
+ self.assertTrue(size > 0)
+ self.assertTrue(fpath.endswith(".dot"))
+
+ print fpath
+
+
+if __name__ == '__main__':
+ unittest.main()
+
ResourceFactory.register_type(Interface)
ResourceFactory.register_type(Link)
-class SerializeTestCase(unittest.TestCase):
+class SerializerTestCase(unittest.TestCase):
def test_serialize(self):
node_count = 4
app_count = 2