TESTBED_STATUS_STARTED, \
TESTBED_STATUS_STOPPED
+import collections
+
class TestbedController(execute.TestbedController):
def __init__(self, testbed_id, testbed_version):
super(TestbedController, self).__init__(testbed_id, testbed_version)
self._configure = dict()
# log of set operations
+ self._setlog = dict()
+ # last set operations
self._set = dict()
# testbed element instances
for factory in self._metadata.build_execute_factories():
self._factories[factory.factory_id] = factory
self._attributes = self._metadata.testbed_attributes()
+ self._root_directory = None
+
+ @property
+ def root_directory(self):
+ return self._root_directory
@property
def guids(self):
def defer_create_set(self, guid, name, value):
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
if not factory.box_attributes.has_attribute(name):
raise AttributeError("Invalid attribute %s for element type %s" %
- (name, factory_id))
+ (name, factory.factory_id))
if not factory.box_attributes.is_attribute_value_valid(name, value):
raise AttributeError("Invalid value %s for attribute %s" % \
(value, name))
def defer_factory_set(self, guid, name, value):
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
if not factory.has_attribute(name):
raise AttributeError("Invalid attribute %s for element type %s" %
- (name, factory_id))
+ (name, factory.factory_id))
if not factory.is_attribute_value_valid(name, value):
raise AttributeError("Invalid value %s for attribute %s" % \
(value, name))
def defer_connect(self, guid1, connector_type_name1, guid2,
connector_type_name2):
- factory_id1 = self._create[guid1]
+ factory1 = self._get_factory(guid1)
factory_id2 = self._create[guid2]
count = self._get_connection_count(guid1, connector_type_name1)
- factory1 = self._factories[factory_id1]
connector_type = factory1.connector_type(connector_type_name1)
connector_type.can_connect(self._testbed_id, factory_id2,
- connector_type_name2, count)
+ connector_type_name2, count, False)
if not guid1 in self._connect:
self._connect[guid1] = dict()
if not connector_type_name1 in self._connect[guid1]:
connector_type_name1
def defer_cross_connect(self, guid, connector_type_name, cross_guid,
- cross_testbed_id, cross_factory_id, cross_connector_type_name):
- factory_id = self._create[guid]
+ cross_testbed_guid, cross_testbed_id, cross_factory_id,
+ cross_connector_type_name):
+ factory = self._get_factory(guid)
count = self._get_connection_count(guid, connector_type_name)
- factory = self._factories[factory_id]
connector_type = factory.connector_type(connector_type_name)
connector_type.can_connect(cross_testbed_id, cross_factory_id,
- cross_connector_type_name, count, must_cross = True)
+ cross_connector_type_name, count, True)
if not guid in self._cross_connect:
self._cross_connect[guid] = dict()
if not connector_type_name in self._cross_connect[guid]:
self._cross_connect[guid][connector_type_name] = dict()
self._cross_connect[guid][connector_type_name] = \
- (cross_guid, cross_testbed_id, cross_factory_id,
- cross_connector_type_name)
+ (cross_guid, cross_testbed_guid, cross_testbed_id,
+ cross_factory_id, cross_connector_type_name)
def defer_add_trace(self, guid, trace_id):
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
if not trace_id in factory.traces:
raise RuntimeError("Element type '%s' has no trace '%s'" %
- (factory_id, trace_id))
+ (factory.factory_id, trace_id))
if not guid in self._add_trace:
self._add_trace[guid] = list()
self._add_trace[guid].append(trace_id)
def defer_add_address(self, guid, address, netprefix, broadcast):
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
if not factory.allow_addresses:
raise RuntimeError("Element type '%s' doesn't support addresses" %
- factory_id)
+ factory.factory_id)
max_addresses = 1 # TODO: MAKE THIS PARAMETRIZABLE
if guid in self._add_address:
count_addresses = len(self._add_address[guid])
if max_addresses == count_addresses:
raise RuntimeError("Element guid %d of type '%s' can't accept \
- more addresses" % (guid, factory_id))
+ more addresses" % (guid, factory.factory_id))
else:
self._add_address[guid] = list()
self._add_address[guid].append((address, netprefix, broadcast))
def defer_add_route(self, guid, destination, netprefix, nexthop):
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
if not factory.allow_routes:
raise RuntimeError("Element type '%s' doesn't support routes" %
- factory_id)
+ factory.factory_id)
if not guid in self._add_route:
self._add_route[guid] = list()
self._add_route[guid].append((destination, netprefix, nexthop))
def do_setup(self):
+ self._root_directory = self._attributes.\
+ get_attribute_value("rootDirectory")
self._status = TESTBED_STATUS_SETUP
def do_create(self):
factory.create_function(self, guid)
parameters = self._get_parameters(guid)
for name, value in parameters.iteritems():
- self.set(TIME_NOW, guid, name, value)
+ self.set(guid, name, value)
self._status = TESTBED_STATUS_CREATED
def _do_connect(self, init = True):
for guid1, connections in self._connect.iteritems():
- element1 = self._elements[guid1]
- factory_id1 = self._create[guid1]
- factory1 = self._factories[factory_id1]
+ 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():
- element2 = self._elements[guid2]
factory_id2 = self._create[guid2]
# Connections are executed in a "From -> To" direction only
# This explicitly ignores the "To -> From" (mirror)
if init:
connect_code = connector_type1.connect_to_init_code(
self._testbed_id, factory_id2,
- connector_type_name2)
+ connector_type_name2,
+ False)
else:
connect_code = connector_type1.connect_to_compl_code(
self._testbed_id, factory_id2,
- connector_type_name2)
+ connector_type_name2,
+ False)
if connect_code:
- connect_code(self, element1, element2)
+ connect_code(self, guid1, guid2)
def do_connect_init(self):
self._do_connect()
def _do_cross_connect(self, cross_data, init = True):
for guid, cross_connections in self._cross_connect.iteritems():
- element = self._elements[guid]
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
for connector_type_name, cross_connection in \
cross_connections.iteritems():
connector_type = factory.connector_type(connector_type_name)
- (cross_testbed_id, cross_factory_id,
- cross_connector_type_name) = cross_connection
+ (cross_guid, cross_testbed_guid, cross_testbed_id,
+ cross_factory_id, cross_connector_type_name) = cross_connection
if init:
connect_code = connector_type.connect_to_init_code(
cross_testbed_id, cross_factory_id,
- cross_conector_type_name)
+ cross_connector_type_name,
+ True)
else:
connect_code = connector_type.connect_to_compl_code(
cross_testbed_id, cross_factory_id,
- cross_conector_type_name)
+ cross_connector_type_name,
+ True)
if connect_code:
- elem_data_guid = cross_data[cross_testbed_id][cross_guid]
- connect_code(self, element, elem_cross_data)
+ elem_cross_data = cross_data[cross_testbed_guid][cross_guid]
+ connect_code(self, guid, elem_cross_data)
def do_cross_connect_init(self, cross_data):
self._do_cross_connect(cross_data)
self._do_cross_connect(cross_data, init = False)
self._status = TESTBED_STATUS_CROSS_CONNECTED
- def set(self, time, guid, name, value):
+ def set(self, guid, name, value, time = TIME_NOW):
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
if not factory.box_attributes.has_attribute(name):
raise AttributeError("Invalid attribute %s for element type %s" %
- (name, factory_id))
- if self._status > TESTBED_STATUS_CREATED and \
+ (name, factory.factory_id))
+ if self._status > TESTBED_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):
(value, name))
if guid not in self._set:
self._set[guid] = dict()
- if time not in self._set[guid]:
- self._set[guid][time] = dict()
- self._set[guid][time][name] = value
+ self._setlog[guid] = dict()
+ if time not in self._setlog[guid]:
+ self._setlog[guid][time] = dict()
+ self._setlog[guid][time][name] = value
+ self._set[guid][name] = value
- def box_get(self, time, guid, name):
+ def get(self, guid, name, time = TIME_NOW):
"""
- Helper for subclasses, gets an attribute from box definitions
- if available. Throws KeyError if the GUID wasn't created
+ gets an attribute from box definitions if available.
+ Throws KeyError if the GUID wasn't created
through the defer_create interface, and AttributeError if the
attribute isn't available (doesn't exist or is design-only)
"""
if not guid in self._create:
raise KeyError, "Element guid %d doesn't exist" % guid
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
if not factory.box_attributes.has_attribute(name):
- raise AttributeError, "Invalid attribute %s for element type %s" % (name, factory_id)
- if self._status > TESTBED_STATUS_CREATED and \
- factory.box_attributes.is_attribute_design_only(name):
- raise AttributeError, "Attribute %s can only be queried during experiment design" % name
+ raise AttributeError, "Invalid attribute %s for element type %s" % \
+ (name, factory.factory_id)
+ if guid in self._set and name in self._set[guid]:
+ return self._set[guid][name]
+ if guid in self._create_set and name in self._create_set[guid]:
+ return self._create_set[guid][name]
return factory.box_attributes.get_attribute_value(name)
- #get: NotImplementedError
-
- def box_get_route(self, guid, index, attribute):
+ def get_route(self, guid, index, attribute):
"""
- Helper implementation for get_route, returns information
- given to defer_add_route.
+ returns information given to defer_add_route.
Raises AttributeError if an invalid attribute is requested
or if the indexed routing rule does not exist.
routes = self._add_route.get(guid)
if not routes:
raise KeyError, "GUID %r not found in %s" % (guid, self._testbed_id)
-
+
+ index = int(index)
if not (0 <= index < len(addresses)):
raise AttributeError, "GUID %r at %s does not have a routing entry #%s" % (
guid, self._testbed_id, index)
return routes[index][attribute_index]
- def box_get_address(self, guid, index, attribute='Address'):
+ def get_address(self, guid, index, attribute='Address'):
"""
- Helper implementation for get_address, returns information
- given to defer_add_address
+ returns information given to defer_add_address
Raises AttributeError if an invalid attribute is requested
or if the indexed routing rule does not exist.
if not addresses:
raise KeyError, "GUID %r not found in %s" % (guid, self._testbed_id)
+ index = int(index)
if not (0 <= index < len(addresses)):
raise AttributeError, "GUID %r at %s does not have an address #%s" % (
guid, self._testbed_id, index)
return addresses[index][attribute_index]
def get_attribute_list(self, guid):
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
attribute_list = list()
return factory.box_attributes.attributes_list
def start(self, time = TIME_NOW):
+ # Plan everything
+ # - group by factory_id
+ # - enqueue task callables
+ plan = collections.defaultdict(list)
+
for guid, factory_id in self._create.iteritems():
factory = self._factories[factory_id]
start_function = factory.start_function
if start_function:
- start_function(self, guid)
+ plan[factory_id].append((start_function, guid))
+
+ # Execute plan, following the factory_id order
+ for factory_id in self._metadata.start_order:
+ if factory_id in plan:
+ for start_function, guid in plan[factory_id]:
+ start_function(self, guid)
+
self._status = TESTBED_STATUS_STARTED
#action: NotImplementedError
stop_function(self, guid)
self._status = TESTBED_STATUS_STOPPED
- def status(self, guid):
+ def status(self, guid = None):
+ if not guid:
+ return self._status
if not guid in self._create:
raise RuntimeError("Element guid %d doesn't exist" % guid)
- factory_id = self._create[guid]
- factory = self._factories[factory_id]
+ factory = self._get_factory(guid)
status_function = factory.status_function
if status_function:
return status_function(self, guid)
return dict() if guid not in self._create_set else \
self._create_set[guid]
+ def _get_factory(self, guid):
+ factory_id = self._create[guid]
+ return self._factories[factory_id]
+