from nepi.core import execute
from nepi.core.metadata import Metadata
from nepi.util import validation
-from nepi.util.constants import STATUS_UNDETERMINED, TIME_NOW, \
- TESTBED_STATUS_ZERO, \
- TESTBED_STATUS_SETUP, \
- TESTBED_STATUS_CREATED, \
- TESTBED_STATUS_CONNECTED, \
- TESTBED_STATUS_CROSS_CONNECTED, \
- TESTBED_STATUS_CONFIGURED, \
- TESTBED_STATUS_STARTED, \
- TESTBED_STATUS_STOPPED
+from nepi.util.constants import TIME_NOW, \
+ ApplicationStatus as AS, \
+ TestbedStatus as TS, \
+ CONNECTION_DELAY
import collections
+import copy
class TestbedController(execute.TestbedController):
def __init__(self, testbed_id, testbed_version):
super(TestbedController, self).__init__(testbed_id, testbed_version)
- self._status = TESTBED_STATUS_ZERO
+ self._status = TS.STATUS_ZERO
# testbed attributes for validation
self._attributes = None
# element factories for validation
self._add_address[guid] = list()
self._add_address[guid].append((address, netprefix, broadcast))
- def defer_add_route(self, guid, destination, netprefix, nexthop):
+ def defer_add_route(self, guid, destination, netprefix, nexthop, metric = 0):
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
factory = self._get_factory(guid)
factory.factory_id)
if not guid in self._add_route:
self._add_route[guid] = list()
- self._add_route[guid].append((destination, netprefix, nexthop))
+ self._add_route[guid].append((destination, netprefix, nexthop, metric))
def do_setup(self):
self._root_directory = self._attributes.\
get_attribute_value("rootDirectory")
- self._status = TESTBED_STATUS_SETUP
+ self._status = TS.STATUS_SETUP
def do_create(self):
def set_params(self, guid):
'create_function',
self._metadata.create_order,
postaction = set_params )
- self._status = TESTBED_STATUS_CREATED
+ self._status = TS.STATUS_CREATED
def _do_connect(self, init = True):
- for guid1, connections in self._connect.iteritems():
- factory1 = self._get_factory(guid1)
- for connector_type_name1, connections2 in connections.iteritems():
- connector_type1 = factory1.connector_type(connector_type_name1)
- for guid2, connector_type_name2 in connections2.iteritems():
- factory_id2 = self._create[guid2]
- # Connections are executed in a "From -> To" direction only
- # This explicitly ignores the "To -> From" (mirror)
- # connections of every connection pair.
- if init:
- connect_code = connector_type1.connect_to_init_code(
- self._testbed_id, factory_id2,
- connector_type_name2,
- False)
- else:
- connect_code = connector_type1.connect_to_compl_code(
- self._testbed_id, factory_id2,
- connector_type_name2,
- False)
- if connect_code:
- connect_code(self, guid1, guid2)
+ unconnected = copy.deepcopy(self._connect)
+
+ while unconnected:
+ for guid1, connections in unconnected.items():
+ factory1 = self._get_factory(guid1)
+ for connector_type_name1, connections2 in connections.items():
+ connector_type1 = factory1.connector_type(connector_type_name1)
+ for guid2, connector_type_name2 in connections2.items():
+ factory_id2 = self._create[guid2]
+ # Connections are executed in a "From -> To" direction only
+ # This explicitly ignores the "To -> From" (mirror)
+ # connections of every connection pair.
+ if init:
+ connect_code = connector_type1.connect_to_init_code(
+ self._testbed_id, factory_id2,
+ connector_type_name2,
+ False)
+ else:
+ connect_code = connector_type1.connect_to_compl_code(
+ self._testbed_id, factory_id2,
+ connector_type_name2,
+ False)
+ delay = None
+ if connect_code:
+ delay = connect_code(self, guid1, guid2)
+
+ if delay is not CONNECTION_DELAY:
+ del unconnected[guid1][connector_type_name1][guid2]
+ if not unconnected[guid1][connector_type_name1]:
+ del unconnected[guid1][connector_type_name1]
+ if not unconnected[guid1]:
+ del unconnected[guid1]
def do_connect_init(self):
self._do_connect()
def do_connect_compl(self):
self._do_connect(init = False)
- self._status = TESTBED_STATUS_CONNECTED
+ self._status = TS.STATUS_CONNECTED
- def _do_in_factory_order(self, action, order, postaction = None):
+ def _do_in_factory_order(self, action, order, postaction = None, poststep = None):
guids = collections.defaultdict(list)
# order guids (elements) according to factory_id
for guid, factory_id in self._create.iteritems():
getattr(factory, action)(self, guid)
if postaction:
postaction(self, guid)
+ if poststep:
+ for guid in guids[factory_id]:
+ poststep(self, guid)
+
+ @staticmethod
+ def do_poststep_preconfigure(self, guid):
+ # dummy hook for implementations interested in
+ # two-phase configuration
+ pass
def do_preconfigure(self):
self._do_in_factory_order(
'preconfigure_function',
- self._metadata.preconfigure_order )
+ self._metadata.preconfigure_order,
+ poststep = self.do_poststep_preconfigure )
+
+ @staticmethod
+ def do_poststep_configure(self, guid):
+ # dummy hook for implementations interested in
+ # two-phase configuration
+ pass
def do_configure(self):
self._do_in_factory_order(
'configure_function',
- self._metadata.configure_order )
- self._status = TESTBED_STATUS_CONFIGURED
+ self._metadata.configure_order,
+ poststep = self.do_poststep_configure )
+ self._status = TS.STATUS_CONFIGURED
def do_prestart(self):
self._do_in_factory_order(
def do_cross_connect_compl(self, cross_data):
self._do_cross_connect(cross_data, init = False)
- self._status = TESTBED_STATUS_CROSS_CONNECTED
+ self._status = TS.STATUS_CROSS_CONNECTED
def set(self, guid, name, value, time = TIME_NOW):
if not guid in self._create:
if not factory.box_attributes.has_attribute(name):
raise AttributeError("Invalid attribute %s for element type %s" %
(name, factory.factory_id))
- if self._status > TESTBED_STATUS_STARTED and \
+ if self._status > TS.STATUS_STARTED and \
factory.box_attributes.is_attribute_design_only(name):
raise AttributeError("Attribute %s can only be modified during experiment design" % name)
if not factory.box_attributes.is_attribute_value_valid(name, value):
return addresses[index][attribute_index]
- def get_tags(self, guid):
- factory = self._get_factory(guid)
- return factory.tags
-
def get_attribute_list(self, guid):
factory = self._get_factory(guid)
attribute_list = list()
return factory.box_attributes.attributes_list
+ def get_factory_id(self, guid):
+ factory = self._get_factory(guid)
+ return factory.factory_id
+
def start(self, time = TIME_NOW):
self._do_in_factory_order(
'start_function',
self._metadata.start_order )
- self._status = TESTBED_STATUS_STARTED
+ self._status = TS.STATUS_STARTED
#action: NotImplementedError
self._do_in_factory_order(
'stop_function',
reversed(self._metadata.start_order) )
- self._status = TESTBED_STATUS_STOPPED
+ self._status = TS.STATUS_STOPPED
def status(self, guid = None):
if not guid:
status_function = factory.status_function
if status_function:
return status_function(self, guid)
- return STATUS_UNDETERMINED
+ return AS.STATUS_UNDETERMINED
def trace(self, guid, trace_id, attribute='value'):
if attribute == 'value':
- fd = open("%s" % self.trace_filename(guid, trace_id), "r")
+ fd = open("%s" % self.trace_filepath(guid, trace_id), "r")
content = fd.read()
fd.close()
elif attribute == 'path':
- content = self.trace_filename(guid, trace_id)
+ content = self.trace_filepath(guid, trace_id)
else:
content = None
return content
- def trace_filename(self, guid, trace_id):
+ def traces_info(self):
+ traces_info = dict()
+ host = self._attributes.get_attribute_value("deployment_host")
+ user = self._attributes.get_attribute_value("deployment_user")
+ for guid, trace_list in self._add_trace.iteritems():
+ traces_info[guid] = dict()
+ for trace_id in trace_list:
+ traces_info[guid][trace_id] = dict()
+ filepath = self.trace(guid, trace_id, attribute = "path")
+ traces_info[guid][trace_id]["host"] = host
+ traces_info[guid][trace_id]["user"] = user
+ traces_info[guid][trace_id]["filepath"] = filepath
+ return traces_info
+
+ def trace_filepath(self, guid, trace_id):
"""
Return a trace's file path, for TestbedController's default
implementation of trace()