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 create_order(self):
61 """ list of factory ids that indicates the order in which the elements
62 should be instantiated.
64 raise NotImplementedError
67 def configure_order(self):
68 """ list of factory ids that indicates the order in which the elements
71 raise NotImplementedError
74 def factories_info(self):
75 """ dictionary of dictionaries of factory specific information
77 "allow_addresses": whether the box allows adding IP addresses,
78 "allow_routes": wether the box allows adding routes,
80 "category": category the element belongs to,
81 "create_function": function for element instantiation,
82 "start_function": function for element starting,
83 "stop_function": function for element stoping,
84 "status_function": function for retrieving element status,
85 "configure_function": function for element configuration,
86 "factory_attributes": list of references to attribute_ids,
87 "box_attributes": list of regerences to attribute_ids,
88 "traces": list of references to trace_id
89 "connector_types": list of references to connector_types
92 raise NotImplementedError
95 def testbed_attributes(self):
96 """ dictionary of attributes for testbed instance configuration
97 attributes_id = dict({
98 "name": attribute name,
100 "type": attribute type,
101 "value": default attribute value,
102 "range": (maximum, minimun) values else None if not defined,
103 "allowed": array of posible values,
104 "flags": attributes flags,
105 "validation_function": validation function for the attribute
109 raise NotImplementedError
111 class Metadata(object):
112 def __init__(self, testbed_id, version):
113 self._version = version
114 self._testbed_id = testbed_id
115 metadata_module = self._load_versioned_metadata_module()
116 self._metadata = metadata_module.VersionedMetadataInfo()
119 def create_order(self):
120 return self._metadata.create_order
123 def configure_order(self):
124 return self._metadata.configure_order
126 def testbed_attributes(self):
127 attributes = AttributesMap()
128 for attr_info in self._metadata.testbed_attributes.values():
129 name = attr_info["name"]
130 help = attr_info["help"]
131 type = attr_info["type"]
132 value = attr_info["value"] if "value" in attr_info else None
133 range = attr_info["range"] if "range" in attr_info else None
134 allowed = attr_info["allowed"] if "allowed" in attr_info else None
135 flags = attr_info["flags"] if "flags" in attr_info \
136 else Attribute.NoFlags
137 validation_function = attr_info["validation_function"]
138 attributes.add_attribute(name, help, type, value,
139 range, allowed, flags, validation_function)
142 def build_design_factories(self):
143 from nepi.core.design import Factory
145 for factory_id, info in self._metadata.factories_info.iteritems():
147 category = info["category"]
148 allow_addresses = info["allow_addresses"] \
149 if "allow_addresses" in info else False
150 allow_routes = info["allow_routes"] \
151 if "allow_routes" in info else False
152 factory = Factory(factory_id, allow_addresses, allow_routes,
154 self._add_attributes(factory, info, "factory_attributes")
155 self._add_attributes(factory, info, "box_attributes", True)
156 self._add_design_traces(factory, info)
157 self._add_design_connector_types(factory, info)
158 factories.append(factory)
161 def build_execute_factories(self):
162 from nepi.core.execute import Factory
164 for factory_id, info in self._metadata.factories_info.iteritems():
165 create_function = info["create_function"] \
166 if "create_function" in info else None
167 start_function = info["start_function"] \
168 if "start_function" in info else None
169 stop_function = info["stop_function"] \
170 if "stop_function" in info else None
171 status_function = info["status_function"] \
172 if "status_function" in info else None
173 configure_function = info["configure_function"] \
174 if "configure_function" in info else None
175 allow_addresses = info["allow_addresses"] \
176 if "allow_addresses" in info else False
177 allow_routes = info["allow_routes"] \
178 if "allow_routes" in info else False
179 factory = Factory(factory_id, create_function, start_function,
180 stop_function, status_function, configure_function,
181 allow_addresses, allow_routes)
182 self._add_attributes(factory, info, "factory_attributes")
183 self._add_attributes(factory, info, "box_attributes", True)
184 self._add_execute_traces(factory, info)
185 self._add_execute_connector_types(factory, info)
186 factories.append(factory)
189 def _load_versioned_metadata_module(self):
190 mod_name = "nepi.testbeds.%s.metadata_v%s" % (self._testbed_id.lower(),
192 if not mod_name in sys.modules:
194 return sys.modules[mod_name]
196 def _add_attributes(self, factory, info, attr_key, box_attributes = False):
198 for attr_id in info[attr_key]:
199 attr_info = self._metadata.attributes[attr_id]
200 name = attr_info["name"]
201 help = attr_info["help"]
202 type = attr_info["type"]
203 value = attr_info["value"] if "value" in attr_info else None
204 range = attr_info["range"] if "range" in attr_info else None
205 allowed = attr_info["allowed"] if "allowed" in attr_info \
207 flags = attr_info["flags"] if "flags" in attr_info \
208 and attr_info["flags"] != None \
209 else Attribute.NoFlags
210 validation_function = attr_info["validation_function"]
212 factory.add_box_attribute(name, help, type, value, range,
213 allowed, flags, validation_function)
215 factory.add_attribute(name, help, type, value, range,
216 allowed, flags, validation_function)
218 def _add_design_traces(self, factory, info):
220 for trace in info["traces"]:
221 trace_info = self._metadata.traces[trace]
222 trace_id = trace_info["name"]
223 help = trace_info["help"]
224 factory.add_trace(trace_id, help)
226 def _add_execute_traces(self, factory, info):
228 for trace in info["traces"]:
229 trace_info = self._metadata.traces[trace]
230 trace_id = trace_info["name"]
231 factory.add_trace(trace_id)
233 def _add_design_connector_types(self, factory, info):
234 from nepi.core.design import ConnectorType
235 if "connector_types" in info:
237 for connection in self._metadata.connections:
238 from_ = connection["from"]
239 to = connection["to"]
240 can_cross = connection["can_cross"]
241 if from_ not in connections:
242 connections[from_] = list()
243 if to not in connections:
244 connections[to] = list()
245 connections[from_].append((to, can_cross))
246 connections[to].append((from_, can_cross))
247 for connector_id in info["connector_types"]:
248 connector_type_info = self._metadata.connector_types[
250 name = connector_type_info["name"]
251 help = connector_type_info["help"]
252 max = connector_type_info["max"]
253 min = connector_type_info["min"]
254 testbed_id = self._testbed_id
255 factory_id = factory.factory_id
256 connector_type = ConnectorType(testbed_id, factory_id, name,
258 for (to, can_cross) in connections[(testbed_id, factory_id,
260 (testbed_id_to, factory_id_to, name_to) = to
261 connector_type.add_allowed_connection(testbed_id_to,
262 factory_id_to, name_to, can_cross)
263 factory.add_connector_type(connector_type)
265 def _add_execute_connector_types(self, factory, info):
266 from nepi.core.execute import ConnectorType
267 if "connector_types" in info:
268 from_connections = dict()
269 to_connections = dict()
270 for connection in self._metadata.connections:
271 from_ = connection["from"]
272 to = connection["to"]
273 can_cross = connection["can_cross"]
274 code = connection["code"]
275 if from_ not in from_connections:
276 from_connections[from_] = list()
277 if to not in to_connections:
278 to_connections[to] = list()
279 from_connections[from_].append((to, can_cross, code))
280 to_connections[to].append((from_, can_cross, code))
281 for connector_id in info["connector_types"]:
282 connector_type_info = self._metadata.connector_types[
284 name = connector_type_info["name"]
285 max = connector_type_info["max"]
286 min = connector_type_info["min"]
287 testbed_id = self._testbed_id
288 factory_id = factory.factory_id
289 connector_type = ConnectorType(testbed_id, factory_id, name,
291 connector_key = (testbed_id, factory_id, name)
292 if connector_key in to_connections:
293 for (from_, can_cross, code) in to_connections[connector_key]:
294 (testbed_id_from, factory_id_from, name_from) = from_
295 connector_type.add_from_connection(testbed_id_from,
296 factory_id_from, name_from, can_cross, code)
297 if connector_key in from_connections:
298 for (to, can_cross, code) in from_connections[(testbed_id,
300 (testbed_id_to, factory_id_to, name_to) = to
301 connector_type.add_to_connection(testbed_id_to,
302 factory_id_to, name_to, can_cross, code)
303 factory.add_connector_type(connector_type)