Added routes to OMF nodes
[nepi.git] / src / nepi / core / testbed_impl.py
index f496f4a..d27588d 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 from nepi.core import execute
@@ -12,6 +11,7 @@ from nepi.util.parallel import ParallelRun
 
 import collections
 import copy
+import logging
 
 class TestbedController(execute.TestbedController):
     def __init__(self, testbed_id, testbed_version):
@@ -49,6 +49,9 @@ class TestbedController(execute.TestbedController):
             self._factories[factory.factory_id] = factory
         self._attributes = self._metadata.testbed_attributes()
         self._root_directory = None
+        
+        # Logging
+        self._logger = logging.getLogger("nepi.core.testbed_impl")
     
     @property
     def root_directory(self):
@@ -147,12 +150,14 @@ class TestbedController(execute.TestbedController):
             self._add_address[guid] = list()
         self._add_address[guid].append((address, netprefix, broadcast))
 
-    def defer_add_route(self, guid, destination, netprefix, nexthop, metric = 0):
+    def defer_add_route(self, guid, destination, netprefix, nexthop, 
+            metric = 0, device = None):
         self._validate_guid(guid)
         self._validate_allow_routes(guid)
         if not guid in self._add_route:
             self._add_route[guid] = list()
-        self._add_route[guid].append((destination, netprefix, nexthop, metric)) 
+        self._add_route[guid].append((destination, netprefix, nexthop, 
+            metric, device)) 
 
     def do_setup(self):
         self._root_directory = self._attributes.\
@@ -213,6 +218,8 @@ class TestbedController(execute.TestbedController):
         self._status = TS.STATUS_CONNECTED
 
     def _do_in_factory_order(self, action, order, postaction = None, poststep = None):
+        logger = self._logger
+        
         guids = collections.defaultdict(list)
         # order guids (elements) according to factory_id
         for guid, factory_id in self._create.iteritems():
@@ -232,28 +239,47 @@ class TestbedController(execute.TestbedController):
             
             # configure action
             factory = self._factories[factory_id]
-            if not getattr(factory, action):
+            if isinstance(action, basestring) and not getattr(factory, action):
                 continue
             def perform_action(guid):
-                getattr(factory, action)(self, guid)
+                if isinstance(action, basestring):
+                    getattr(factory, action)(self, guid)
+                else:
+                    action(self, guid)
                 if postaction:
                     postaction(self, guid)
 
             # perform the action on all elements, in parallel if so requested
             if runner:
+                logger.debug("TestbedController: Starting parallel %s", action)
                 runner.start()
+
             for guid in guids[factory_id]:
                 if runner:
+                    logger.debug("TestbedController: Scheduling %s on %s", action, guid)
                     runner.put(perform_action, guid)
                 else:
+                    logger.debug("TestbedController: Performing %s on %s", action, guid)
                     perform_action(guid)
+
+            # sync
             if runner:
-                runner.join()
+                runner.sync()
             
             # post hook
             if poststep:
                 for guid in guids[factory_id]:
-                    poststep(self, guid)
+                    if runner:
+                        logger.debug("TestbedController: Scheduling post-%s on %s", action, guid)
+                        runner.put(poststep, self, guid)
+                    else:
+                        logger.debug("TestbedController: Performing post-%s on %s", action, guid)
+                        poststep(self, guid)
+
+            # sync
+            if runner:
+                runner.join()
+                logger.debug("TestbedController: Finished parallel %s", action)
 
     @staticmethod
     def do_poststep_preconfigure(self, guid):
@@ -304,6 +330,14 @@ class TestbedController(execute.TestbedController):
                         cross_connector_type_name,
                         True)
                 if connect_code:
+                    if hasattr(connect_code, "func"):
+                        func_name = connect_code.func.__name__
+                    elif hasattr(connect_code, "__name__"):
+                        func_name = connect_code.__name__
+                    else:
+                        func_name = repr(connect_code)
+                    self._logger.debug("Cross-connect - guid: %d, connect_code: %s " % (
+                        guid, func_name))
                     elem_cross_data = cross_data[cross_testbed_guid][cross_guid]
                     connect_code(self, guid, elem_cross_data)       
 
@@ -432,6 +466,9 @@ class TestbedController(execute.TestbedController):
         if status_function:
             return status_function(self, guid)
         return AS.STATUS_UNDETERMINED
+    
+    def testbed_status(self):
+        return self._status
 
     def trace(self, guid, trace_id, attribute='value'):
         if attribute == 'value':
@@ -440,6 +477,8 @@ class TestbedController(execute.TestbedController):
             fd.close()
         elif attribute == 'path':
             content = self.trace_filepath(guid, trace_id)
+        elif attribute == 'filename':
+            content = self.trace_filename(guid, trace_id)
         else:
             content = None
         return content
@@ -465,6 +504,13 @@ class TestbedController(execute.TestbedController):
         """
         raise NotImplementedError
 
+    def trace_filename(self, guid, trace_id):
+        """
+        Return a trace's file name, for TestbedController's default 
+        implementation of trace()
+        """
+        raise NotImplementedError
+
     #shutdown: NotImplementedError
 
     def get_connected(self, guid, connector_type_name, 
@@ -531,7 +577,7 @@ class TestbedController(execute.TestbedController):
 
     def _validate_testbed_value(self, name, value):
         if not self._attributes.is_attribute_value_valid(name, value):
-            raise AttributeError("Invalid value %s for testbed attribute %s" % \
+            raise AttributeError("Invalid value %r for testbed attribute %s" % \
                 (value, name))
 
     def _validate_box_attribute(self, guid, name):
@@ -543,7 +589,7 @@ class TestbedController(execute.TestbedController):
     def _validate_box_value(self, guid, name, value):
         factory = self._get_factory(guid)
         if not factory.box_attributes.is_attribute_value_valid(name, value):
-            raise AttributeError("Invalid value %s for attribute %s" % \
+            raise AttributeError("Invalid value %r for attribute %s" % \
                 (value, name))
 
     def _validate_factory_attribute(self, guid, name):
@@ -555,7 +601,7 @@ class TestbedController(execute.TestbedController):
     def _validate_factory_value(self, guid, name, value):
         factory = self._get_factory(guid)
         if not factory.is_attribute_value_valid(name, value):
-            raise AttributeError("Invalid value %s for attribute %s" % \
+            raise AttributeError("Invalid value %r for attribute %s" % \
                 (value, name))
 
     def _validate_trace(self, guid, trace_name):