2 # -*- coding: utf-8 -*-
4 from nepi.core.attributes import AttributesMap
5 from nepi.util.parser._xml import XmlExperimentParser
6 from nepi.util import validation
9 class ConnectorType(object):
10 def __init__(self, testbed_id, factory_id, name, max = -1, min = 0):
11 super(ConnectorType, self).__init__()
16 "The maximum number of connections allowed need to be more than 0")
19 "The minimum number of connections allowed needs to be at least 0")
20 # connector_type_id -- univoquely identifies a connector type
22 self._connector_type_id = (testbed_id.lower(), factory_id.lower(),
24 # name -- display name for the connector type
26 # max -- maximum amount of connections that this type support,
29 # min -- minimum amount of connections required by this type of connector
31 # from_connections -- connections where the other connector is the "From"
32 # to_connections -- connections where the other connector is the "To"
33 # keys in the dictionary correspond to the
34 # connector_type_id for possible connections. The value is a tuple:
35 # (can_cross, connect)
36 # can_cross: indicates if the connection is allowed accros different
38 # code: is the connection function to be invoked when the elements
40 self._from_connections = dict()
41 self._to_connections = dict()
44 def connector_type_id(self):
45 return self._connector_type_id
59 def add_from_connection(self, testbed_id, factory_id, name, can_cross, code):
60 self._from_connections[(testbed_id.lower(), factory_id.lower(),
61 name.lower())] = (can_cross, code)
63 def add_to_connection(self, testbed_id, factory_id, name, can_cross, code):
64 self._to_connections[(testbed_id.lower(), factory_id.lower(),
65 name.lower())] = (can_cross, code)
67 def can_connect(self, testbed_id, factory_id, name, count,
69 connector_type_id = (testbed_id.lower(), factory_id.lower(),
71 if connector_type_id in self._from_connections:
72 (can_cross, code) = self._from_connections[connector_type_id]
73 elif connector_type_id in self._to_connections:
74 (can_cross, code) = self._to_connections[connector_type_id]
77 return not must_cross or can_cross
79 def code_to_connect(self, testbed_id, factory_id, name):
80 connector_type_id = (testbed_id.lower(), factory_id.lower(),
82 if not connector_type_id in self._to_connections.keys():
84 (can_cross, code) = self._to_connections[connector_type_id]
87 # TODO: create_function, start_function, stop_function, status_function
89 class Factory(AttributesMap):
90 def __init__(self, factory_id, create_function, start_function,
91 stop_function, status_function, allow_addresses = False,
92 allow_routes = False):
93 super(Factory, self).__init__()
94 self._factory_id = factory_id
95 self._allow_addresses = (allow_addresses == True)
96 self._allow_routes = (allow_routes == True)
97 self._create_function = create_function
98 self._start_function = start_function
99 self._stop_function = stop_function
100 self._status_function = status_function
101 self._connector_types = dict()
102 self._traces = list()
105 def factory_id(self):
106 return self._factory_id
109 def allow_addresses(self):
110 return self._allow_addresses
113 def allow_routes(self):
114 return self._allow_routes
117 def create_function(self):
118 return self._create_function
121 def start_function(self):
122 return self._start_function
125 def stop_function(self):
126 return self._stop_function
129 def status_function(self):
130 return self._status_function
136 def connector_type(self, name):
137 return self._connector_types[name]
139 def add_connector_type(self, connector_type):
140 self._connector_types[connector_type.name] = connector_type
142 def add_trace(self, trace_id):
143 self._traces.append(trace_id)
145 class TestbedInstance(object):
146 def __init__(self, testbed_id, testbed_version):
147 self._testbed_id = testbed_id
148 self._testbed_version = testbed_version
152 raise NotImplementedError
154 def configure(self, name, value):
155 """Set a configuartion attribute for the testbed instance"""
156 raise NotImplementedError
158 def create(self, guid, factory_id):
159 """Instructs creation of element """
160 raise NotImplementedError
162 def create_set(self, guid, name, value):
163 """Instructs setting an attribute on an element"""
164 raise NotImplementedError
166 def connect(self, guid1, connector_type_name1, guid2,
167 connector_type_name2):
168 raise NotImplementedError
170 def cross_connect(self, guid, connector_type_name, cross_guid,
171 cross_testbed_id, cross_factory_id, cross_connector_type_name):
172 raise NotImplementedError
174 def add_trace(self, guid, trace_id):
175 raise NotImplementedError
177 def add_adddress(self, guid, family, address, netprefix, broadcast):
178 raise NotImplementedError
180 def add_route(self, guid, destination, netprefix, nexthop):
181 raise NotImplementedError
184 """After do_setup the testbed initial configuration is done"""
185 raise NotImplementedError
188 """After do_create all instructed elements are created and
190 raise NotImplementedError
192 def do_connect(self):
193 """After do_connect all internal connections between testbed elements
195 raise NotImplementedError
197 def do_configure(self):
198 """After do_configure elements are configured"""
199 raise NotImplementedError
201 def do_cross_connect(self):
202 """After do_cross_connect all external connections between different testbed
204 raise NotImplementedError
206 def start(self, time):
207 raise NotImplementedError
209 def stop(self, time):
210 raise NotImplementedError
212 def set(self, time, guid, name, value):
213 raise NotImplementedError
215 def get(self, time, guid, name):
216 raise NotImplementedError
218 def action(self, time, guid, action):
219 raise NotImplementedError
221 def status(self, guid):
222 raise NotImplementedError
224 def trace(self, guid, trace_id):
225 raise NotImplementedError
228 raise NotImplementedError
230 class ExperimentController(object):
231 def __init__(self, experiment_xml):
232 self._experiment_xml = experiment_xml
233 self._testbeds = dict()
234 self._access_config = dict()
237 def experiment_xml(self):
238 return self._experiment_xml
240 def testbed_instance(self, guid):
241 return self._testbeds[guid]
243 def set_testbed_access_config(self, guid, access_config):
244 self._access_config[guid] = access_config
246 def trace(self, testbed_guid, guid, trace_id):
247 return self._testbeds[testbed_guid].trace(guid, trace_id)
250 parser = XmlExperimentParser()
251 data = parser.from_xml_to_data(self._experiment_xml)
252 element_guids = list()
253 for guid in data.guids:
254 if data.is_testbed_data(guid):
255 (testbed_id, testbed_version) = data.get_testbed_data(guid)
256 instance = self._build_testbed_instance(testbed_id,
258 for (name, value) in data.get_attribute_data(guid):
259 instance.configure(name, value)
260 self._testbeds[guid] = instance
262 element_guids.append(guid)
264 for guid in element_guids:
265 (testbed_guid, factory_id) = data.get_box_data(guid)
266 instance = self._testbeds[testbed_guid]
267 instance.create(guid, factory_id)
268 for (name, value) in data.get_attribute_data(guid):
269 instance.create_set(guid, name, value)
271 for guid in element_guids:
272 (testbed_guid, factory_id) = data.get_box_data(guid)
273 instance = self._testbeds[testbed_guid]
274 for (connector_type_name, other_guid, other_connector_type_name) \
275 in data.get_connection_data(guid):
276 (testbed_guid, factory_id) = data.get_box_data(guid)
277 (other_testbed_guid, other_factory_id) = data.get_box_data(
279 if testbed_guid == other_testbed_guid:
280 instance.connect(guid, connector_type_name, other_guid,
281 other_connector_type_name)
283 instance.cross_connect(guid, connector_type_name, other_guid,
284 other_testbed_id, other_factory_id, other_connector_type_name)
285 for trace_id in data.get_trace_data(guid):
286 instance.add_trace(guid, trace_id)
287 for (autoconf, address, family, netprefix, broadcast) in \
288 data.get_address_data(guid):
290 # TODO: BUG!!! Hardcodeado!!!!!! XXXXXXXXX CORREGIR!!!
293 instance.add_adddress(guid, family, address, netprefix,
295 for (family, destination, netprefix, nexthop) in \
296 data.get_route_data(guid):
297 instance.add_route(guid, destination, netprefix, nexthop)
299 for instance in self._testbeds.values():
301 for instance in self._testbeds.values():
303 instance.do_connect()
304 instance.do_configure()
305 for instances in self._testbeds.values():
306 instance.do_cross_connect()
307 for instances in self._testbeds.values():
311 for instance in self._testbeds.values():
314 def status(self, guid):
315 for instance in self._testbeds.values():
316 for guid_ in instance.guids:
318 return instance.status(guid)
319 raise RuntimeError("No element exists with guid %d" % guid)
322 for instance in self._testbeds.values():
325 def _build_testbed_instance(self, testbed_id, testbed_version):
326 mod_name = "nepi.testbeds.%s" % (testbed_id.lower())
327 if not mod_name in sys.modules:
329 module = sys.modules[mod_name]
330 return module.TestbedInstance(testbed_version)