1737f141d1c3272d86cb706da777e2871ca319f7
[nepi.git] / src / nepi / util / parser / base.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import sys
5
6 class ExperimentData(object):
7     def __init__(self):
8         self.data = dict()
9     
10     def __repr__(self):
11         return "%s(%r)" % (self.__class__, self.data)
12     
13     def __str__(self):
14         from pprint import pformat
15         return "%s:%s" % (self.__class__, pformat(self.data))
16
17     @property
18     def guids(self):
19         return self.data.keys()
20
21     def add_testbed_data(self, guid, testbed_id, testbed_version):
22         testbed_data = dict()
23         testbed_data["testbed_id"] = testbed_id
24         testbed_data["testbed_version"] = testbed_version
25         self.data[guid] = testbed_data
26
27     def add_box_data(self, guid, testbed_guid, factory_id):
28         box_data = dict()
29         box_data["testbed_guid"] = testbed_guid
30         box_data["factory_id"] = factory_id
31         self.data[guid] = box_data
32
33     def add_graphical_info_data(self, guid, x, y, width, height, label):
34         data = self.data[guid]
35         if not "graphical_info" in data:
36             data["graphical_info"] = dict()
37         graphical_info_data = data["graphical_info"]
38         graphical_info_data["x"] = x
39         graphical_info_data["y"] = y
40         graphical_info_data["width"] = width
41         graphical_info_data["height"] = height
42         graphical_info_data["label"] = label
43
44     def add_factory_attribute_data(self, guid, name, value):
45         data = self.data[guid]
46         if not "factory_attributes" in data:
47             data["factory_attributes"] = dict()
48         factory_attributes_data = data["factory_attributes"]
49         factory_attributes_data[name] = value
50
51     def add_attribute_data(self, guid, name, value):
52         data = self.data[guid]
53         if not "attributes" in data:
54             data["attributes"] = dict()
55         attributes_data = data["attributes"]
56         attributes_data[name] = value
57
58     def add_trace_data(self, guid, trace_name):
59         data = self.data[guid]
60         if not "traces" in data:
61             data["traces"] = list()
62         traces_data = data["traces"]
63         traces_data.append(trace_name)
64
65     def add_connection_data(self, guid, connector_type_name, other_guid,
66             other_connector_type_name):
67         data = self.data[guid]
68         if not "connections" in data:
69             data["connections"] = dict()
70         connections_data = data["connections"]
71         if not connector_type_name in connections_data:
72             connections_data[connector_type_name] = dict()
73         connection_data = connections_data[connector_type_name]
74         connection_data[other_guid] = other_connector_type_name
75
76     def add_address_data(self, guid, autoconf, address, netprefix, 
77             broadcast):
78         data = self.data[guid]
79         if not "addresses" in data:
80             data["addresses"] = list()
81         addresses_data = data["addresses"]
82         address_data = dict()
83         if autoconf:
84             address_data["AutoConfigure"] = autoconf
85         if address:
86             address_data["Address"] = address
87         address_data["NetPrefix"] = netprefix
88         if broadcast:
89             address_data["Broadcast"] = broadcast
90         addresses_data.append(address_data)
91
92     def add_route_data(self, guid, destination, netprefix, nexthop): 
93         data = self.data[guid]
94         if not "routes" in data:
95             data["routes"] = list()
96         routes_data = data["routes"]
97         route_data = dict({
98             "Destination": destination,
99             "NetPrefix": netprefix, 
100             "NextHop": nexthop 
101             })
102         routes_data.append(route_data)
103
104     def is_testbed_data(self, guid):
105         return True if "testbed_id" in self.data[guid] else None
106
107     def get_testbed_data(self, guid):
108         testbed_data = self.data[guid]
109         return (testbed_data["testbed_id"], testbed_data["testbed_version"])
110
111     def get_box_data(self, guid):
112         box_data = self.data[guid]
113         return (box_data["testbed_guid"], box_data["factory_id"])
114
115     def get_graphical_info_data(self, guid):
116         data = self.data[guid]
117         if not "graphical_info" in data:
118             return (0, 0, 0, 0, "") 
119         graphical_info_data = data["graphical_info"]
120         return (graphical_info_data["x"],
121                 graphical_info_data["y"],
122                 graphical_info_data["width"],
123                 graphical_info_data["height"],
124                 graphical_info_data["label"])
125
126     def get_factory_attribute_data(self, guid):
127         data = self.data[guid]
128         if not "factory_attributes" in data:
129             return []
130         factory_attributes_data = data["factory_attributes"]
131         return [(name, value) for name, value \
132                 in factory_attributes_data.iteritems()]
133
134     def get_attribute_data(self, guid, attribute=None, default=None):
135         data = self.data[guid]
136         if not "attributes" in data:
137             if attribute is None:
138                 return []
139             else:
140                 return None
141         attributes_data = data["attributes"]
142         if attribute is None:
143             return [(name, value) for name, value \
144                     in attributes_data.iteritems()]
145         else:
146             return attributes_data.get(attribute, default)
147
148     def set_attribute_data(self, guid, attribute, value):
149         data = self.data[guid]
150         if not "attributes" in data:
151             raise KeyError, "No attributes in reference OBJECT %r" % (guid,)
152         attributes_data = data["attributes"]
153         attributes_data[attribute] = value
154
155     def get_trace_data(self, guid):
156         data = self.data[guid]
157         if not "traces" in data:
158             return []
159         return [trace_id for trace_id in data["traces"]]
160
161     def get_connection_data(self, guid):
162         data = self.data[guid]
163         if not "connections" in data:
164             return []
165         connections_data = data["connections"]
166         return [(connector_type_name, other_guid, other_connector_type_name) \
167                     for connector_type_name, connection_data \
168                         in connections_data.iteritems() \
169                             for other_guid, other_connector_type_name \
170                                 in connection_data.iteritems()]
171
172     def get_address_data(self, guid):
173         data = self.data[guid]
174         if not "addresses" in data:
175             return []
176         addresses_data = data["addresses"]
177         return [(data["AutoConfigure"] if "AutoConfigure" in data else None,
178                  data["Address"] if "Address" in data else None,
179                  data["NetPrefix"] if "NetPrefix" in data else None,
180                  data["Broadcast"] if "Broadcast" in data else None) \
181                  for data in addresses_data]
182
183     def get_route_data(self, guid):
184         data = self.data[guid]
185         if not "routes" in data:
186             return []
187         routes_data = data["routes"]
188         return [(data["Destination"],
189                  data["NetPrefix"],
190                  data["NextHop"]) \
191                          for data in routes_data]
192
193 class ExperimentParser(object):
194     def to_data(self, experiment_description):
195         data = ExperimentData()
196         for testbed_description in experiment_description.testbed_descriptions:
197             guid = testbed_description.guid
198             testbed_id = testbed_description.provider.testbed_id
199             testbed_version = testbed_description.provider.testbed_version
200             data.add_testbed_data(guid, testbed_id, testbed_version)
201             self.graphical_info_to_data(data, guid, 
202                     testbed_description.graphical_info)
203             self.attributes_to_data(data, guid, testbed_description.attributes)
204             for box in testbed_description.boxes:
205                 data.add_box_data(box.guid, guid, box.factory_id)
206                 self.graphical_info_to_data(data, box.guid, box.graphical_info)
207                 self.factory_attributes_to_data(data, box.guid, 
208                         box.factory_attributes)
209                 self.attributes_to_data(data, box.guid, box.attributes)
210                 self.traces_to_data(data, box.guid, box.traces)
211                 self.connections_to_data(data, box.guid, box.connectors)
212                 self.addresses_to_data(data, box.guid, box.addresses)
213                 self.routes_to_data(data, box.guid, box.routes)
214         return data
215
216     def graphical_info_to_data(self, data, guid, g_info):
217         data.add_graphical_info_data(guid, g_info.x, g_info.y, g_info.width, 
218                 g_info.height, g_info.label)
219
220     def factory_attributes_to_data(self, data, guid, factory_attributes):
221         factory_attributes = factory_attributes or dict()
222         for name, value in factory_attributes.iteritems():
223             data.add_factory_attribute_data(guid, name, value)
224
225     def attributes_to_data(self, data, guid, attributes):
226         for attribute in attributes:
227             if attribute.modified or attribute.has_no_default_value:
228                 data.add_attribute_data(guid, attribute.name, attribute.value)
229
230     def traces_to_data(self, data, guid, traces):
231         for trace in traces:
232             if trace.enabled:
233                 data.add_trace_data(guid, trace.trace_id)
234
235     def connections_to_data(self, data, guid, connectors):
236         for connector in connectors:
237             connector_type_name = connector.connector_type.name
238             for other_connector in connector.connections:
239                 other_guid = other_connector.box.guid
240                 other_connector_type_name = other_connector.connector_type.name
241                 data.add_connection_data(guid, connector_type_name, other_guid,
242                         other_connector_type_name)
243
244     def addresses_to_data(self, data, guid, addresses):
245         for addr in addresses:
246              autoconf = addr.get_attribute_value("AutoConfigure")
247              address = addr.get_attribute_value("Address")
248              netprefix = addr.get_attribute_value("NetPrefix")
249              broadcast = addr.get_attribute_value("Broadcast") \
250                     if addr.has_attribute("Broadcast") and \
251                     addr.is_attribute_modified("Broadcast") else None
252              data.add_address_data(guid, autoconf, address, netprefix, 
253                     broadcast)
254
255     def routes_to_data(self, data, guid, routes):
256         for route in routes:
257              destination = route.get_attribute_value("Destination")
258              netprefix = route.get_attribute_value("NetPrefix")
259              nexthop = route.get_attribute_value("NextHop")
260              data.add_route_data(guid, destination, netprefix, nexthop)
261
262     def from_data(self, experiment_description, data):
263         box_guids = list()
264         for guid in data.guids:
265             if data.is_testbed_data(guid):
266                 self.testbed_from_data(experiment_description, guid, data)
267             else:
268                 self.box_from_data(experiment_description, guid, data)
269                 box_guids.append(guid)
270         self.connections_from_data(experiment_description, box_guids, data)
271
272     def testbed_from_data(self, experiment_description, guid, data):
273         from nepi.core.design import FactoriesProvider
274         (testbed_id, testbed_version) = data.get_testbed_data(guid)
275         provider = FactoriesProvider(testbed_id, testbed_version)
276         experiment_description.add_testbed_description(provider)
277         testbed_description = experiment_description.testbed_description(guid)
278         self.graphical_info_from_data(testbed_description, data)
279         self.attributes_from_data(testbed_description, data)
280
281     def box_from_data(self, experiment_description, guid, data):
282         (testbed_guid, factory_id) = data.get_box_data(guid)
283         testbed_description = experiment_description.testbed_description(
284                 testbed_guid)
285         self.factory_attributes_from_data(testbed_description, factory_id,
286                 guid, data)
287         box = testbed_description.create(factory_id)
288         self.graphical_info_from_data(box, data)
289         self.attributes_from_data(box, data)
290         self.traces_from_data(box, data)
291         self.addresses_from_data(box, data)
292         self.routes_from_data(box, data)
293
294     def graphical_info_from_data(self, element, data):
295         (x, y, width, height, label) =  data.get_graphical_info_data(
296                 element.guid)
297         element.graphical_info.x = x
298         element.graphical_info.y = y
299         element.graphical_info.width = width
300         element.graphical_info.height = height
301         element.graphical_info.label = label
302
303     def factory_attributes_from_data(self, testbed_description, factory_id, 
304             guid, data):
305         factory = testbed_description.provider.factory(factory_id)
306         for (name, value) in data.get_factory_attribute_data(guid):
307             factory.set_attribute_value(name, value)
308
309     def attributes_from_data(self, element, data):
310         for name, value in data.get_attribute_data(element.guid):
311             element.set_attribute_value(name, value)
312
313     def traces_from_data(self, box, data):
314         for name in data.get_trace_data(box.guid):
315             box.enable_trace(name)
316
317     def addresses_from_data(self, box, data):
318         for (autoconf, address, netprefix, broadcast) \
319                 in data.get_address_data(box.guid):
320             addr = box.add_address()
321             if autoconf:
322                 addr.set_attribute_value("AutoConfigure", autoconf)
323             if address:
324                 addr.set_attribute_value("Address", address)
325             if netprefix != None:
326                 addr.set_attribute_value("NetPrefix", netprefix)
327             if broadcast:
328                 addr.set_attribute_value("Broadcast", broadcast)
329
330     def routes_from_data(self, box, data):
331          for (destination, netprefix, nexthop) \
332                  in data.get_route_data(box.guid):
333             addr = box.add_route()
334             addr.set_attribute_value("Destination", destination)
335             addr.set_attribute_value("NetPrefix", netprefix)
336             addr.set_attribute_value("NextHop", nexthop)
337
338     def connections_from_data(self, experiment_description, guids, data):
339         for guid in guids:
340             box = experiment_description.box(guid)
341             for (connector_type_name, other_guid, other_connector_type_name) \
342                     in data.get_connection_data(guid):
343                     other_box = experiment_description.box(other_guid)
344                     connector = box.connector(connector_type_name)
345                     other_connector = other_box.connector(
346                             other_connector_type_name)
347                     if not connector.is_connected(other_connector):
348                         connector.connect(other_connector)
349