rename src/nepi/ into just nepi/
[nepi.git] / nepi / resources / ns3 / ns3wrapper_debug.py
diff --git a/nepi/resources/ns3/ns3wrapper_debug.py b/nepi/resources/ns3/ns3wrapper_debug.py
new file mode 100644 (file)
index 0000000..70a84b7
--- /dev/null
@@ -0,0 +1,175 @@
+#
+#    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 version 2 as
+#    published by the Free Software Foundation;
+#
+#    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>
+
+
+############ METHODS DEBUG NS3WRAPPER EXECUTION
+##
+## The ns3wrapper works in ditributed mode, receiving instructions from
+## a remote client. This makes it very hard to debug scripting errors 
+## in the client side. To simplify error debugging, when set to debug mode,
+## the ns3wrapper dumps every executed line to a script that can be then
+## executed locally to reproduce and debug the experiment.
+##
+###########################################################################
+
+import logging
+
+SINGLETON = "singleton::"
+
+class NS3WrapperDebuger(object):
+    def __init__(self, enabled):
+        super(NS3WrapperDebuger, self).__init__()
+        self._enabled = enabled
+        self._script_path = "debug.py"
+
+        self.dump_header()
+
+    @property
+    def enabled(self):
+        return self._enabled
+
+    @property
+    def script_path(self):
+        return self._script_path
+
+    def dump_to_script(self, command):
+        with open(self.script_path, "a") as f:
+            f.write("%s" % command)
+
+    def dump_header(self):
+        if not self.enabled:
+            return
+
+        header = """
+from ns3wrapper import NS3Wrapper
+
+wrapper = NS3Wrapper()
+
+"""
+        self.dump_to_script(header)
+
+    def dump_factory(self, uuid, type_name, kwargs):
+        if not self.enabled:
+            return
+
+        command = ("kwargs = %(kwargs)s\n"
+                "%(uuid)s = wrapper.factory(%(type_name)s, **kwargs)\n\n" 
+                ) % dict({
+                 "uuid": self.format_value(uuid),
+                 "type_name": self.format_value(type_name),
+                 "kwargs": self.format_kwargs(kwargs)
+                })
+
+        self.dump_to_script(command)
+
+    def dump_create(self, uuid, clazzname, args):
+        if not self.enabled:
+            return
+
+        command = ("args = %(args)s\n"
+                "%(uuid)s = wrapper.create(%(clazzname)s, *args)\n\n" 
+                ) % dict({
+                 "uuid": self.format_value(uuid),
+                 "clazzname": self.format_value(clazzname),
+                 "args": self.format_args(args),
+                })
+
+        self.dump_to_script(command)
+
+    def dump_invoke(self, newuuid, uuid, operation, args, kwargs):
+        if not self.enabled:
+            return
+
+        command = ("args = %(args)s\n"
+                   "kwargs = %(kwargs)s\n"
+                   "%(newuuid)s = wrapper.invoke(%(uuid)s, %(operation)s, *args, **kwargs)\n\n" 
+                ) % dict({
+                 "newuuid": self.format_value(newuuid) if newuuid else "nothing",
+                 "uuid": self.format_value(uuid),
+                 "operation": self.format_value(operation),
+                 "args": self.format_args(args),
+                 "kwargs": self.format_kwargs(kwargs),
+                })
+
+        self.dump_to_script(command)
+
+    def dump_set(self, uuid, name, value):
+        if not self.enabled:
+            return
+
+        command = ("wrapper.set(%(uuid)s, %(name)s, %(value)s)\n\n" 
+                ) % dict({
+                 "uuid": self.format_value(uuid),
+                 "name": self.format_value(name),
+                 "value": self.format_value(value),
+                })
+
+        self.dump_to_script(command)
+
+    def dump_get(self, uuid, name):
+        if not self.enabled:
+            return
+
+        command = ("wrapper.get(%(uuid)s, %(name)s)\n\n" 
+                ) % dict({
+                 "uuid": self.format_value(uuid),
+                 "name": self.format_value(name),
+                })
+        
+        self.dump_to_script(command)
+
+    def dump_start(self):
+        if not self.enabled:
+            return
+
+        command = "wrapper.start()\n\n"
+        self.dump_to_script(command)
+
+    def dump_stop(self, time = None):
+        if not self.enabled:
+            return
+
+        command = ("wrapper.stop(time=%(time)s)\n\n" 
+                ) % dict({
+                 "time": self.format_value(time) if time else "None",
+                })
+
+        self.dump_to_script(command)
+
+    def dump_shutdown(self):
+        if not self.enabled:
+            return
+
+        command = "wrapper.shutdown()\n\n"
+        self.dump_to_script(command)
+
+    def format_value(self, value):
+        if isinstance(value, str) and value.startswith("uuid"):
+            return value.replace("-", "")
+
+        import pprint 
+        return pprint.pformat(value)
+
+    def format_args(self, args):
+        return "[%s]" % ",".join(self.format_value(arg) for arg in args)
+
+    def format_kwargs(self, kwargs):
+        fkwargs = ["%s: %s" % (self.format_value(k), self.format_value(v)) for (k, v) in kwargs.items()]
+        
+        return  "dict({%s})" % ",".join(fkwargs)
+