2 # -*- coding: utf-8 -*-
6 class VersionedMetadataInfo(object):
8 def connections_types(self):
9 """ dictionary of dictionaries with allowed connection information.
12 "name": connector type name,
13 "max": maximum number of connections allowed (-1 for no limit),
14 "min": minimum number of connections allowed
17 raise NotImplementedError
20 def connections(self):
21 """ array of dictionaries with allowed connection information.
23 "from": (testbed_id1, factory_id1, connector_type_name1),
24 "to": (testbed_id2, factory_id2, connector_type_name2),
25 "code": connection function to invoke upon connection creation
26 "can_cross": whether the connection can be done across testbed
30 raise NotImplementedError
34 """ dictionary of dictionaries of all available attributes.
35 "attribute_id": dict({
36 "name": attribute name,
38 "type": attribute type,
39 "value": default attribute value,
40 "range": (maximum, minimun) values else None if not defined,
41 "allowed": array of posible values,
42 "readonly": whether the attribute is read only for the user,
43 "visible": whether the attribute is visible for the user,
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
86 class Metadata(object):
87 def __init__(self, testbed_id, version):
88 self._version = version
89 self._testbed_id = testbed_id
90 self._metadata = self._load_versioned_metadata_info()
93 def factories_order(self):
94 return self._metadata.factories_order
96 def build_design_factories(self):
97 from nepi.core.design import Factory
99 for factory_id, info in self._metadata.factories_info.iteritems():
101 category = info["category"]
102 allow_addresses = info["allow_addresses"] \
103 if "allow_addresses" in info else False
104 allow_routes = info["allow_routes"] \
105 if "allow_routes" in info else False
106 factory = Factory(factory_id, allow_addresses, allow_routes,
108 self._add_attributes(factory, info, "factory_attributes")
109 self._add_attributes(factory, info, "box_attributes", True)
110 self._add_design_traces(factory, info)
111 self._add_design_connector_types(factory, info)
112 factories.append(factory)
115 def build_execute_factories(self):
116 from nepi.core.execute import Factory
118 for factory_id, info in self._metadata.factories_info.iteritems():
119 create_function = info["create_function"]
120 start_function = info["start_function"]
121 stop_function = info["stop_function"]
122 status_function = info["status_function"]
123 allow_addresses = info["allow_addresses"] \
124 if "allow_addresses" in info else False
125 allow_routes = info["allow_routes"] \
126 if "allow_routes" in info else False
127 factory = Factory(factory_id, create_function, start_function,
128 stop_function, status_function, allow_addresses,
130 self._add_attributes(factory, info, "factory_attributes")
131 self._add_attributes(factory, info, "box_attributes")
132 self._add_execute_traces(factory, info)
133 self._add_execute_connector_types(factory, info)
134 factories.append(factory)
137 def _load_versioned_metadata_info(self):
138 mod_name = "nepi.testbeds.%s.metadata_v%s" % (self._testbed_id.lower(),
140 if not mod_name in sys.modules:
142 return sys.modules[mod_name]
144 def _add_attributes(self, factory, info, attributes_key,
145 box_attributes = False):
146 if attributes_key in info:
147 for attribute_id in info[attributes_key]:
148 attribute_info = self._metadata.attributes[attribute_id]
149 name = attribute_info["name"]
150 help = attribute_info["help"]
151 type = attribute_info["type"]
152 value = attribute_info["value"]
153 range = attribute_info["range"]
154 allowed = attribute_info["allowed"]
155 readonly = attribute_info["readonly"]
156 visible = attribute_info["visible"]
157 validation_function = attribute_info["validation_function"]
159 factory.add_box_attribute(name, help, type, value, range,
160 allowed, readonly, visible, validation_function)
162 factory.add_attribute(name, help, type, value, range,
163 allowed, readonly, visible, validation_function)
165 def _add_design_traces(self, factory, info):
167 for trace in info["traces"]:
168 trace_info = self._metadata.traces[trace]
169 trace_id = trace_info["name"]
170 help = trace_info["help"]
171 factory.add_trace(trace_id, help)
173 def _add_execute_traces(self, factory, info):
175 for trace in info["traces"]:
176 trace_info = self._metadata.traces[trace]
177 trace_id = trace_info["name"]
178 factory.add_trace(trace_id)
180 def _add_design_connector_types(self, factory, info):
181 from nepi.core.design import ConnectorType
182 if "connector_types" in info:
184 for connection in self._metadata.connections:
185 from_ = connection["from"]
186 to = connection["to"]
187 can_cross = connection["can_cross"]
188 if from_ not in connections:
189 connections[from_] = list()
190 if to not in connections:
191 connections[to] = list()
192 connections[from_].append((to, can_cross))
193 connections[to].append((from_, can_cross))
194 for connector_id in info["connector_types"]:
195 connector_type_info = self._metadata.connector_types[
197 name = connector_type_info["name"]
198 help = connector_type_info["help"]
199 max = connector_type_info["max"]
200 min = connector_type_info["min"]
201 testbed_id = self._testbed_id
202 factory_id = factory.factory_id
203 connector_type = ConnectorType(testbed_id, factory_id, name,
205 for (to, can_cross) in connections[(testbed_id, factory_id,
207 (testbed_id_to, factory_id_to, name_to) = to
208 connector_type.add_allowed_connection(testbed_id_to,
209 factory_id_to, name_to, can_cross)
210 factory.add_connector_type(connector_type)
212 def _add_execute_connector_types(self, factory, info):
213 from nepi.core.execute import ConnectorType
214 if "connector_types" in info:
215 from_connections = dict()
216 to_connections = dict()
217 for connection in self._metadata.connections:
218 from_ = connection["from"]
219 to = connection["to"]
220 can_cross = connection["can_cross"]
221 code = connection["code"]
222 if from_ not in from_connections:
223 from_connections[from_] = list()
224 if to not in to_connections:
225 to_connections[to] = list()
226 from_connections[from_].append((to, can_cross, code))
227 to_connections[to].append((from_, can_cross, code))
228 for connector_id in info["connector_types"]:
229 connector_type_info = self._metadata.connector_types[
231 name = connector_type_info["name"]
232 max = connector_type_info["max"]
233 min = connector_type_info["min"]
234 testbed_id = self._testbed_id
235 factory_id = factory.factory_id
236 connector_type = ConnectorType(testbed_id, factory_id, name,
238 connector_key = (testbed_id, factory_id, name)
239 if connector_key in to_connections:
240 for (from_, can_cross, code) in to_connections[connector_key]:
241 (testbed_id_from, factory_id_from, name_from) = from_
242 connector_type.add_from_connection(testbed_id_from,
243 factory_id_from, name_from, can_cross, code)
244 if connector_key in from_connections:
245 for (to, can_cross, code) in from_connections[(testbed_id,
247 (testbed_id_to, factory_id_to, name_to) = to
248 connector_type.add_to_connection(testbed_id_to,
249 factory_id_to, name_to, can_cross, code)
250 factory.add_connector_type(connector_type)