# -*- coding: utf-8 -*-
from nepi.core.attributes import Attribute, AttributesMap
+from nepi.util.constants import STATUS_FINISHED
+from nepi.util.parser._xml import XmlExperimentParser
from nepi.util import validation
import sys
self._status_function = status_function
self._connector_types = dict()
self._traces = list()
+ self._box_attributes = AttributesMap()
@property
def factory_id(self):
def allow_routes(self):
return self._allow_routes
+ @property
+ def box_attributes(self):
+ return self._box_attributes
+
@property
def create_function(self):
return self._create_function
def add_trace(self, trace_id):
self._traces.append(trace_id)
-class TestbedConfiguration(AttributesMap):
- def __init__(self):
- super(TestbedConfiguration, self).__init__()
- self.add_attribute("HomeDirectory",
- "Path to the local directory where traces and other files \
- will be stored",
- Attribute.STRING, False, None, None, "",
- validation.is_string)
+ def add_box_attribute(self, name, help, type, value = None, range = None,
+ allowed = None, flags = Attribute.NoFlags, validation_function = None):
+ self._box_attributes.add_attribute(name, help, type, value, range,
+ allowed, flags, validation_function)
class TestbedInstance(object):
- def __init__(self, testbed_id, testbed_version, configuration):
+ def __init__(self, testbed_id, testbed_version):
self._testbed_id = testbed_id
self._testbed_version = testbed_version
- self._configuration = configuration
- self._home_directory = configuration.get_attribute_value(
- "HomeDirectory")
@property
- def home_directory(self):
- return self._home_directory
+ def guids(self):
+ raise NotImplementedError
+
+ def configure(self, name, value):
+ """Set a configuartion attribute for the testbed instance"""
+ raise NotImplementedError
def create(self, guid, factory_id):
"""Instructs creation of element """
raise NotImplementedError
def create_set(self, guid, name, value):
- """Instructs setting an attribute on an element"""
+ """Instructs setting an initial attribute on an element"""
raise NotImplementedError
- def do_create(self):
- """After do_create all instructed elements are created and
- attributes setted"""
+ def factory_set(self, guid, name, value):
+ """Instructs setting an attribute on a factory"""
raise NotImplementedError
def connect(self, guid1, connector_type_name1, guid2,
cross_testbed_id, cross_factory_id, cross_connector_type_name):
raise NotImplementedError
- def do_connect(self):
- raise NotImplementedError
-
def add_trace(self, guid, trace_id):
raise NotImplementedError
def add_route(self, guid, destination, netprefix, nexthop):
raise NotImplementedError
+ def do_setup(self):
+ """After do_setup the testbed initial configuration is done"""
+ raise NotImplementedError
+
+ def do_create(self):
+ """After do_create all instructed elements are created and
+ attributes setted"""
+ raise NotImplementedError
+
+ def do_connect(self):
+ """After do_connect all internal connections between testbed elements
+ are done"""
+ raise NotImplementedError
+
def do_configure(self):
+ """After do_configure elements are configured"""
raise NotImplementedError
def do_cross_connect(self):
+ """After do_cross_connect all external connections between different testbed
+ elements are done"""
raise NotImplementedError
- def set(self, time, guid, name, value):
+ def start(self, time):
raise NotImplementedError
- def get(self, time, guid, name):
+ def stop(self, time):
raise NotImplementedError
- def start(self, time):
+ def set(self, time, guid, name, value):
raise NotImplementedError
- def action(self, time, guid, action):
+ def get(self, time, guid, name):
raise NotImplementedError
- def stop(self, time):
+ def action(self, time, guid, action):
raise NotImplementedError
def status(self, guid):
def shutdown(self):
raise NotImplementedError
+class ExperimentController(object):
+ def __init__(self, experiment_xml):
+ self._experiment_xml = experiment_xml
+ self._testbeds = dict()
+ self._access_config = dict()
+
+ @property
+ def experiment_xml(self):
+ return self._experiment_xml
+
+ def testbed_instance(self, guid):
+ return self._testbeds[guid]
+
+ def set_testbed_access_config(self, guid, access_config):
+ self._access_config[guid] = access_config
+
+ def trace(self, testbed_guid, guid, trace_id):
+ return self._testbeds[testbed_guid].trace(guid, trace_id)
+
+ def start(self):
+ self._create_testbed_instances()
+ for instance in self._testbeds.values():
+ instance.do_setup()
+ for instance in self._testbeds.values():
+ instance.do_create()
+ instance.do_connect()
+ instance.do_configure()
+ for instances in self._testbeds.values():
+ instance.do_cross_connect()
+ for instances in self._testbeds.values():
+ instance.start()
+
+ def stop(self):
+ for instance in self._testbeds.values():
+ instance.stop()
+
+ def is_finished(self, guid):
+ for instance in self._testbeds.values():
+ for guid_ in instance.guids:
+ if guid_ == guid:
+ return instance.status(guid) == STATUS_FINISHED
+ raise RuntimeError("No element exists with guid %d" % guid)
+
+ def shutdown(self):
+ for instance in self._testbeds.values():
+ instance.shutdown()
+
+ def _build_testbed_instance(self, testbed_id, testbed_version):
+ mod_name = "nepi.testbeds.%s" % (testbed_id.lower())
+ if not mod_name in sys.modules:
+ __import__(mod_name)
+ module = sys.modules[mod_name]
+ return module.TestbedInstance(testbed_version)
+
+ def _create_testbed_instances(self):
+ parser = XmlExperimentParser()
+ data = parser.from_xml_to_data(self._experiment_xml)
+ element_guids = list()
+ for guid in data.guids:
+ if data.is_testbed_data(guid):
+ (testbed_id, testbed_version) = data.get_testbed_data(guid)
+ instance = self._build_testbed_instance(testbed_id,
+ testbed_version)
+ for (name, value) in data.get_attribute_data(guid):
+ instance.configure(name, value)
+ self._testbeds[guid] = instance
+ else:
+ element_guids.append(guid)
+ self._program_testbed_instances(element_guids, data)
+
+ def _program_testbed_instances(self, element_guids, data):
+ for guid in element_guids:
+ (testbed_guid, factory_id) = data.get_box_data(guid)
+ instance = self._testbeds[testbed_guid]
+ instance.create(guid, factory_id)
+ for (name, value) in data.get_attribute_data(guid):
+ instance.create_set(guid, name, value)
+
+ for guid in element_guids:
+ (testbed_guid, factory_id) = data.get_box_data(guid)
+ instance = self._testbeds[testbed_guid]
+ for (connector_type_name, other_guid, other_connector_type_name) \
+ in data.get_connection_data(guid):
+ (testbed_guid, factory_id) = data.get_box_data(guid)
+ (other_testbed_guid, other_factory_id) = data.get_box_data(
+ other_guid)
+ if testbed_guid == other_testbed_guid:
+ instance.connect(guid, connector_type_name, other_guid,
+ other_connector_type_name)
+ else:
+ instance.cross_connect(guid, connector_type_name, other_guid,
+ other_testbed_id, other_factory_id, other_connector_type_name)
+ for trace_id in data.get_trace_data(guid):
+ instance.add_trace(guid, trace_id)
+ for (autoconf, address, family, netprefix, broadcast) in \
+ data.get_address_data(guid):
+ if address != None:
+ instance.add_adddress(guid, family, address, netprefix,
+ broadcast)
+ for (family, destination, netprefix, nexthop) in \
+ data.get_route_data(guid):
+ instance.add_route(guid, destination, netprefix, nexthop)
+