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