from nepi.util import validation
from nepi.util.constants import AF_INET, AF_INET6, STATUS_UNDETERMINED, TIME_NOW
-class TestbedInstance(execute.TestbedInstance):
+class TestbedController(execute.TestbedController):
def __init__(self, testbed_id, testbed_version):
- super(TestbedInstance, self).__init__(testbed_id, testbed_version)
+ super(TestbedController, self).__init__(testbed_id, testbed_version)
self._started = False
# testbed attributes for validation
self._attributes = None
def elements(self):
return self._elements
- def configure(self, name, value):
+ def defer_configure(self, name, value):
if not self._attributes.has_attribute(name):
raise RuntimeError("Invalid attribute %s for testbed" % name)
# Validation
self._attributes.set_attribute_value(name, value)
self._configure[name] = value
- def create(self, guid, factory_id):
+ def defer_create(self, guid, factory_id):
if factory_id not in self._factories:
raise RuntimeError("Invalid element type %s for testbed version %s" %
(factory_id, self._testbed_version))
guid)
self._create[guid] = factory_id
- def create_set(self, guid, name, value):
+ 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]
self._create_set[guid] = dict()
self._create_set[guid][name] = value
- def factory_set(self, guid, name, value):
+ 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]
self._factory_set[guid] = dict()
self._factory_set[guid][name] = value
- def connect(self, guid1, connector_type_name1, guid2,
+ def defer_connect(self, guid1, connector_type_name1, guid2,
connector_type_name2):
factory_id1 = self._create[guid1]
factory_id2 = self._create[guid2]
self._connect[guid2][connector_type_name2][guid1] = \
connector_type_name1
- def cross_connect(self, guid, connector_type_name, cross_guid,
+ 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]
count = self._get_connection_count(guid, connector_type_name)
(cross_guid, cross_testbed_id, cross_factory_id,
cross_connector_type_name)
- def add_trace(self, guid, trace_id):
+ 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]
self._add_trace[guid] = list()
self._add_trace[guid].append(trace_id)
- def add_address(self, guid, family, address, netprefix, broadcast):
+ 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]
if not factory.allow_addresses:
raise RuntimeError("Element type '%s' doesn't support addresses" %
factory_id)
- max_addresses = factory.get_attribute_value("MaxAddresses")
+ 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, family_id))
+ more addresses" % (guid, factory_id))
else:
self._add_address[guid] = list()
- self._add_address[guid].append((family, address, netprefix, broadcast))
+ self._add_address[guid].append((address, netprefix, broadcast))
- def add_route(self, guid, destination, netprefix, nexthop):
+ 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]
self._add_route[guid] = list()
self._add_route[guid].append((destination, netprefix, nexthop))
- def do_setup(self):
- raise NotImplementedError
+ #do_setup(self): NotImplementedError
def do_create(self):
guids = dict()
guids[factory_id] = list()
guids[factory_id].append(guid)
# create elements following the factory_id order
- for factory_id in self._metadata.factories_order:
+ for factory_id in self._metadata.create_order:
# omit the factories that have no element to create
if factory_id not in guids:
continue
factory = self._factories[factory_id]
for guid in guids[factory_id]:
+ factory.create_function(self, guid)
parameters = self._get_parameters(guid)
- factory_parameters = dict() if guid not in \
- self._factory_set else self._factory_set[guid]
- factory.create_function(self, guid, parameters,
- factory_parameters)
for name, value in parameters.iteritems():
self.set(TIME_NOW, guid, name, value)
code_to_connect(self, element1, element2)
def do_configure(self):
- raise NotImplementedError
+ guids = dict()
+ # order guids (elements) according to factory_id
+ for guid, factory_id in self._create.iteritems():
+ if not factory_id in guids:
+ guids[factory_id] = list()
+ guids[factory_id].append(guid)
+ # configure elements following the factory_id order
+ for factory_id in self._metadata.configure_order:
+ # omit the factories that have no element to create
+ if factory_id not in guids:
+ continue
+ factory = self._factories[factory_id]
+ if not factory.configure_function:
+ continue
+ for guid in guids[factory_id]:
+ factory.configure_function(self, guid)
def do_cross_connect(self):
for guid, cross_connections in self._cross_connect.iteritems():
self._set[guid][time] = dict()
self._set[guid][time][name] = value
- def get(self, time, guid, name):
- raise NotImplementedError
+ def box_get(self, time, guid, name):
+ """
+ Helper for subclasses, 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]
+ if not factory.box_attributes.has_attribute(name):
+ raise AttributeError, "Invalid attribute %s for element type %s" % (name, factory_id)
+ if self._started and factory.is_attribute_design_only(name):
+ raise AttributeError, "Attribute %s can only be queried during experiment design" % name
+ return factory.box_attributes.get_attribute_value(name)
+
+ #get: NotImplementedError
+
+ def box_get_route(self, guid, index, attribute):
+ """
+ Helper implementation for get_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.
+
+ Raises KeyError if the GUID has not been seen by
+ defer_add_route
+ """
+ ATTRIBUTES = ['Destination', 'NetPrefix', 'NextHop']
+
+ if attribute not in ATTRIBUTES:
+ raise AttributeError, "Attribute %r invalid for addresses of %r" % (attribute, guid)
+
+ attribute_index = ATTRIBUTES.index(attribute)
+
+ routes = self._add_route.get(guid)
+ if not routes:
+ raise KeyError, "GUID %r not found in %s" % (guid, self._testbed_id)
+
+ 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'):
+ """
+ Helper implementation for get_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.
+
+ Raises KeyError if the GUID has not been seen by
+ defer_add_address
+ """
+ ATTRIBUTES = ['Address', 'NetPrefix', 'Broadcast']
+
+ if attribute not in ATTRIBUTES:
+ raise AttributeError, "Attribute %r invalid for addresses of %r" % (attribute, guid)
+
+ attribute_index = ATTRIBUTES.index(attribute)
+
+ addresses = self._add_address.get(guid)
+ if not addresses:
+ raise KeyError, "GUID %r not found in %s" % (guid, self._testbed_id)
+
+ 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 start(self, time = TIME_NOW):
for guid, factory_id in self._create.iteritems():
factory = self._factories[factory_id]
start_function = factory.start_function
if start_function:
- traces = self._traces(guid)
- parameters = self._parameters(guid)
- start_function(self, guid, parameters, traces)
+ start_function(self, guid)
self._started = True
- def action(self, time, guid, action):
- raise NotImplementedError
+ #action: NotImplementedError
def stop(self, time = TIME_NOW):
for guid, factory_id in self._create.iteritems():
factory = self._factories[factory_id]
stop_function = factory.stop_function
if stop_function:
- traces = self._traces(guid)
- parameters = self._parameters(guid)
- stop_function(self, guid, parameters, traces)
+ stop_function(self, guid)
def status(self, guid):
if not guid in self._create:
factory = self._factories[factory_id]
status_function = factory.status_function
if status_function:
- return status_function(self, guid, parameters, traces)
+ return status_function(self, guid)
return STATUS_UNDETERMINED
- def trace(self, guid, trace_id):
+ def trace(self, guid, trace_id, attribute='value'):
+ if attribute == 'value':
+ fd = open("%s" % self.trace_filename(guid, trace_id), "r")
+ content = fd.read()
+ fd.close()
+ elif attribute == 'path':
+ content = self.trace_filename(guid, trace_id)
+ else:
+ content = None
+ return content
+
+ def trace_filename(self, guid, trace_id):
+ """
+ Return a trace's file path, for TestbedController's default
+ implementation of trace()
+ """
raise NotImplementedError
- def shutdown(self):
- raise NotImplementedError
+ #shutdown: NotImplementedError
def get_connected(self, guid, connector_type_name,
other_connector_type_name):