1 # -*- coding: utf-8 -*-
7 from constants import TESTBED_ID, TESTBED_VERSION
8 from nepi.core import metadata
9 from nepi.core.attributes import Attribute
10 from nepi.util import tags, validation, ipaddr2
11 from nepi.util.constants import ApplicationStatus as AS, \
12 FactoryCategories as FC, DeploymentConfiguration as DC
14 ##############################################################################
16 class OmfResource(object):
17 def __init__(self, guid, tc):
18 super(OmfResource, self).__init__()
19 self._tc = weakref.ref(tc)
24 return self._tc and self._tc()
45 ## NODE #######################################################################
47 class OmfNode(OmfResource):
48 def __init__(self, guid, tc):
49 super(OmfNode, self).__init__(guid, tc)
50 self.hostname = self.tc._get_parameters(guid)['hostname']
51 self.tc.api.enroll_host(self.hostname)
54 routes = self.tc._add_route.get(self.guid, [])
55 iface_guids = self.tc.get_connected(self.guid, "devs", "node")
58 (destination, netprefix, nexthop, metric, device) = route
59 netmask = ipaddr2.ipv4_mask2dot(netprefix)
61 # Validate that the interface is associated to the node
62 for iface_guid in iface_guids:
63 iface = self.tc.elements.get(iface_guid)
64 if iface.devname == device:
65 self.tc.api.execute(self.hostname,
66 "Id#%s" % str(random.getrandbits(128)),
67 "add -net %s netmask %s dev %s" % (destination, netmask, iface.devname),
73 ## APPLICATION ################################################################
75 class OmfApplication(OmfResource):
76 def __init__(self, guid, tc):
77 super(OmfApplication, self).__init__(guid, tc)
78 node_guids = tc.get_connected(guid, "node", "apps")
79 if len(node_guids) == 0:
80 raise RuntimeError("Can't instantiate interface %d outside node" % guid)
82 self._node_guid = node_guids[0]
89 node = self.tc.elements.get(self._node_guid)
90 self.tc.api.execute(node.hostname,
97 node = self.tc.elements.get(self._node_guid)
98 self.tc.api.exit(node.hostname,
102 if guid not in testbed_instance.elements.keys():
103 return AS.STATUS_NOT_STARTED
104 return AS.STATUS_RUNNING
106 #return AS.STATUS_FINISHED
109 ## WIFIIFACE ########################################################
111 class OmfWifiInterface(OmfResource):
112 alias2name = dict({'w0':'wlan0', 'w1':'wlan1'})
114 def __init__(self, guid, tc):
115 super(OmfWifiInterface, self).__init__(guid, tc)
116 node_guids = tc.get_connected(guid, "node", "devs")
117 if len(node_guids) == 0:
118 raise RuntimeError("Can't instantiate interface %d outside node" % guid)
120 self._node_guid = node_guids[0]
129 def __setattr__(self, name, value):
131 self.devname = self.alias2name.get(value)
133 if name in ["ip", "mode", "type", "essid", "channel"]:
134 node = self.tc.elements.get(self._node_guid)
135 attribute = "net/%s/%s" % (self.alias, name)
136 self._tc().api.configure(node.hostname, attribute, value)
138 super(OmfWifiInterface, self).__setattr__(name, value)
142 WIFIIFACE = "WifiInterface"
144 OMFAPPLICATION = "OmfApplication"
146 def create(factory, testbed_instance, guid):
150 elif factory == OMFAPPLICATION:
151 clazz = OmfApplication
152 elif factory == WIFIIFACE:
153 clazz = OmfWifiInterface
155 element = clazz(guid, testbed_instance)
156 #import pdb; pdb.set_trace()
157 testbed_instance._elements[guid] = element
159 def start(testbed_instance, guid):
160 element = testbed_instance.elements.get(guid)
163 def stop(testbed_instance, guid):
164 element = testbed_instance.elements.get(guid)
167 def status(testbed_instance, guid):
168 element = testbed_instance.elements.get(guid)
169 return element.status()
171 def configure(testbed_instance, guid):
172 element = testbed_instance.elements.get(guid)
173 return element.configure()
175 ### Factory information ###
177 connector_types = dict({
179 "help": "Connector from node to applications",
185 "help": "Connector to network interfaces",
191 "help": "Connector from a device to a channel",
197 "help": "Connector to a Node",
206 "from": (TESTBED_ID, NODE, "devs"),
207 "to": (TESTBED_ID, WIFIIFACE, "node"),
211 "from": (TESTBED_ID, WIFIIFACE, "chan"),
212 "to": (TESTBED_ID, CHANNEL, "devs"),
216 "from": (TESTBED_ID, NODE, "apps"),
217 "to": (TESTBED_ID, OMFAPPLICATION, "node"),
225 "help": "Application id",
226 "type": Attribute.STRING,
227 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
228 "validation_function": validation.is_string
232 "help": "Application arguments",
233 "type": Attribute.STRING,
234 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
235 "validation_function": validation.is_string
239 "help": "Path to binary (e.g '/opt/vlc-1.1.13/vlc')",
240 "type": Attribute.STRING,
241 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
242 "validation_function": validation.is_string
246 "help": "String with space separated values of environment variables to set before starting application (e.g 'FOO=foo BAR=bar')",
247 "type": Attribute.STRING,
248 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
249 "validation_function": validation.is_string
253 "help": "Hostname for the target OMF node",
254 "type": Attribute.STRING,
255 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
256 "validation_function": validation.is_string
260 "help": "Corresponds to the OMF attributes net/w0/mode",
261 "type": Attribute.STRING,
262 "flags": Attribute.NoDefaultValue,
263 "validation_function": validation.is_string
267 "help": "Corresponds to the OMF attributes net/w0/type",
268 "type": Attribute.STRING,
269 "flags": Attribute.NoDefaultValue,
270 "validation_function": validation.is_string
274 "help": "Corresponds to the OMF attributes net/w0/channel",
275 "type": Attribute.STRING,
276 "flags": Attribute.NoDefaultValue,
277 "validation_function": validation.is_string
281 "help": "Corresponds to the OMF attributes net/w0/essid",
282 "type": Attribute.STRING,
283 "flags": Attribute.NoDefaultValue,
284 "validation_function": validation.is_string
288 "help": "Corresponds to the OMF attributes net/w0/ip",
289 "type": Attribute.STRING,
290 "flags": Attribute.NoDefaultValue,
291 "validation_function": validation.is_ip4_address
295 "help": "Alias for device (e.g. w0, w1, etc)",
296 "type": Attribute.STRING,
298 "flags": Attribute.NoDefaultValue,
299 "validation_function": validation.is_string
305 create_order = [ NODE, WIFIIFACE, CHANNEL, OMFAPPLICATION ]
306 configure_order = [ WIFIIFACE, NODE, CHANNEL, OMFAPPLICATION ]
308 factories_info = dict({
311 "category": FC.CATEGORY_NODES,
312 "create_function": functools.partial(create, NODE),
313 "configure_function": configure,
314 "box_attributes": ["hostname"],
315 "connector_types": ["devs", "apps"],
316 "tags": [tags.NODE, tags.ALLOW_ROUTES],
319 "help": "Wireless network interface",
320 "category": FC.CATEGORY_DEVICES,
321 "create_function": functools.partial(create, WIFIIFACE),
322 "configure_function": configure,
323 "box_attributes": ["mode", "type", "channel", "essid", "ip", "alias"],
324 "connector_types": ["node", "chan"],
325 "tags": [tags.INTERFACE, tags.HAS_ADDRESSES],
328 "help": "Wireless channel",
329 "category": FC.CATEGORY_DEVICES,
330 "create_function": create,
331 "create_function": functools.partial(create, CHANNEL),
332 "box_attributes": ["mode", "type", "channel", "essid"],
333 "connector_types": ["devs"],
335 OMFAPPLICATION: dict({
336 "help": "Generic executable command line application",
337 "category": FC.CATEGORY_APPLICATIONS,
338 "create_function": functools.partial(create, OMFAPPLICATION),
339 "start_function": start,
340 "stop_function": stop,
341 "status_function": status,
342 "box_attributes": ["appId", "arguments", "path", "env"],
343 "connector_types": ["node"],
344 "tags": [tags.APPLICATION],
348 testbed_attributes = dict({
349 "enable_debug": dict({
350 "name": "enableDebug",
351 "help": "Enable netns debug output",
352 "type": Attribute.BOOL,
354 "validation_function": validation.is_bool
359 "type": Attribute.STRING,
360 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
361 "validation_function": validation.is_string
365 "help": "OMF XMPP server host",
366 "type": Attribute.STRING,
367 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
368 "validation_function": validation.is_string
372 "help": "OMF XMPP service port",
373 "type": Attribute.INTEGER,
374 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
375 "validation_function": validation.is_integer
377 "xmppPassword": dict({
378 "name": "xmppPassword",
379 "help": "OMF XMPP slice password",
380 "type": Attribute.STRING,
381 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
382 "validation_function": validation.is_string
386 "help": "Root node of the xmpp server pubsub tree",
387 "type": Attribute.STRING,
389 "flags": Attribute.ExecReadOnly | Attribute.ExecImmutable,
390 "validation_function": validation.is_string
394 supported_recovery_policies = [
398 class MetadataInfo(metadata.MetadataInfo):
400 def connector_types(self):
401 return connector_types
404 def connections(self):
408 def attributes(self):
416 def create_order(self):
420 def configure_order(self):
421 return configure_order
424 def factories_info(self):
425 return factories_info
428 def testbed_attributes(self):
429 return testbed_attributes
432 def testbed_id(self):
436 def testbed_version(self):
437 return TESTBED_VERSION
440 def supported_recover_policies(self):
441 return supported_recovery_policies