Added routes to OMF nodes
[nepi.git] / src / nepi / util / parser / base.py
index feef6ab..eeaf594 100644 (file)
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
 import sys
@@ -6,6 +5,13 @@ import sys
 class ExperimentData(object):
     def __init__(self):
         self.data = dict()
+    
+    def __repr__(self):
+        return "%s(%r)" % (self.__class__, self.data)
+    
+    def __str__(self):
+        from pprint import pformat
+        return "%s:%s" % (self.__class__, pformat(self.data))
 
     @property
     def guids(self):
@@ -23,6 +29,16 @@ class ExperimentData(object):
         box_data["factory_id"] = factory_id
         self.data[guid] = box_data
 
+    def add_graphical_info_data(self, guid, x, y, width, height):
+        data = self.data[guid]
+        if not "graphical_info" in data:
+            data["graphical_info"] = dict()
+        graphical_info_data = data["graphical_info"]
+        graphical_info_data["x"] = x
+        graphical_info_data["y"] = y
+        graphical_info_data["width"] = width
+        graphical_info_data["height"] = height
+
     def add_factory_attribute_data(self, guid, name, value):
         data = self.data[guid]
         if not "factory_attributes" in data:
@@ -55,37 +71,31 @@ class ExperimentData(object):
         connection_data = connections_data[connector_type_name]
         connection_data[other_guid] = other_connector_type_name
 
-    def add_address_data(self, guid, autoconf, address, family, netprefix, 
+    def add_address_data(self, guid, address, netprefix, 
             broadcast):
         data = self.data[guid]
         if not "addresses" in data:
             data["addresses"] = list()
         addresses_data = data["addresses"]
         address_data = dict()
-        if autoconf:
-            address_data["AutoConfigure"] = autoconf
         if address:
             address_data["Address"] = address
-        if family:
-            address_data["Family"] = family
-        if netprefix:
-            address_data["NetPrefix"] = netprefix
+        address_data["NetPrefix"] = netprefix
         if broadcast:
             address_data["Broadcast"] = broadcast
         addresses_data.append(address_data)
 
-    def add_route_data(self, guid, family, destination, netprefix, nexthop, 
-            interface):
+    def add_route_data(self, guid, destination, netprefix, nexthop, metric, device):
         data = self.data[guid]
         if not "routes" in data:
             data["routes"] = list()
         routes_data = data["routes"]
         route_data = dict({
-            "Family": family, 
             "Destination": destination,
             "NetPrefix": netprefix, 
             "NextHop": nexthop, 
-            "Interface": Interface
+            "Metric": metric,
+            "Device": device
             })
         routes_data.append(route_data)
 
@@ -100,6 +110,16 @@ class ExperimentData(object):
         box_data = self.data[guid]
         return (box_data["testbed_guid"], box_data["factory_id"])
 
+    def get_graphical_info_data(self, guid):
+        data = self.data[guid]
+        if not "graphical_info" in data:
+            return (0, 0, 0, 0, "") 
+        graphical_info_data = data["graphical_info"]
+        return (graphical_info_data["x"],
+                graphical_info_data["y"],
+                graphical_info_data["width"],
+                graphical_info_data["height"])
+
     def get_factory_attribute_data(self, guid):
         data = self.data[guid]
         if not "factory_attributes" in data:
@@ -108,19 +128,32 @@ class ExperimentData(object):
         return [(name, value) for name, value \
                 in factory_attributes_data.iteritems()]
 
-    def get_attribute_data(self, guid):
+    def get_attribute_data(self, guid, attribute=None, default=None):
         data = self.data[guid]
         if not "attributes" in data:
-            return []
+            if attribute is None:
+                return []
+            else:
+                return None
         attributes_data = data["attributes"]
-        return [(name, value) for name, value \
-                in attributes_data.iteritems()]
+        if attribute is None:
+            return [(name, value) for name, value \
+                    in attributes_data.iteritems()]
+        else:
+            return attributes_data.get(attribute, default)
+
+    def set_attribute_data(self, guid, attribute, value):
+        data = self.data[guid]
+        if not "attributes" in data:
+            raise KeyError, "No attributes in reference OBJECT %r" % (guid,)
+        attributes_data = data["attributes"]
+        attributes_data[attribute] = value
 
     def get_trace_data(self, guid):
         data = self.data[guid]
         if not "traces" in data:
             return []
-        return [trace_name for trace_name in data["traces"]]
+        return data["traces"]
 
     def get_connection_data(self, guid):
         data = self.data[guid]
@@ -138,9 +171,7 @@ class ExperimentData(object):
         if not "addresses" in data:
             return []
         addresses_data = data["addresses"]
-        return [(data["AutoConfigure"] if "AutoConfigure" in data else None,
-                 data["Address"] if "Address" in data else None,
-                 data["Family"] if "Family" in data else None,
+        return [(data["Address"] if "Address" in data else None,
                  data["NetPrefix"] if "NetPrefix" in data else None,
                  data["Broadcast"] if "Broadcast" in data else None) \
                  for data in addresses_data]
@@ -150,12 +181,12 @@ class ExperimentData(object):
         if not "routes" in data:
             return []
         routes_data = data["routes"]
-        return [(data["Family"],
-                 data["Destination"],
+        return [(data["Destination"],
                  data["NetPrefix"],
                  data["NextHop"],
-                 data["Interface"]) \
-                 for data in routes_data]
+                 data["Metric"],
+                 data["Device"]) \
+                         for data in routes_data]
 
 class ExperimentParser(object):
     def to_data(self, experiment_description):
@@ -165,27 +196,35 @@ class ExperimentParser(object):
             testbed_id = testbed_description.provider.testbed_id
             testbed_version = testbed_description.provider.testbed_version
             data.add_testbed_data(guid, testbed_id, testbed_version)
+            self.graphical_info_to_data(data, guid, 
+                    testbed_description.graphical_info)
             self.attributes_to_data(data, guid, testbed_description.attributes)
             for box in testbed_description.boxes:
                 data.add_box_data(box.guid, guid, box.factory_id)
+                self.graphical_info_to_data(data, box.guid, box.graphical_info)
                 self.factory_attributes_to_data(data, box.guid, 
                         box.factory_attributes)
                 self.attributes_to_data(data, box.guid, box.attributes)
                 self.traces_to_data(data, box.guid, box.traces)
                 self.connections_to_data(data, box.guid, box.connectors)
-                self.addresses_to_data(data, box.guid, box.addresses)
-                self.routes_to_data(data, box.guid, box.routes)
+                if hasattr(box, "addresses"):
+                    self.addresses_to_data(data, box.guid, box.addresses)
+                if hasattr(box, "routes"):
+                    self.routes_to_data(data, box.guid, box.routes)
         return data
 
-    def factory_attributes_to_data(self, data, guid, attributes):
-        for attribute in attributes:
-            if attribute.modified:
-                data.add_factory_attribute_data(guid, attribute.name, 
-                        attribute.value)
+    def graphical_info_to_data(self, data, guid, g_info):
+        data.add_graphical_info_data(guid, g_info.x, g_info.y, g_info.width, 
+                g_info.height)
+
+    def factory_attributes_to_data(self, data, guid, factory_attributes):
+        factory_attributes = factory_attributes or dict()
+        for name, value in factory_attributes.iteritems():
+            data.add_factory_attribute_data(guid, name, value)
 
     def attributes_to_data(self, data, guid, attributes):
         for attribute in attributes:
-            if attribute.modified:
+            if attribute.modified or attribute.has_no_default_value:
                 data.add_attribute_data(guid, attribute.name, attribute.value)
 
     def traces_to_data(self, data, guid, traces):
@@ -204,33 +243,26 @@ class ExperimentParser(object):
 
     def addresses_to_data(self, data, guid, addresses):
         for addr in addresses:
-             autoconf = addr.get_attribute_value("AutoConfigure") \
-                    if addr.is_attribute_modified("AutoConfigure") else None
-             address = addr.get_attribute_value("Address") \
-                    if addr.is_attribute_modified("Address") else None
-             netprefix = addr.get_attribute_value("NetPrefix") \
-                    if addr.is_attribute_modified("NetPrefix") else None
-             family = addr.get_attribute_value("Family") \
-                    if addr.is_attribute_modified("Family") else None
+             address = addr.get_attribute_value("Address")
+             netprefix = addr.get_attribute_value("NetPrefix")
              broadcast = addr.get_attribute_value("Broadcast") \
                     if addr.has_attribute("Broadcast") and \
-                     addr.is_attribute_modified("Broadcast") else None
-             data.add_address_data(guid, autoconf, address, family, netprefix, 
-                    broadcast)
+                    addr.is_attribute_modified("Broadcast") else None
+             data.add_address_data(guid, address, netprefix, broadcast)
 
     def routes_to_data(self, data, guid, routes):
         for route in routes:
-             family = route.get_attribute_value("Family")
              destination = route.get_attribute_value("Destination")
              netprefix = route.get_attribute_value("NetPrefix")
              nexthop = route.get_attribute_value("NextHop")
-             interface = route.get_attribute_value("Interface")
-             data.add_route_data(guid, family, destination, netprefix, nexthop, 
-                    interface)
+             metric = route.get_attribute_value("Metric")
+             device = route.get_attribute_value("Device")
+             data.add_route_data(guid, destination, netprefix, nexthop, 
+                     metric, device)
 
     def from_data(self, experiment_description, data):
         box_guids = list()
-        for guid in data.guids:
+        for guid in sorted(data.guids):
             if data.is_testbed_data(guid):
                 self.testbed_from_data(experiment_description, guid, data)
             else:
@@ -239,14 +271,15 @@ class ExperimentParser(object):
         self.connections_from_data(experiment_description, box_guids, data)
 
     def testbed_from_data(self, experiment_description, guid, data):
+        from nepi.core.design import FactoriesProvider
         (testbed_id, testbed_version) = data.get_testbed_data(guid)
-        mod_name = 'nepi.testbeds.%s' % testbed_id
-        if not mod_name in sys.modules:
-            __import__(mod_name)
-        testbed_mod = sys.modules[mod_name]
-        provider = testbed_mod.TestbedFactoriesProvider(testbed_version)
-        experiment_description.add_testbed_description(provider)
+        provider = FactoriesProvider(testbed_id)
+        if provider.testbed_version != testbed_version:
+            raise RuntimeError("Bad testbed version on testbed %s. Asked for %s, got %s" % \
+                    (testbed_id, testbed_version, provider.testbed_version))
+        experiment_description.add_testbed_description(provider, guid)
         testbed_description = experiment_description.testbed_description(guid)
+        self.graphical_info_from_data(testbed_description, data)
         self.attributes_from_data(testbed_description, data)
 
     def box_from_data(self, experiment_description, guid, data):
@@ -255,12 +288,22 @@ class ExperimentParser(object):
                 testbed_guid)
         self.factory_attributes_from_data(testbed_description, factory_id,
                 guid, data)
-        box = testbed_description.create(factory_id)
+        box = testbed_description.create(factory_id, guid)
+
+        self.graphical_info_from_data(box, data)
         self.attributes_from_data(box, data)
         self.traces_from_data(box, data)
         self.addresses_from_data(box, data)
         self.routes_from_data(box, data)
 
+    def graphical_info_from_data(self, element, data):
+        (x, y, width, height) =  data.get_graphical_info_data(
+                element.guid)
+        element.graphical_info.x = x
+        element.graphical_info.y = y
+        element.graphical_info.width = width
+        element.graphical_info.height = height
+
     def factory_attributes_from_data(self, testbed_description, factory_id, 
             guid, data):
         factory = testbed_description.provider.factory(factory_id)
@@ -273,31 +316,27 @@ class ExperimentParser(object):
 
     def traces_from_data(self, box, data):
         for name in data.get_trace_data(box.guid):
-            box.trace(name).enable()
+            box.enable_trace(name)
 
     def addresses_from_data(self, box, data):
-        for (autoconf, address, family, netprefix, broadcast) \
-                in data.get_address_data(box.guid):
+        for (address, netprefix, broadcast) in data.get_address_data(box.guid):
             addr = box.add_address()
-            if autoconf:
-                addr.set_attribute_value("AutoConfigure", autoconf)
             if address:
                 addr.set_attribute_value("Address", address)
-            if family:
-                addr.set_attribute_value("Family", family)
-            if netprefix:
+            if netprefix != None:
                 addr.set_attribute_value("NetPrefix", netprefix)
             if broadcast:
                 addr.set_attribute_value("Broadcast", broadcast)
 
     def routes_from_data(self, box, data):
-         for (family, destination, netprefix, nexthop, interface) \
-                in data.get_route_data(box.guid):
-            addr = box.add_route(family)
+         for (destination, netprefix, nexthop, metric, device) \
+                 in data.get_route_data(box.guid):
+            addr = box.add_route()
             addr.set_attribute_value("Destination", destination)
             addr.set_attribute_value("NetPrefix", netprefix)
             addr.set_attribute_value("NextHop", nexthop)
-            addr.set_attribute_value("Interface", interface)
+            addr.set_attribute_value("Metric", metric)
+            addr.set_attribute_value("Device", device)
 
     def connections_from_data(self, experiment_description, guids, data):
         for guid in guids:
@@ -311,4 +350,3 @@ class ExperimentParser(object):
                     if not connector.is_connected(other_connector):
                         connector.connect(other_connector)
 
-