Added attribute MaxAddresses for interface factories to design
[nepi.git] / src / nepi / testbeds / planetlab / metadata_v01.py
index c2f7e41..6fcc07d 100644 (file)
@@ -7,8 +7,9 @@ from constants import TESTBED_ID
 from nepi.core import metadata
 from nepi.core.attributes import Attribute
 from nepi.util import validation
-from nepi.util.constants import STATUS_NOT_STARTED, STATUS_RUNNING, \
-        STATUS_FINISHED, ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
+from nepi.util.constants import ApplicationStatus as AS, \
+        FactoryCategories as FC, \
+        ATTR_NEPI_TESTBED_ENVIRONMENT_SETUP
 
 import functools
 import os
@@ -43,13 +44,13 @@ def is_addrlist(attribute, value):
         if '/' in component:
             addr, mask = component.split('/',1)
         else:
-            addr, mask = component, 32
+            addr, mask = component, '32'
         
         if mask is not None and not (mask and mask.isdigit()):
             # No empty or nonnumeric masks
             return False
         
-        if not validation.is_ip4_address(attribute, value):
+        if not validation.is_ip4_address(attribute, addr):
             # Address part must be ipv4
             return False
         
@@ -147,6 +148,9 @@ def connect_dep(testbed_instance, node_guid, app_guid):
         for envkey, envval in app.env.iteritems():
             envval = app._replace_paths(envval)
             node.env[envkey].append(envval)
+    
+    if app.rpmFusion:
+        node.rpmFusion = True
 
 def connect_node_netpipe(testbed_instance, node_guid, netpipe_guid):
     node = testbed_instance._elements[node_guid]
@@ -166,12 +170,17 @@ def create_node(testbed_instance, guid):
     
     # add constraint on number of (real) interfaces
     # by counting connected devices
-    dev_guids = testbed_instance.get_connected(guid, "node", "devs")
+    dev_guids = testbed_instance.get_connected(guid, "devs", "node")
     num_open_ifaces = sum( # count True values
         NODEIFACE == testbed_instance._get_factory_id(guid)
         for guid in dev_guids )
     element.min_num_external_ifaces = num_open_ifaces
     
+    # require vroute vsys if we have routes to set up
+    routes = testbed_instance._add_route.get(guid)
+    if routes:
+        element.required_vsys.add("vroute")
+    
     testbed_instance.elements[guid] = element
 
 def create_nodeiface(testbed_instance, guid):
@@ -274,7 +283,7 @@ def stop_application(testbed_instance, guid):
 
 def status_application(testbed_instance, guid):
     if guid not in testbed_instance.elements.keys():
-        return STATUS_NOT_STARTED
+        return AS.STATUS_NOT_STARTED
     
     app = testbed_instance.elements[guid]
     return app.status()
@@ -372,12 +381,6 @@ def configure_node(testbed_instance, guid):
     # Do some validations
     node.validate()
     
-    # recently provisioned nodes may not be up yet
-    sleeptime = 1.0
-    while not node.is_alive():
-        time.sleep(sleeptime)
-        sleeptime = min(30.0, sleeptime*1.5)
-    
     # this will be done in parallel in all nodes
     # this call only spawns the process
     node.install_dependencies()
@@ -404,7 +407,7 @@ def configure_application(testbed_instance, guid):
     app.node.wait_dependencies()
     
     # Install stuff
-    app.setup()
+    app.async_setup()
 
 def configure_dependency(testbed_instance, guid):
     dep = testbed_instance._elements[guid]
@@ -416,7 +419,7 @@ def configure_dependency(testbed_instance, guid):
     dep.node.wait_dependencies()
     
     # Install stuff
-    dep.setup()
+    dep.async_setup()
 
 def configure_netpipe(testbed_instance, guid):
     netpipe = testbed_instance._elements[guid]
@@ -795,6 +798,14 @@ attributes = dict({
                 "flags": Attribute.DesignOnly,
                 "validation_function": validation.is_string
             }),
+    "rpm-fusion": dict({
+                "name": "rpmFusion",
+                "help": "True if required packages can be found in the RpmFusion repository",
+                "type": Attribute.BOOL,
+                "flags": Attribute.DesignOnly,
+                "value": False,
+                "validation_function": validation.is_bool
+            }),
     "sources": dict({
                 "name": "sources",
                 "help": "Space-separated list of regular files to be deployed in the working path prior to building. "
@@ -929,17 +940,17 @@ create_order = [ INTERNET, NODE, NODEIFACE, TAPIFACE, TUNIFACE, NETPIPE, NEPIDEP
 
 configure_order = [ INTERNET, NODE, NODEIFACE, TAPIFACE, TUNIFACE, NETPIPE, NEPIDEPENDENCY, NS3DEPENDENCY, DEPENDENCY, APPLICATION ]
 
-# Start node after ifaces, because the node needs the ifaces in order to set up routes
+# Start (and prestart) node after ifaces, because the node needs the ifaces in order to set up routes
 start_order = [ INTERNET, NODEIFACE, TAPIFACE, TUNIFACE, NODE, NETPIPE, NEPIDEPENDENCY, NS3DEPENDENCY, DEPENDENCY, APPLICATION ]
 
 factories_info = dict({
     NODE: dict({
             "allow_routes": True,
             "help": "Virtualized Node (V-Server style)",
-            "category": "topology",
+            "category": FC.CATEGORY_NODES,
             "create_function": create_node,
             "preconfigure_function": configure_node,
-            "start_function": configure_node_routes,
+            "prestart_function": configure_node_routes,
             "box_attributes": [
                 "forward_X11",
                 "hostname",
@@ -960,7 +971,7 @@ factories_info = dict({
     NODEIFACE: dict({
             "has_addresses": True,
             "help": "External network interface - they cannot be brought up or down, and they MUST be connected to the internet.",
-            "category": "devices",
+            "category": FC.CATEGORY_DEVICES,
             "create_function": create_nodeiface,
             "preconfigure_function": configure_nodeiface,
             "box_attributes": [ ],
@@ -969,11 +980,11 @@ factories_info = dict({
     TUNIFACE: dict({
             "allow_addresses": True,
             "help": "Virtual TUN network interface (layer 3)",
-            "category": "devices",
+            "category": FC.CATEGORY_DEVICES,
             "create_function": create_tuniface,
             "preconfigure_function": preconfigure_tuniface,
             "configure_function": postconfigure_tuniface,
-            "start_function": wait_tuniface,
+            "prestart_function": wait_tuniface,
             "box_attributes": [
                 "up", "device_name", "mtu", "snat", "pointopoint",
                 "txqueuelen",
@@ -985,11 +996,11 @@ factories_info = dict({
     TAPIFACE: dict({
             "allow_addresses": True,
             "help": "Virtual TAP network interface (layer 2)",
-            "category": "devices",
+            "category": FC.CATEGORY_DEVICES,
             "create_function": create_tapiface,
             "preconfigure_function": preconfigure_tuniface,
             "configure_function": postconfigure_tuniface,
-            "start_function": wait_tuniface,
+            "prestart_function": wait_tuniface,
             "box_attributes": [
                 "up", "device_name", "mtu", "snat", "pointopoint",
                 "txqueuelen",
@@ -1000,7 +1011,7 @@ factories_info = dict({
         }),
     APPLICATION: dict({
             "help": "Generic executable command line application",
-            "category": "applications",
+            "category": FC.CATEGORY_APPLICATIONS,
             "create_function": create_application,
             "start_function": start_application,
             "status_function": status_application,
@@ -1008,23 +1019,23 @@ factories_info = dict({
             "configure_function": configure_application,
             "box_attributes": ["command", "sudo", "stdin",
                                "depends", "build-depends", "build", "install",
-                               "sources" ],
+                               "sources", "rpm-fusion" ],
             "connector_types": ["node"],
             "traces": ["stdout", "stderr", "buildlog"]
         }),
     DEPENDENCY: dict({
             "help": "Requirement for package or application to be installed on some node",
-            "category": "applications",
+            "category": FC.CATEGORY_APPLICATIONS,
             "create_function": create_dependency,
             "preconfigure_function": configure_dependency,
             "box_attributes": ["depends", "build-depends", "build", "install",
-                               "sources" ],
+                               "sources", "rpm-fusion" ],
             "connector_types": ["node"],
             "traces": ["buildlog"]
         }),
     NEPIDEPENDENCY: dict({
             "help": "Requirement for NEPI inside NEPI - required to run testbed instances inside a node",
-            "category": "applications",
+            "category": FC.CATEGORY_APPLICATIONS,
             "create_function": create_nepi_dependency,
             "preconfigure_function": configure_dependency,
             "box_attributes": [ ],
@@ -1033,7 +1044,7 @@ factories_info = dict({
         }),
     NS3DEPENDENCY: dict({
             "help": "Requirement for NS3 inside NEPI - required to run NS3 testbed instances inside a node. It also needs NepiDependency.",
-            "category": "applications",
+            "category": FC.CATEGORY_APPLICATIONS,
             "create_function": create_ns3_dependency,
             "preconfigure_function": configure_dependency,
             "box_attributes": [ ],
@@ -1042,13 +1053,13 @@ factories_info = dict({
         }),
     INTERNET: dict({
             "help": "Internet routing",
-            "category": "topology",
+            "category": FC.CATEGORY_CHANNELS,
             "create_function": create_internet,
             "connector_types": ["devs"],
         }),
     NETPIPE: dict({
             "help": "Link emulation",
-            "category": "topology",
+            "category": FC.CATEGORY_CHANNELS,
             "create_function": create_netpipe,
             "configure_function": configure_netpipe,
             "box_attributes": ["netpipe_mode",
@@ -1136,6 +1147,10 @@ class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
     def configure_order(self):
         return configure_order
 
+    @property
+    def prestart_order(self):
+        return start_order
+
     @property
     def start_order(self):
         return start_order