systematic use of context managers for dealing with files instead of open()/close...
[nepi.git] / src / nepi / resources / netns / netnswrapper_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 NETNSWRAPPER EXECUTION
21 ##
22 ## The netnswrapper 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 class NetNSWrapperDebuger(object):
33     def __init__(self, enabled):
34         super(NetNSWrapperDebuger, self).__init__()
35         self._enabled = enabled
36         self._script_path = "debug.py"
37
38         self.dump_header()
39
40     @property
41     def enabled(self):
42         return self._enabled
43
44     @property
45     def script_path(self):
46         return self._script_path
47
48     def dump_to_script(self, command):
49         with open(self.script_path, "a") as f:
50             f.write("%s" % command)
51
52     def dump_header(self):
53         if not self.enabled:
54             return
55
56         header = """
57 from netnswrapper import NetNSWrapper
58
59 wrapper = NS3Wrapper()
60
61 """
62         self.dump_to_script(header)
63
64     def dump_factory(self, uuid, type_name, kwargs):
65         if not self.enabled:
66             return
67
68         command = ("kwargs = %(kwargs)s\n"
69                 "%(uuid)s = wrapper.factory(%(type_name)s, **kwargs)\n\n" 
70                 ) % dict({
71                  "uuid": self.format_value(uuid),
72                  "type_name": self.format_value(type_name),
73                  "kwargs": self.format_kwargs(kwargs)
74                 })
75
76         self.dump_to_script(command)
77
78     def dump_create(self, uuid, clazzname, args):
79         if not self.enabled:
80             return
81
82         command = ("args = %(args)s\n"
83                 "%(uuid)s = wrapper.create(%(clazzname)s, *args)\n\n" 
84                 ) % dict({
85                  "uuid": self.format_value(uuid),
86                  "clazzname": self.format_value(clazzname),
87                  "args": self.format_args(args),
88                 })
89
90         self.dump_to_script(command)
91
92     def dump_invoke(self, newuuid, uuid, operation, args, kwargs):
93         if not self.enabled:
94             return
95
96         command = ("args = %(args)s\n"
97                    "kwargs = %(kwargs)s\n"
98                    "%(newuuid)s = wrapper.invoke(%(uuid)s, %(operation)s, *args, **kwargs)\n\n" 
99                 ) % dict({
100                  "newuuid": self.format_value(newuuid) if newuuid else "nothing",
101                  "uuid": self.format_value(uuid),
102                  "operation": self.format_value(operation),
103                  "args": self.format_args(args),
104                  "kwargs": self.format_kwargs(kwargs),
105                 })
106
107         self.dump_to_script(command)
108
109     def dump_set(self, uuid, name, value):
110         if not self.enabled:
111             return
112
113         command = ("wrapper.set(%(uuid)s, %(name)s, %(value)s)\n\n" 
114                 ) % dict({
115                  "uuid": self.format_value(uuid),
116                  "name": self.format_value(name),
117                  "value": self.format_value(value),
118                 })
119
120         self.dump_to_script(command)
121
122     def dump_get(self, uuid, name):
123         if not self.enabled:
124             return
125
126         command = ("wrapper.get(%(uuid)s, %(name)s)\n\n" 
127                 ) % dict({
128                  "uuid": self.format_value(uuid),
129                  "name": self.format_value(name),
130                 })
131         
132         self.dump_to_script(command)
133
134     def dump_shutdown(self):
135         if not self.enabled:
136             return
137
138         command = "wrapper.shutdown()\n\n"
139         self.dump_to_script(command)
140
141     def format_value(self, value):
142         if isinstance(value, str) and value.startswith("uuid"):
143             return value.replace("-", "")
144
145         import pprint 
146         return pprint.pformat(value)
147
148     def format_args(self, args):
149         fargs = map(self.format_value, args)
150         return "[%s]" % ",".join(fargs)
151
152     def format_kwargs(self, kwargs):
153         fkwargs = map(lambda (k,w): 
154                "%s: %s" % (self.format_value(k), self.format_value(w)), 
155             kwargs.iteritems())
156         
157         return  "dict({%s})" % ",".join(fkwargs)
158