2 # -*- coding: utf-8 -*-
4 from nepi.core.attributes import Attribute, AttributesMap
7 class VersionedMetadataInfo(object):
9 def connector_types(self):
10 """ dictionary of dictionaries with allowed connection information.
13 "name": connector type name,
14 "max": maximum number of connections allowed (-1 for no limit),
15 "min": minimum number of connections allowed
18 raise NotImplementedError
21 def connections(self):
22 """ array of dictionaries with allowed connection information.
24 "from": (testbed_id1, factory_id1, connector_type_name1),
25 "to": (testbed_id2, factory_id2, connector_type_name2),
26 "code": connection function to invoke upon connection creation
27 "can_cross": whether the connection can be done across testbed
31 raise NotImplementedError
35 """ dictionary of dictionaries of all available attributes.
37 "name": attribute name,
39 "type": attribute type,
40 "value": default attribute value,
41 "range": (maximum, minimun) values else None if not defined,
42 "allowed": array of posible values,
43 "flags": attributes flags,
44 "validation_function": validation function for the attribute
47 raise NotImplementedError
51 """ dictionary of dictionaries of all available traces.
57 raise NotImplementedError
60 def factories_order(self):
61 """ list of factory ids that indicates the order in which the elements
62 should be instantiated.
64 raise NotImplementedError
67 def factories_info(self):
68 """ dictionary of dictionaries of factory specific information
70 "allow_addresses": whether the box allows adding IP addresses,
71 "allow_routes": wether the box allows adding routes,
73 "category": category the element belongs to,
74 "create_function": function for element instantiation,
75 "start_function": function for element starting,
76 "stop_function": function for element stoping,
77 "status_function": function for retrieving element status,
78 "factory_attributes": list of references to attribute_ids,
79 "box_attributes": list of regerences to attribute_ids,
80 "traces": list of references to trace_id
81 "connector_types": list of references to connector_types
84 raise NotImplementedError
87 def testbed_attributes(self):
88 """ dictionary of attributes for testbed instance configuration
89 attributes_id = dict({
90 "name": attribute name,
92 "type": attribute type,
93 "value": default attribute value,
94 "range": (maximum, minimun) values else None if not defined,
95 "allowed": array of posible values,
96 "flags": attributes flags,
97 "validation_function": validation function for the attribute
101 raise NotImplementedError
103 class Metadata(object):
104 def __init__(self, testbed_id, version):
105 self._version = version
106 self._testbed_id = testbed_id
107 metadata_module = self._load_versioned_metadata_module()
108 self._metadata = metadata_module.VersionedMetadataInfo()
111 def factories_order(self):
112 return self._metadata.factories_order
114 def testbed_attributes(self):
115 attributes = AttributesMap()
116 for attribute_info in self._metadata.testbed_attributes.values():
117 name = attribute_info["name"]
118 help = attribute_info["help"]
119 type = attribute_info["type"]
120 value = attribute_info["value"]
121 range = attribute_info["range"]
122 allowed = attribute_info["allowed"]
123 flags = attribute_info["flags"] if "flags" in attribute_info \
124 else Attribute.NoFlags
125 validation_function = attribute_info["validation_function"]
126 attributes.add_attribute(name, help, type, value,
127 range, allowed, flags, validation_function)
130 def build_design_factories(self):
131 from nepi.core.design import Factory
133 for factory_id, info in self._metadata.factories_info.iteritems():
135 category = info["category"]
136 allow_addresses = info["allow_addresses"] \
137 if "allow_addresses" in info else False
138 allow_routes = info["allow_routes"] \
139 if "allow_routes" in info else False
140 factory = Factory(factory_id, allow_addresses, allow_routes,
142 self._add_attributes(factory, info, "factory_attributes")
143 self._add_attributes(factory, info, "box_attributes", True)
144 self._add_design_traces(factory, info)
145 self._add_design_connector_types(factory, info)
146 factories.append(factory)
149 def build_execute_factories(self):
150 from nepi.core.execute import Factory
152 for factory_id, info in self._metadata.factories_info.iteritems():
153 create_function = info["create_function"]
154 start_function = info["start_function"]
155 stop_function = info["stop_function"]
156 status_function = info["status_function"]
157 allow_addresses = info["allow_addresses"] \
158 if "allow_addresses" in info else False
159 allow_routes = info["allow_routes"] \
160 if "allow_routes" in info else False
161 factory = Factory(factory_id, create_function, start_function,
162 stop_function, status_function, allow_addresses,
164 self._add_attributes(factory, info, "factory_attributes")
165 self._add_attributes(factory, info, "box_attributes", True)
166 self._add_execute_traces(factory, info)
167 self._add_execute_connector_types(factory, info)
168 factories.append(factory)
171 def _load_versioned_metadata_module(self):
172 mod_name = "nepi.testbeds.%s.metadata_v%s" % (self._testbed_id.lower(),
174 if not mod_name in sys.modules:
176 return sys.modules[mod_name]
178 def _add_attributes(self, factory, info, attributes_key,
179 box_attributes = False):
180 if attributes_key in info:
181 for attribute_id in info[attributes_key]:
183 attribute_info = self._metadata.attributes[attribute_id]
185 print "\"%s\"," % attribute_id
187 name = attribute_info["name"]
188 help = attribute_info["help"]
189 type = attribute_info["type"]
190 value = attribute_info["value"]
191 range = attribute_info["range"]
192 allowed = attribute_info["allowed"]
193 flags = attribute_info["flags"] if "flags" in attribute_info \
194 else Attribute.NoFlags
195 validation_function = attribute_info["validation_function"]
197 factory.add_box_attribute(name, help, type, value, range,
198 allowed, flags, validation_function)
200 factory.add_attribute(name, help, type, value, range,
201 allowed, flags, validation_function)
203 def _add_design_traces(self, factory, info):
205 for trace in info["traces"]:
206 trace_info = self._metadata.traces[trace]
207 trace_id = trace_info["name"]
208 help = trace_info["help"]
209 factory.add_trace(trace_id, help)
211 def _add_execute_traces(self, factory, info):
213 for trace in info["traces"]:
214 trace_info = self._metadata.traces[trace]
215 trace_id = trace_info["name"]
216 factory.add_trace(trace_id)
218 def _add_design_connector_types(self, factory, info):
219 from nepi.core.design import ConnectorType
220 if "connector_types" in info:
222 for connection in self._metadata.connections:
223 from_ = connection["from"]
224 to = connection["to"]
225 can_cross = connection["can_cross"]
226 if from_ not in connections:
227 connections[from_] = list()
228 if to not in connections:
229 connections[to] = list()
230 connections[from_].append((to, can_cross))
231 connections[to].append((from_, can_cross))
232 for connector_id in info["connector_types"]:
233 connector_type_info = self._metadata.connector_types[
235 name = connector_type_info["name"]
236 help = connector_type_info["help"]
237 max = connector_type_info["max"]
238 min = connector_type_info["min"]
239 testbed_id = self._testbed_id
240 factory_id = factory.factory_id
241 connector_type = ConnectorType(testbed_id, factory_id, name,
243 for (to, can_cross) in connections[(testbed_id, factory_id,
245 (testbed_id_to, factory_id_to, name_to) = to
246 connector_type.add_allowed_connection(testbed_id_to,
247 factory_id_to, name_to, can_cross)
248 factory.add_connector_type(connector_type)
250 def _add_execute_connector_types(self, factory, info):
251 from nepi.core.execute import ConnectorType
252 if "connector_types" in info:
253 from_connections = dict()
254 to_connections = dict()
255 for connection in self._metadata.connections:
256 from_ = connection["from"]
257 to = connection["to"]
258 can_cross = connection["can_cross"]
259 code = connection["code"]
260 if from_ not in from_connections:
261 from_connections[from_] = list()
262 if to not in to_connections:
263 to_connections[to] = list()
264 from_connections[from_].append((to, can_cross, code))
265 to_connections[to].append((from_, can_cross, code))
266 for connector_id in info["connector_types"]:
267 connector_type_info = self._metadata.connector_types[
269 name = connector_type_info["name"]
270 max = connector_type_info["max"]
271 min = connector_type_info["min"]
272 testbed_id = self._testbed_id
273 factory_id = factory.factory_id
274 connector_type = ConnectorType(testbed_id, factory_id, name,
276 connector_key = (testbed_id, factory_id, name)
277 if connector_key in to_connections:
278 for (from_, can_cross, code) in to_connections[connector_key]:
279 (testbed_id_from, factory_id_from, name_from) = from_
280 connector_type.add_from_connection(testbed_id_from,
281 factory_id_from, name_from, can_cross, code)
282 if connector_key in from_connections:
283 for (to, can_cross, code) in from_connections[(testbed_id,
285 (testbed_id_to, factory_id_to, name_to) = to
286 connector_type.add_to_connection(testbed_id_to,
287 factory_id_to, name_to, can_cross, code)
288 factory.add_connector_type(connector_type)