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