ff8d0de878a2c86160cd17ac87e36fe8fe8a20f7
[nepi.git] / src / nepi / resources / ns3 / ns3wrapper_debug.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
5 #    This program is free software: you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License as published by
7 #    the Free Software Foundation, either version 3 of the License, or
8 #    (at your option) any later version.
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19
20
21 ############ METHODS DEBUG NS3WRAPPER EXECUTION
22 ##
23 ## The ns3wrapper works in ditributed mode, receiving instructions from
24 ## a remote client. This makes it very hard to debug scripting errors 
25 ## in the client side. To simplify error debugging, when set to debug mode,
26 ## the ns3wrapper dumps every executed line to a script that can be then
27 ## executed locally to reproduce and debug the experiment.
28 ##
29 ###########################################################################
30
31 import logging
32
33 SINGLETON = "singleton::"
34
35 class NS3WrapperDebuger(object):
36     def __init__(self, enabled):
37         super(NS3WrapperDebuger, self).__init__()
38         self._enabled = enabled
39         self._script_path = "debug.py"
40
41         self.dump_header()
42
43     @property
44     def enabled(self):
45         return self._enabled
46
47     @property
48     def script_path(self):
49         return self._script_path
50
51     def dump_to_script(self, command):
52         f = open(self.script_path, "a")
53         f.write("%s" % command)
54         f.close()
55
56     def dump_header(self):
57         if not self.enabled:
58             return
59
60         header = """
61 from ns3wrapper import NS3Wrapper
62
63 wrapper = NS3Wrapper()
64
65 """
66         self.dump_to_script(header)
67
68     def dump_factory(self, uuid, type_name, kwargs):
69         if not self.enabled:
70             return
71
72         command = ("kwargs = %(kwargs)s\n"
73                 "%(uuid)s = wrapper.factory(%(type_name)s, **kwargs)\n\n" 
74                 ) % dict({
75                  "uuid": self.format_value(uuid),
76                  "type_name": self.format_value(type_name),
77                  "kwargs": self.format_kwargs(kwargs)
78                 })
79
80         self.dump_to_script(command)
81
82     def dump_create(self, uuid, clazzname, args):
83         if not self.enabled:
84             return
85
86         command = ("args = %(args)s\n"
87                 "%(uuid)s = wrapper.create(%(clazzname)s, *args)\n\n" 
88                 ) % dict({
89                  "uuid": self.format_value(uuid),
90                  "clazzname": self.format_value(clazzname),
91                  "args": self.format_args(args),
92                 })
93
94         self.dump_to_script(command)
95
96     def dump_invoke(self, newuuid, uuid, operation, args, kwargs):
97         if not self.enabled:
98             return
99
100         command = ("args = %(args)s\n"
101                    "kwargs = %(kwargs)s\n"
102                    "%(newuuid)s = wrapper.invoke(%(uuid)s, %(operation)s, *args, **kwargs)\n\n" 
103                 ) % dict({
104                  "newuuid": self.format_value(newuuid) if newuuid else "nothing",
105                  "uuid": self.format_value(uuid),
106                  "operation": self.format_value(operation),
107                  "args": self.format_args(args),
108                  "kwargs": self.format_kwargs(kwargs),
109                 })
110
111         self.dump_to_script(command)
112
113     def dump_set(self, uuid, name, value):
114         if not self.enabled:
115             return
116
117         command = ("wrapper.set(%(uuid)s, %(name)s, %(value)s)\n\n" 
118                 ) % dict({
119                  "uuid": self.format_value(uuid),
120                  "name": self.format_value(name),
121                  "value": self.format_value(value),
122                 })
123
124         self.dump_to_script(command)
125
126     def dump_get(self, uuid, name):
127         if not self.enabled:
128             return
129
130         command = ("wrapper.get(%(uuid)s, %(name)s)\n\n" 
131                 ) % dict({
132                  "uuid": self.format_value(uuid),
133                  "name": self.format_value(name),
134                 })
135         
136         self.dump_to_script(command)
137
138     def dump_start(self):
139         if not self.enabled:
140             return
141
142         command = "wrapper.start()\n\n"
143         self.dump_to_script(command)
144
145     def dump_stop(self, time = None):
146         if not self.enabled:
147             return
148
149         command = ("wrapper.stop(time=%(time)s)\n\n" 
150                 ) % dict({
151                  "time": self.format_value(time) if time else "None",
152                 })
153
154         self.dump_to_script(command)
155
156     def dump_shutdown(self):
157         if not self.enabled:
158             return
159
160         command = "wrapper.shutdown()\n\n"
161         self.dump_to_script(command)
162
163     def format_value(self, value):
164         if isinstance(value, str) and value.startswith("uuid"):
165             return value.replace("-", "")
166
167         import pprint 
168         return pprint.pformat(value)
169
170     def format_args(self, args):
171         fargs = map(self.format_value, args)
172         return "[%s]" % ",".join(fargs)
173
174     def format_kwargs(self, kwargs):
175         fkwargs = map(lambda (k,w): 
176                "%s: %s" % (self.format_value(k), self.format_value(w)), 
177             kwargs.iteritems())
178         
179         return  "dict({%s})" % ",".join(fkwargs)
180