X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fcore%2Ftestbed_impl.py;h=fc8cf060ba8b630c94888e2c17969300ae725327;hb=af6e0d8cceaabe492b9901405ce0610d72fd35cf;hp=1472cca505610dea674e7d17bed91bba7ae9749f;hpb=657ddfbe6bc3bafb2a03ea8d8bfdd3abfe67fdf3;p=nepi.git diff --git a/src/nepi/core/testbed_impl.py b/src/nepi/core/testbed_impl.py index 1472cca5..fc8cf060 100644 --- a/src/nepi/core/testbed_impl.py +++ b/src/nepi/core/testbed_impl.py @@ -6,9 +6,9 @@ from nepi.core.metadata import Metadata 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 @@ -45,23 +45,23 @@ class TestbedInstance(execute.TestbedInstance): 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 Netns version %s" % + raise RuntimeError("Invalid element type %s for testbed version %s" % (factory_id, self._testbed_version)) if guid in self._create: raise RuntimeError("Cannot add elements with the same guid: %d" % 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] @@ -74,7 +74,7 @@ class TestbedInstance(execute.TestbedInstance): 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] @@ -87,7 +87,7 @@ class TestbedInstance(execute.TestbedInstance): 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] @@ -109,7 +109,7 @@ class TestbedInstance(execute.TestbedInstance): 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) @@ -125,7 +125,7 @@ class TestbedInstance(execute.TestbedInstance): (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] @@ -137,7 +137,7 @@ class TestbedInstance(execute.TestbedInstance): self._add_trace[guid] = list() self._add_trace[guid].append(trace_id) - def add_adddress(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] @@ -145,17 +145,17 @@ class TestbedInstance(execute.TestbedInstance): 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] @@ -167,8 +167,7 @@ class TestbedInstance(execute.TestbedInstance): 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() @@ -178,18 +177,14 @@ class TestbedInstance(execute.TestbedInstance): 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]: - parameters = dict() if guid not in self._create_set else \ - self._create_set[guid] - factory_parameters = dict() if guid not in \ - self._factory_set else self._create_set[guid] - factory.create_function(self, guid, parameters, - factory_parameters) + factory.create_function(self, guid) + parameters = self._get_parameters(guid) for name, value in parameters.iteritems(): self.set(TIME_NOW, guid, name, value) @@ -210,10 +205,25 @@ class TestbedInstance(execute.TestbedInstance): self._testbed_id, factory_id2, connector_type_name2) if code_to_connect: - code_to_connect(element1, element2) + 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(): @@ -248,46 +258,128 @@ class TestbedInstance(execute.TestbedInstance): 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 = [] if guid not in self._add_trace else \ - self._add_trace[guid] - parameters = dict() if guid not in self._create_set else \ - self._create_set[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 = [] if guid not in self._add_trace else \ - self._add_trace[guid] - stop_function(self, guid, traces) + stop_function(self, guid) def status(self, guid): - for guid, factory_id in self._create.iteritems(): - factory = self._factories[factory_id] - status_function = factory.status_function - if status_function: - return status_function(self, guid) + 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] + status_function = factory.status_function + if status_function: + 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): @@ -317,3 +409,10 @@ class TestbedInstance(execute.TestbedInstance): cross_count = len(self._cross_connect[guid][connection_type_name]) return count + cross_count + def _get_traces(self, guid): + return [] if guid not in self._add_trace else self._add_trace[guid] + + def _get_parameters(self, guid): + return dict() if guid not in self._create_set else \ + self._create_set[guid] +