feef6ab84ff3ac15e7a34448c2c167a03f33f50f
[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     @property
11     def guids(self):
12         return self.data.keys()
13
14     def add_testbed_data(self, guid, testbed_id, testbed_version):
15         testbed_data = dict()
16         testbed_data["testbed_id"] = testbed_id
17         testbed_data["testbed_version"] = testbed_version
18         self.data[guid] = testbed_data
19
20     def add_box_data(self, guid, testbed_guid, factory_id):
21         box_data = dict()
22         box_data["testbed_guid"] = testbed_guid
23         box_data["factory_id"] = factory_id
24         self.data[guid] = box_data
25
26     def add_factory_attribute_data(self, guid, name, value):
27         data = self.data[guid]
28         if not "factory_attributes" in data:
29             data["factory_attributes"] = dict()
30         factory_attributes_data = data["factory_attributes"]
31         factory_attributes_data[name] = value
32
33     def add_attribute_data(self, guid, name, value):
34         data = self.data[guid]
35         if not "attributes" in data:
36             data["attributes"] = dict()
37         attributes_data = data["attributes"]
38         attributes_data[name] = value
39
40     def add_trace_data(self, guid, trace_name):
41         data = self.data[guid]
42         if not "traces" in data:
43             data["traces"] = list()
44         traces_data = data["traces"]
45         traces_data.append(trace_name)
46
47     def add_connection_data(self, guid, connector_type_name, other_guid,
48             other_connector_type_name):
49         data = self.data[guid]
50         if not "connections" in data:
51             data["connections"] = dict()
52         connections_data = data["connections"]
53         if not connector_type_name in connections_data:
54             connections_data[connector_type_name] = dict()
55         connection_data = connections_data[connector_type_name]
56         connection_data[other_guid] = other_connector_type_name
57
58     def add_address_data(self, guid, autoconf, address, family, netprefix, 
59             broadcast):
60         data = self.data[guid]
61         if not "addresses" in data:
62             data["addresses"] = list()
63         addresses_data = data["addresses"]
64         address_data = dict()
65         if autoconf:
66             address_data["AutoConfigure"] = autoconf
67         if address:
68             address_data["Address"] = address
69         if family:
70             address_data["Family"] = family
71         if netprefix:
72             address_data["NetPrefix"] = netprefix
73         if broadcast:
74             address_data["Broadcast"] = broadcast
75         addresses_data.append(address_data)
76
77     def add_route_data(self, guid, family, destination, netprefix, nexthop, 
78             interface):
79         data = self.data[guid]
80         if not "routes" in data:
81             data["routes"] = list()
82         routes_data = data["routes"]
83         route_data = dict({
84             "Family": family, 
85             "Destination": destination,
86             "NetPrefix": netprefix, 
87             "NextHop": nexthop, 
88             "Interface": Interface
89             })
90         routes_data.append(route_data)
91
92     def is_testbed_data(self, guid):
93         return True if "testbed_id" in self.data[guid] else None
94
95     def get_testbed_data(self, guid):
96         testbed_data = self.data[guid]
97         return (testbed_data["testbed_id"], testbed_data["testbed_version"])
98
99     def get_box_data(self, guid):
100         box_data = self.data[guid]
101         return (box_data["testbed_guid"], box_data["factory_id"])
102
103     def get_factory_attribute_data(self, guid):
104         data = self.data[guid]
105         if not "factory_attributes" in data:
106             return []
107         factory_attributes_data = data["factory_attributes"]
108         return [(name, value) for name, value \
109                 in factory_attributes_data.iteritems()]
110
111     def get_attribute_data(self, guid):
112         data = self.data[guid]
113         if not "attributes" in data:
114             return []
115         attributes_data = data["attributes"]
116         return [(name, value) for name, value \
117                 in attributes_data.iteritems()]
118
119     def get_trace_data(self, guid):
120         data = self.data[guid]
121         if not "traces" in data:
122             return []
123         return [trace_name for trace_name in data["traces"]]
124
125     def get_connection_data(self, guid):
126         data = self.data[guid]
127         if not "connections" in data:
128             return []
129         connections_data = data["connections"]
130         return [(connector_type_name, other_guid, other_connector_type_name) \
131                     for connector_type_name, connection_data \
132                         in connections_data.iteritems() \
133                             for other_guid, other_connector_type_name \
134                                 in connection_data.iteritems()]
135
136     def get_address_data(self, guid):
137         data = self.data[guid]
138         if not "addresses" in data:
139             return []
140         addresses_data = data["addresses"]
141         return [(data["AutoConfigure"] if "AutoConfigure" in data else None,
142                  data["Address"] if "Address" in data else None,
143                  data["Family"] if "Family" in data else None,
144                  data["NetPrefix"] if "NetPrefix" in data else None,
145                  data["Broadcast"] if "Broadcast" in data else None) \
146                  for data in addresses_data]
147
148     def get_route_data(self, guid):
149         data = self.data[guid]
150         if not "routes" in data:
151             return []
152         routes_data = data["routes"]
153         return [(data["Family"],
154                  data["Destination"],
155                  data["NetPrefix"],
156                  data["NextHop"],
157                  data["Interface"]) \
158                  for data in routes_data]
159
160 class ExperimentParser(object):
161     def to_data(self, experiment_description):
162         data = ExperimentData()
163         for testbed_description in experiment_description.testbed_descriptions:
164             guid = testbed_description.guid
165             testbed_id = testbed_description.provider.testbed_id
166             testbed_version = testbed_description.provider.testbed_version
167             data.add_testbed_data(guid, testbed_id, testbed_version)
168             self.attributes_to_data(data, guid, testbed_description.attributes)
169             for box in testbed_description.boxes:
170                 data.add_box_data(box.guid, guid, box.factory_id)
171                 self.factory_attributes_to_data(data, box.guid, 
172                         box.factory_attributes)
173                 self.attributes_to_data(data, box.guid, box.attributes)
174                 self.traces_to_data(data, box.guid, box.traces)
175                 self.connections_to_data(data, box.guid, box.connectors)
176                 self.addresses_to_data(data, box.guid, box.addresses)
177                 self.routes_to_data(data, box.guid, box.routes)
178         return data
179
180     def factory_attributes_to_data(self, data, guid, attributes):
181         for attribute in attributes:
182             if attribute.modified:
183                 data.add_factory_attribute_data(guid, attribute.name, 
184                         attribute.value)
185
186     def attributes_to_data(self, data, guid, attributes):
187         for attribute in attributes:
188             if attribute.modified:
189                 data.add_attribute_data(guid, attribute.name, attribute.value)
190
191     def traces_to_data(self, data, guid, traces):
192         for trace in traces:
193             if trace.enabled:
194                 data.add_trace_data(guid, trace.name)
195
196     def connections_to_data(self, data, guid, connectors):
197         for connector in connectors:
198             connector_type_name = connector.connector_type.name
199             for other_connector in connector.connections:
200                 other_guid = other_connector.box.guid
201                 other_connector_type_name = other_connector.connector_type.name
202                 data.add_connection_data(guid, connector_type_name, other_guid,
203                         other_connector_type_name)
204
205     def addresses_to_data(self, data, guid, addresses):
206         for addr in addresses:
207              autoconf = addr.get_attribute_value("AutoConfigure") \
208                     if addr.is_attribute_modified("AutoConfigure") else None
209              address = addr.get_attribute_value("Address") \
210                     if addr.is_attribute_modified("Address") else None
211              netprefix = addr.get_attribute_value("NetPrefix") \
212                     if addr.is_attribute_modified("NetPrefix") else None
213              family = addr.get_attribute_value("Family") \
214                     if addr.is_attribute_modified("Family") else None
215              broadcast = addr.get_attribute_value("Broadcast") \
216                     if addr.has_attribute("Broadcast") and \
217                      addr.is_attribute_modified("Broadcast") else None
218              data.add_address_data(guid, autoconf, address, family, netprefix, 
219                     broadcast)
220
221     def routes_to_data(self, data, guid, routes):
222         for route in routes:
223              family = route.get_attribute_value("Family")
224              destination = route.get_attribute_value("Destination")
225              netprefix = route.get_attribute_value("NetPrefix")
226              nexthop = route.get_attribute_value("NextHop")
227              interface = route.get_attribute_value("Interface")
228              data.add_route_data(guid, family, destination, netprefix, nexthop, 
229                     interface)
230
231     def from_data(self, experiment_description, data):
232         box_guids = list()
233         for guid in data.guids:
234             if data.is_testbed_data(guid):
235                 self.testbed_from_data(experiment_description, guid, data)
236             else:
237                 self.box_from_data(experiment_description, guid, data)
238                 box_guids.append(guid)
239         self.connections_from_data(experiment_description, box_guids, data)
240
241     def testbed_from_data(self, experiment_description, guid, data):
242         (testbed_id, testbed_version) = data.get_testbed_data(guid)
243         mod_name = 'nepi.testbeds.%s' % testbed_id
244         if not mod_name in sys.modules:
245             __import__(mod_name)
246         testbed_mod = sys.modules[mod_name]
247         provider = testbed_mod.TestbedFactoriesProvider(testbed_version)
248         experiment_description.add_testbed_description(provider)
249         testbed_description = experiment_description.testbed_description(guid)
250         self.attributes_from_data(testbed_description, data)
251
252     def box_from_data(self, experiment_description, guid, data):
253         (testbed_guid, factory_id) = data.get_box_data(guid)
254         testbed_description = experiment_description.testbed_description(
255                 testbed_guid)
256         self.factory_attributes_from_data(testbed_description, factory_id,
257                 guid, data)
258         box = testbed_description.create(factory_id)
259         self.attributes_from_data(box, data)
260         self.traces_from_data(box, data)
261         self.addresses_from_data(box, data)
262         self.routes_from_data(box, data)
263
264     def factory_attributes_from_data(self, testbed_description, factory_id, 
265             guid, data):
266         factory = testbed_description.provider.factory(factory_id)
267         for (name, value) in data.get_factory_attribute_data(guid):
268             factory.set_attribute_value(name, value)
269
270     def attributes_from_data(self, element, data):
271         for name, value in data.get_attribute_data(element.guid):
272             element.set_attribute_value(name, value)
273
274     def traces_from_data(self, box, data):
275         for name in data.get_trace_data(box.guid):
276             box.trace(name).enable()
277
278     def addresses_from_data(self, box, data):
279         for (autoconf, address, family, netprefix, broadcast) \
280                 in data.get_address_data(box.guid):
281             addr = box.add_address()
282             if autoconf:
283                 addr.set_attribute_value("AutoConfigure", autoconf)
284             if address:
285                 addr.set_attribute_value("Address", address)
286             if family:
287                 addr.set_attribute_value("Family", family)
288             if netprefix:
289                 addr.set_attribute_value("NetPrefix", netprefix)
290             if broadcast:
291                 addr.set_attribute_value("Broadcast", broadcast)
292
293     def routes_from_data(self, box, data):
294          for (family, destination, netprefix, nexthop, interface) \
295                 in data.get_route_data(box.guid):
296             addr = box.add_route(family)
297             addr.set_attribute_value("Destination", destination)
298             addr.set_attribute_value("NetPrefix", netprefix)
299             addr.set_attribute_value("NextHop", nexthop)
300             addr.set_attribute_value("Interface", interface)
301
302     def connections_from_data(self, experiment_description, guids, data):
303         for guid in guids:
304             box = experiment_description.box(guid)
305             for (connector_type_name, other_guid, other_connector_type_name) \
306                     in data.get_connection_data(guid):
307                     other_box = experiment_description.box(other_guid)
308                     connector = box.connector(connector_type_name)
309                     other_connector = other_box.connector(
310                             other_connector_type_name)
311                     if not connector.is_connected(other_connector):
312                         connector.connect(other_connector)
313
314