2 # -*- coding: utf-8 -*-
4 from constants import TESTBED_ID
5 from nepi.core import metadata
6 from nepi.core.attributes import Attribute
7 from nepi.util import validation
8 from nepi.util.constants import STATUS_NOT_STARTED, STATUS_RUNNING, \
12 NODEIFACE = "NodeInterface"
13 APPLICATION = "Application"
15 PL_TESTBED_ID = "planetlab"
17 ### Connection functions ####
19 ### Creation functions ###
21 def create_node(testbed_instance, guid):
22 parameters = testbed_instance._get_parameters(guid)
23 element = testbed_instance.pl.Node()
24 testbed_instance.elements[guid] = element
26 def create_nodeiface(testbed_instance, guid):
27 parameters = testbed_instance._get_parameters(guid)
28 element = testbed_instance.pl.Iface()
29 testbed_instance.elements[guid] = element
31 def create_application(testbed_instance, guid):
32 testbed_instance.elements[guid] = None # Delayed construction
34 ### Start/Stop functions ###
36 def start_application(testbed_instance, guid):
37 parameters = testbed_instance._get_parameters(guid)
38 traces = testbed_instance._get_traces(guid)
39 user = parameters["user"]
40 command = parameters["command"]
41 stdout = stderr = None
42 if "stdout" in traces:
43 filename = testbed_instance.trace_filename(guid, "stdout")
44 stdout = open(filename, "wb")
45 testbed_instance.follow_trace("stdout", stdout)
46 if "stderr" in traces:
47 filename = testbed_instance.trace_filename(guid, "stderr")
48 stderr = open(filename, "wb")
49 testbed_instance.follow_trace("stderr", stderr)
51 node_guid = testbed_instance.get_connected(guid, "node", "apps")
52 if len(node_guid) == 0:
53 raise RuntimeError("Can't instantiate interface %d outside netns \
55 node = testbed_instance.elements[node_guid[0]]
56 element = node.Popen(command, shell = True, stdout = stdout,
57 stderr = stderr, user = user)
58 testbed_instance.elements[guid] = element
60 ### Status functions ###
62 def status_application(testbed_instance, guid):
63 if guid not in testbed_instance.elements.keys():
64 return STATUS_NOT_STARTED
65 app = testbed_instance.elements[guid]
66 if app.poll() == None:
68 return STATUS_FINISHED
70 ### Configure functions ###
72 def configure_device(testbed_instance, guid):
73 element = testbed_instance._elements[guid]
74 if not guid in testbed_instance._add_address:
76 addresses = testbed_instance._add_address[guid]
77 for address in addresses:
78 (address, netprefix, broadcast) = address
79 # TODO: Decide if we should add a ipv4 or ipv6 address
80 element.add_v4_address(address, netprefix)
82 def configure_node(testbed_instance, guid):
83 element = testbed_instance._elements[guid]
84 if not guid in testbed_instance._add_route:
86 routes = testbed_instance._add_route[guid]
88 (destination, netprefix, nexthop) = route
89 element.add_route(prefix = destination, prefix_len = netprefix,
92 ### Factory information ###
94 connector_types = dict({
96 "help": "Connector from node to applications",
102 "help": "Connector from node to network interfaces",
108 "help": "Connector to a Node",
114 "help": "Connector to a P2PInterface",
120 "help": "Connector to a network interface that can receive a file descriptor",
126 "help": "Connector to a switch",
135 "from": (TESTBED_ID, NODE, "devs"),
136 "to": (TESTBED_ID, P2PIFACE, "node"),
141 "from": (TESTBED_ID, NODE, "devs"),
142 "to": (TESTBED_ID, TAPIFACE, "node"),
147 "from": (TESTBED_ID, NODE, "devs"),
148 "to": (TESTBED_ID, NODEIFACE, "node"),
153 "from": (TESTBED_ID, P2PIFACE, "p2p"),
154 "to": (TESTBED_ID, P2PIFACE, "p2p"),
159 "from": (TESTBED_ID, TAPIFACE, "fd"),
160 "to": (NS3_TESTBED_ID, FDNETDEV, "fd"),
161 "code": connect_fd_local,
165 "from": (TESTBED_ID, SWITCH, "devs"),
166 "to": (TESTBED_ID, NODEIFACE, "switch"),
167 "code": connect_switch,
171 "from": (TESTBED_ID, NODE, "apps"),
172 "to": (TESTBED_ID, APPLICATION, "node"),
179 "forward_X11": dict({
180 "name": "forward_X11",
181 "help": "Forward x11 from main namespace to the node",
182 "type": Attribute.BOOL,
184 "flags": Attribute.DesignOnly,
185 "validation_function": validation.is_bool
189 "help": "Mac address",
190 "type": Attribute.STRING,
191 "flags": Attribute.DesignOnly,
192 "validation_function": validation.is_mac_address
197 "type": Attribute.BOOL,
199 "validation_function": validation.is_bool
201 "device_name": dict({
203 "help": "Device name",
204 "type": Attribute.STRING,
205 "flags": Attribute.DesignOnly,
206 "validation_function": validation.is_string
210 "help": "Maximum transmition unit for device",
211 "type": Attribute.INTEGER,
212 "validation_function": validation.is_integer
216 "help": "Broadcast address",
217 "type": Attribute.STRING,
218 "validation_function": validation.is_string # TODO: should be is address!
222 "help": "Multicast enabled",
223 "type": Attribute.BOOL,
225 "validation_function": validation.is_bool
229 "help": "ARP enabled",
230 "type": Attribute.BOOL,
232 "validation_function": validation.is_bool
236 "help": "Command line string",
237 "type": Attribute.STRING,
238 "flags": Attribute.DesignOnly,
239 "validation_function": validation.is_string
243 "help": "System user",
244 "type": Attribute.STRING,
245 "flags": Attribute.DesignOnly,
246 "validation_function": validation.is_string
250 "help": "Standard input",
251 "type": Attribute.STRING,
252 "flags": Attribute.DesignOnly,
253 "validation_function": validation.is_string
260 "help": "Standard output stream"
264 "help": "Application standard error",
268 create_order = [ NODE, P2PIFACE, NODEIFACE, TAPIFACE, SWITCH,
271 configure_order = [ P2PIFACE, NODEIFACE, TAPIFACE, SWITCH, NODE,
274 factories_info = dict({
276 "allow_routes": True,
277 "help": "Emulated Node with virtualized network stack",
278 "category": "topology",
279 "create_function": create_node,
280 "configure_function": configure_node,
281 "box_attributes": ["forward_X11"],
282 "connector_types": ["devs", "apps"]
285 "allow_addresses": True,
286 "help": "Point to point network interface",
287 "category": "devices",
288 "create_function": create_p2piface,
289 "configure_function": configure_device,
290 "box_attributes": ["lladdr", "up", "device_name", "mtu",
291 "multicast", "broadcast", "arp"],
292 "connector_types": ["node", "p2p"]
295 "allow_addresses": True,
296 "help": "Tap device network interface",
297 "category": "devices",
298 "create_function": create_tapiface,
299 "configure_function": configure_device,
300 "box_attributes": ["lladdr", "up", "device_name", "mtu",
301 "multicast", "broadcast", "arp"],
302 "connector_types": ["node", "fd"]
305 "allow_addresses": True,
306 "help": "Node network interface",
307 "category": "devices",
308 "create_function": create_nodeiface,
309 "configure_function": configure_device,
310 "box_attributes": ["lladdr", "up", "device_name", "mtu",
311 "multicast", "broadcast", "arp"],
312 "connector_types": ["node", "switch"]
315 "display_name": "Switch",
316 "help": "Switch interface",
317 "category": "devices",
318 "create_function": create_switch,
319 "box_attributes": ["up", "device_name", "mtu", "multicast"],
320 #TODO: Add attribute ("Stp", help, type, value, range, allowed, readonly, validation_function),
321 #TODO: Add attribute ("ForwarddDelay", help, type, value, range, allowed, readonly, validation_function),
322 #TODO: Add attribute ("HelloTime", help, type, value, range, allowed, readonly, validation_function),
323 #TODO: Add attribute ("AgeingTime", help, type, value, range, allowed, readonly, validation_function),
324 #TODO: Add attribute ("MaxAge", help, type, value, range, allowed, readonly, validation_function)
325 "connector_types": ["devs"]
328 "help": "Generic executable command line application",
329 "category": "applications",
330 "create_function": create_application,
331 "start_function": start_application,
332 "status_function": status_application,
333 "box_attributes": ["command", "user"],
334 "connector_types": ["node"],
335 "traces": ["stdout", "stderr"]
339 testbed_attributes = dict({
340 "enable_debug": dict({
341 "name": "enableDebug",
342 "help": "Enable netns debug output",
343 "type": Attribute.BOOL,
345 "validation_function": validation.is_bool
349 class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
351 def connector_types(self):
352 return connector_types
355 def connections(self):
359 def attributes(self):
367 def create_order(self):
371 def configure_order(self):
372 return configure_order
375 def factories_info(self):
376 return factories_info
379 def testbed_attributes(self):
380 return testbed_attributes