description classes are generic classes with no testbed specific code.
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 8 Feb 2011 17:28:21 +0000 (18:28 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Tue, 8 Feb 2011 17:28:21 +0000 (18:28 +0100)
12 files changed:
examples/design1.py [new file with mode: 0644]
src/nepi/__init__.py [new file with mode: 0644]
src/nepi/core/__init__.py [new file with mode: 0644]
src/nepi/core/attributes.py
src/nepi/core/description.py [new file with mode: 0644]
src/nepi/core/experiment.py
src/nepi/core/protocol.py
src/nepi/core/testbed.py
src/nepi/testbeds/__init__.py [new file with mode: 0644]
src/nepi/testbeds/netns/__init__.py [new file with mode: 0644]
src/nepi/utils/__init__.py [new file with mode: 0644]
src/nepi/utils/guid_generator.py [new file with mode: 0644]

diff --git a/examples/design1.py b/examples/design1.py
new file mode 100644 (file)
index 0000000..7a9cca3
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from nepi.core.experiment import ExperimentDescription
+
+testbed_id = "netns"
+testbed_version = "0.1"
+experiment = ExperimentDescription()
+netns = experiment.add_testbed_description(testbed_id, testbed_version)
+node1 = netns.create("Node")
+node2 = netns.create("Node")
+iface1 = netns.create("NodeInterface")
+iface1.set_attribute_value("up", True)
+node1.connector("devs").connect(iface1.connector("node"))
+ip1 = iface1.add_address()
+p1.set_attribute_value("Address", "10.0.0.1")
+iface2 = netns.create("NodeInterface")
+iface2.set_attribute_value("up", True)
+node2.connector("devs").connect(iface2.connector("node"))
+ip2 = iface2.add_address()
+ip2.set_attribute_value("Address", "10.0.0.2")
+switch = netns.create("Switch")
+switch.set_attribute_value("up", True)
+iface1.connector("switch").connect(switch.connector("devs"))
+iface2.connector("switch").connect(switch.connector("devs"))
+app = netns.create("Application")
+app.set_attribute_value("command", "ping -qc10 10.0.0.2")
+app.connector("node").connect(node1.connector("apps"))
+
+print experiment.xml_description
+
+description = """
+<experiment>
+  <testbeds>
+    <testbed testbed_id="netns" testbed_version="1.0" guid="1">
+      <elements>
+        <element factory_id="Node" guid="2">
+          <construct-parameters>
+          </construct-parameters>
+          <attributes>
+          </attributes>
+          <traces>
+          </traces>
+          <addresses>
+          </addresses>
+          <routes>
+          </routes>
+        </element>
+      </elements>
+      <connections>
+      </connections>
+    </testbed>
+  </testbeds>
+</experiment>
+"""
+
diff --git a/src/nepi/__init__.py b/src/nepi/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/nepi/core/__init__.py b/src/nepi/core/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
index 4832cab..2db9f0c 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# vim:ts=4:sw=4:et:ai:sts=4
 
 class AttributesMap(object):
     """AttributesMap is the base class for every object whose attributes 
@@ -13,14 +12,8 @@ class AttributesMap(object):
     def attributes_name(self):
         return set(self._attributes.keys())
 
-    def is_valid_attribute_value(self, name, value):
-        raise NotImplementedError
-
     def set_attribute_value(self, name, value):
-        if self.is_valid_attribute_value(name, value):
-            self._attributes[name].value = value
-            return True
-        return False
+        self._attributes[name].value = value
 
     def set_attribute_readonly(self, name, value):
         self._attributes[name].readonly = value
@@ -44,10 +37,11 @@ class AttributesMap(object):
         return self._attributes[name].readonly
 
     def add_attribute(self, name, help, type, value = None, range = None,
-        allowed = None, readonly = False):
+        allowed = None, readonly = False, validation_function = None):
         if name in self._attributes:
             raise AttributeError('Attribute %s already exists' % name))
-        attribute = Attribute(name, help, type, value, range, allowed, readonly)
+        attribute = Attribute(name, help, type, value, range, allowed, readonly,
+                validation_function)
         self._attributes[name] = attribute
 
     def del_attribute(self, name):
@@ -66,13 +60,14 @@ class Attribute(object):
     types = [STRING, BOOL, ENUM, DOUBLE, INTEGER, ENDPOINT, TIME]
 
     def __init__(self, name, help, type, value = None, range = None,
-        allowed = None, readonly = False):
+        allowed = None, readonly = False, validation_function = None):
         if not type in Attribute.types:
             raise AttributeError("invalid type %s " % type)
         self.name = name
-        self.value = value
         self.type = type
         self.help = help
+        self._value = value
+        self._validation_function = validation_function
         self.readonly = (readonly == True)
         self.modified = False
         # range: max and min possible values
@@ -80,3 +75,16 @@ class Attribute(object):
         # list of possible values
         self.allowed = allowed
 
+    def get_value(self):
+        return self._value
+
+    def set_value(self, value):
+        func = self._validation_function
+        if not func or func(value):
+            self._value = value
+        else:
+            raise RuntimeError("Invalid value %s for attribute %s" %
+                    (str(value), self.name))
+
+    value = property(get_value, set_value)
+
diff --git a/src/nepi/core/description.py b/src/nepi/core/description.py
new file mode 100644 (file)
index 0000000..d3837d0
--- /dev/null
@@ -0,0 +1,293 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from nepi.core.attributes import AttributesMap
+
+class ConnectorType(object):
+    """A ConnectorType defines a kind of connector that can be used in an Object.
+    """
+    def __init__(self, connector_type_id, help, name, max = -1, min = 0):
+        super(ConnectorType, self).__init__()
+        """
+        ConnectorType(name, help, display_name, max, min):
+        - connector_type_id: (unique) identifier for this type. 
+            Typically: testbed_id + factory_id + name
+        - name: descriptive name for the user
+        - help: help text
+        - max: amount of connections that this type support, -1 for no limit
+        - min: minimum amount of connections to this type of connector
+        """
+        if max == -1:
+            max = sys.maxint
+        elif max <= 0:
+                raise RuntimeError(
+             'The maximum number of connections allowed need to be more than 0')
+        if min < 0:
+            raise RuntimeError(
+             'The minimum number of connections allowed needs to be at least 0')
+        self._connector_type_id = connector_type_id
+        self._help = help
+        self._name = name
+        self._max = max
+        self._min = min
+        self._allowed_connections = list()
+
+    @property
+    def connector_type_id(self):
+        return self._connector_type_id
+
+    @property
+    def help(self):
+        return self._help
+
+    @property
+    def name(self):
+        return self._name
+
+    @property
+    def max(self):
+        return self._max
+
+    @property
+    def min(self):
+        return self._min
+
+    def add_allowed_connection(self, connector_type_id):
+        self._allowed_connections.append(connector_type_id)
+
+    def can_connect(self, connector_type_id):
+        return connector_type_id in self._allowed_connections
+
+class Connector(object):
+    """A Connector sepcifies the connection points in an Object"""
+    def __init__(self, element, connector_type):
+        super(Connector, self).__init__()
+        self._element = element
+        self._connector_type = connector_type
+        self._connections = dict()
+
+    @property
+    def element(self):
+        return self._element
+
+    @property
+    def connector_type(self):
+        return self._connector_type
+
+    @property
+    def connections(self):
+        return self._connections.values()
+
+    def is_full(self):
+        """Return True if the connector has the maximum number of connections"""
+        return len(self.connections) == self.connector_type.max
+
+    def is_complete(self):
+        """Return True if the connector has the minimum number of connections"""
+        return len(self.connections) >= self.connector_type.min 
+
+    def connect(self, connector):
+        if self.is_full() or connector.is_full():
+            raise RuntimeError("Connector is full")    
+        if not self.can_connect(connector) or not connector.can_connect(self):
+            raise RuntimeError("Could not connect.")
+        self._connections[connector._key] = connector
+        connector._connections[self._key] = self
+
+    def disconnect(self, connector):
+        if connector._key not in self._connections or 
+            self._key not in connector._connections:
+                raise RuntimeError("Could not disconnect.")
+        del self._connections[connector._key]
+        del connector._connections[self._key]
+
+    def can_connect(self, connector):
+        connector_type_id = connector.connector_type.connector_type_id
+        self.connector_type.can_connect(connector_type_id) 
+
+    def destroy(self):
+        for connector in self._connections:
+            self.disconnect(connector)
+        self._element = self._connectors = None
+
+    @property
+    def _key(self):
+        return "%d_%s" % (self.element.guid, 
+                self.connector_type.connector_type_id)
+
+class Trace(AttributesMap):
+    def __init__(self, name, help, enabled=False):
+        super(Trace, self).__init__()
+        self._name = name
+        self._help = help       
+        self._enabled = enabled
+    
+    @property
+    def name(self):
+        return self._name
+
+    @property
+    def help(self):
+        return self._help
+
+    @property
+    def is_enabled(self):
+        return self._enabled
+
+    def enable(self):
+        self._enabled = True
+
+    def disable(self):
+        self._enabled = False
+
+class Element(AttributesMap):
+    def __init__(self, guid, testbed_id, factory, container = None):
+        super(Element, self).__init__()
+        # general unique id
+        self._guid = guid
+        # factory identifier or name
+        self._factory_id = factory.factory_id
+        # elements can be nested inside other 'container' elements
+        self._container = container
+        # traces for the element
+        self._traces = dict()
+        # connectors for the element
+        self._connectors = dict()
+        for connector_type in factory.connector_types:
+            connector = Connector(self, connector_type)
+            self._connectors[connector_type.connector_id] = connector
+
+    @property
+    def guid(self):
+        return self._guid
+
+    @property
+    def factory_id(self):
+        return self._factory_id
+
+    @property
+    def container(self):
+        return self._container
+
+    @property
+    def connectors(self):
+        return self._connectors.values()
+
+    @property
+    def traces(self):
+        return self._traces.values()
+
+    def connector(self, name):
+        return self._connectors[name]
+
+    def trace(self, name):
+        return self._traces[name]
+
+    def destroy(self):
+        super(Element, self).destroy()
+        for c in self.connectors:
+            c.destroy()         
+        for t in self.traces:
+            t.destroy()
+        self._connectors = self._traces = None
+
+class Factory(AttributesMap):
+    def __init__(self, factory_id, help = None, category = None):
+        super(Factory, self).__init__()
+        self._factory_id = factory_id
+        self._help = help
+        self._category = category
+        self._connector_types = set()
+
+    @property
+    def factory_id(self):
+        return self._factory_id
+
+    @property
+    def help(self):
+        return self._help
+
+    @property
+    def category(self):
+        return self._category
+
+    @property
+    def connector_types(self):
+        return self._connector_types
+
+    def add_connector_type(self, connector_id, help, name, max = -1, min = 0):
+        connector_type = ConnectorType(connector_id, help, name, max, min)            
+        self._connector_types.add(connector_type)
+
+    def create(self, guid, testbed_design, container = None):
+        raise NotImplementedError
+
+    def destroy(self):
+        super(Factory, self).destroy()
+        self._connector_types = None
+
+#TODO: Provide some way to identify that the providers and the factories
+# belong to a specific testbed version
+class Provider(object):
+    def __init__(self):
+        super(Provider, self).__init__()
+        self._factories = dict()
+
+    def factory(self, factory_id):
+        return self._factories[factory_id]
+
+    def add_factory(self, factory):
+        self._factories[factory.factory_id] = factory
+
+    def remove_factory(self, factory_id):
+        del self._factories[factory_id]
+
+    def list_factories(self):
+        return self._factories.keys()
+
+class TestbedDescription(AttributeMap):
+    def __init__(self, guid_generator, testbed_id, testbed_version, provider):
+        super(TestbedDescription, self).__init__()
+        self._guid_generator = guid_generator
+        self._guid = guid_generator.next()
+        self._testbed_id = testbed_id
+        self._testbed_version = testbed_version
+        self._provider = provider
+        self._elements = dict()
+
+    @property
+    def guid(self):
+        return self._guid
+
+    @property
+    def testbed_id(self):
+        return self._testbed_id
+
+    @property
+    def testbed_version(self):
+        return self._testbed_version
+
+    @property
+    def provider(self):
+        return provider
+
+    @property
+    def elements(self):
+        return self._elements.values()
+
+    def create(self, factory_id):
+        guid = self.guid_generator.next()
+        factory = self._provider.factories(factory_id)
+        element = factory.create(guid, self)
+        self._elements[guid] = element
+
+    def delete(self, guid):
+        element = self._elements[guid]
+        del self._elements[guid]
+        element.destroy()
+
+    def destroy(self):
+        for guid, element in self._elements.iteitems():
+            del self._elements[guid]
+            element.destroy()
+        self._elements = None
+
index e50c6fb..19825e4 100644 (file)
@@ -1,17 +1,44 @@
+#!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# vim:ts=4:sw=4:et:ai:sts=4
 
-class Experiment(object):
-    def __init__(self):
-        self._backends = dict()
+from nepi.utils.guid import GuidGenerator 
+import sys
 
-    def add_backend(self, backend):
-        self._backends[backend.guid] = backend
+class ExperimentDescription(object):
+    def __init__(self, guid = 0):
+        self._guid_generator = GuidGenerator(guid)
+        # testbed design instances
+        self._testbed_descriptions = dict()
+        self._testbed_providers = dict()
 
-    def remove_backend(self, backend):
-        del self._backends[backend.guid]
+    @property
+    def xml_description(self):
+        raise NotImplementedError
 
-    def instructions(self):
-        #TODO
-        pass
+    def add_testbed_description(self, testbed_id, testbed_version):
+        testbed_module = self._testbed_module(testbed_id)
+        testbed_provider = self._testbed_provider(testbed_id, testbed_version)
+        testbed_description = testbed_module.create_description_instance(
+                self._guid_generator, tesbed_id, testbed_version, 
+                testbed_provider)
+        guid = testbed_description.guid
+        self._testbed_descriptions[guid] = testbed_description
+
+    def remove_testbed_description(self, testbed_description):
+        guid = testbed_description.guid
+        del self._testbed_descriptions[guid]
+
+    def _testbed_module(self, testbed_id):
+        mod_name = 'nepi.testbeds.%s' % testbed_id
+        if not mod_name in sys.modules:
+            __import__(mod_name)
+        return sys.modules[mod_name]
+
+    def _testbed_provider(self, testbed_id, testbed_version):
+        key = "%s_%s" % (testbed_id, testbed_version)
+        if key not in self._testbed_providers:
+            testbed_module = self._testbed_module(testbed_id)
+            testbed_provider = testbed_module.create_provider(testbed_version)
+            self._testbed_providers[key] = testbed_provider
+        return self._testbed_providers[key]
 
index c650a32..5155920 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# vim:ts=4:sw=4:et:ai:sts=4
 
 # PROTOCOL MESSAGES
 CREATE      = 0
index 655f7e4..aaf7434 100644 (file)
@@ -1,290 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
-# vim:ts=4:sw=4:et:ai:sts=4
 from nepi.core.attributes import AttributesMap
 
-class ConnectorType(object):
-    """A ConnectorType defines a kind of connector that can be used in an Object.
-    """
-    def __init__(self, connector_id, help, name, max = -1, min = 0):
-        super(ConnectorType, self).__init__()
-        """
-        ConnectorType(name, help, display_name, max, min):
-        - connector_id: (unique) identifier for this type
-        - name: descriptive name for the user
-        - help: help text
-        - max: amount of connections that this type support, -1 for no limit
-        - min: minimum amount of connections to this type of connector
-        """
-        if max == -1:
-            max = sys.maxint
-        elif max <= 0:
-                raise RuntimeError(
-             'The maximum number of connections allowed need to be more than 0')
-        if min < 0:
-            raise RuntimeError(
-             'The minimum number of connections allowed needs to be at least 0')
-        self._connector_id = connector_id
-        self._help = help
-        self._name = name
-        self._max = max
-        self._min = min
-
-    @property
-    def connector_id(self):
-        return self._connector_id
-
-    @property
-    def help(self):
-        return self._help
-
-    @property
-    def name(self):
-        return self._name
-
-    @property
-    def max(self):
-        return self._max
-
-    @property
-    def min(self):
-        return self._min
-
-class Connector(object):
-    """A Connector sepcifies the connection points in an Object"""
-    def __init__(self, element, connector_type):
-        super(Connector, self).__init__()
-        self._element = element
-        self._connector_type = connector_type
-        self._connections = dict()
-
-    @property
-    def element(self):
-        return self._element
-
-    @property
-    def connector_type(self):
-        return self._connector_type
-
-    @property
-    def connections(self):
-        return self._connections.values()
-
-    def is_full(self):
-        """Return True if the connector has the maximum number of connections"""
-        return len(self.connections) == self.connector_type.max
-
-    def is_complete(self):
-        """Return True if the connector has the minimum number of connections"""
-        return len(self.connection) >= self.connector_type.min 
-
-    def connect(self, connector):
-        if self.is_full() or connector.is_full():
-            raise RuntimeError("Connector is full")    
-        if not self.can_connect(connector) or not connector.can_connect(self):
-            raise RuntimeError("Could not connect.")
-        self._connections[connector._key] = connector
-        connector._connections[self._key] = self
-
-    def disconnect(self, connector):
-        if connector._key not in self._connections or 
-            self._key not in connector._connections:
-                raise RuntimeError("Could not disconnect.")
-        del self._connections[connector._key]
-        del connector._connections[self._key]
-
-    def can_connect(self, connector):
-        raise NotImplementedError
-
-    def destroy(self):
-        for connector in self._connections:
-            self.disconnect(connector)
-        self._element = self._connectors = None
-
-    @property
-    def _key(self):
-        return "%d_%s" % (self.element.guid, self.connector_type.connector_id)
-
-class Trace(AttributesMap):
-    def __init__(self, name, help, enabled=False):
-        super(Trace, self).__init__()
-        self._name = name
-        self._help = help       
-        self._enabled = enabled
-    
-    @property
-    def name(self):
-        return self._name
-
-    @property
-    def help(self):
-        return self._help
-
-    @property
-    def is_enabled(self):
-        return self._enabled
-
-    def read_trace(self):
-        raise NotImplementedError
-
-    def enable(self):
-        self._enabled = True
-
-    def disable(self):
-        self._enabled = False
-
-class Element(AttributesMap):
-    def __init__(self, guid, testbed_id, factory, container = None):
-        super(Element, self).__init__()
-        # general unique id
-        self._guid = guid
-        # factory identifier or name
-        self._factory_id = factory.factory_id
-        # testbed identifier
-        self._tesbed_id = testbed_id
-        # elements can be nested inside other 'container' elements
-        self._container = container
-        # traces for the element
-        self._traces = dict()
-        # connectors for the element
-        self._connectors = dict()
-        for connector_type in factory.connector_types:
-            connector = Connector(self, connector_type)
-            self._connectors[connector_type.connector_id] = connector
-
-    @property
-    def guid(self):
-        return self._guid
-
-    @property
-    def factory_id(self):
-        return self._factory_id
-
-    @property
-    def testbed_id(self):
-        return self._testbed_id
-
-    @property
-    def container(self):
-        return self._container
-
-    @property
-    def connectors(self):
-        return self._connectors.values()
-
-    @property
-    def traces(self):
-        return self._traces.values()
-
-    def connector(self, name):
-        return self._connectors[name]
-
-    def trace(self, name):
-        return self._traces[name]
-
-    def destroy(self):
-        super(Element, self).destroy()
-        for c in self.connectors:
-            c.destroy()         
-        for t in self.traces:
-            t.destroy()
-        self._connectors = self._traces = None
-
-class Factory(AttributesMap):
-    def __init__(self, factory_id, help = None, category = None):
-        super(Factory, self).__init__()
-        self._factory_id = factory_id
-        self._help = help
-        self._category = category
-        self._connector_types = set()
-
-    @property
-    def factory_id(self):
-        return self._factory_id
-
-    @property
-    def help(self):
-        return self._help
-
-    @property
-    def category(self):
-        return self._category
-
-    @property
-    def connector_types(self):
-        return self._connector_types
-
-    def add_connector_type(self, connector_id, help, name, max = -1, min = 0):
-        connector_type = ConnectorType(connector_id, help, name, max, min)            
-        self._connector_types.add(connector_type)
-
-    def create(self, guid, testbed_design, container = None):
-        raise NotImplementedError
-
-    def destroy(self):
-        super(Factory, self).destroy()
-        self._connector_types = None
-
-#TODO: Provide some way to identify that the providers and the factories
-# belong to a specific testbed version
-class Provider(object):
-    def __init__(self):
-        super(Provider, self).__init__()
-        self._factories = dict()
-
-    def factory(self, factory_id):
-        return self._factories[factory_id]
-
-    def add_factory(self, factory):
-        self._factories[factory.factory_id] = factory
-
-    def remove_factory(self, factory_id):
-        del self._factories[factory_id]
-
-    def list_factories(self):
-        return self._factories.keys()
-
-class TestbedDesignInstance(AttributeMap):
-    def __init__(self, guid_generator, testbed_id, provider):
-        super(TestbedInstance, self).__init__()
-        self._guid_generator = guid_generator
-        self._guid = guid_generator.next()
-        self._testbed_id = testbed_id
-        self._provider = provider
-        self._elements = dict()
-
-    @property
-    def guid(self):
-        return self._guid
-
-    @property
-    def testbed_id(self):
-        return self._testbed_id
-
-    @property
-    def elements(self):
-        return self._elements.values()
-
-    def create(self, factory_id):
-        guid = self.guid_generator.next()
-        factory = self._provider.factories(factory_id)
-        element = factory.create(guid, self)
-        self._elements[guid] = element
-
-    def delete(self, guid):
-        element = self._elements[guid]
-        del self._elements[guid]
-        element.destroy()
-
-    def instructions(self):
-        raise NotImplementedError
-
-    def destroy(self):
-        for guid, element in self._elements.iteitems():
-            del self._elements[guid]
-            element.destroy()
-        self._elements = None
-
 class TestbedConfiguration(AttributesMap):
     pass
 
@@ -292,50 +9,54 @@ class TestbedInstance(object):
     def __init__(self, configuration):
         pass
 
-    def execute(self, instruction):
-        #TODO:
-        pass
+    def create(self, guid, factory_id, parameters):
+        raise NotImplementedError
 
-    def execute_batch(self, batch):
+    def do_create(self):
         raise NotImplementedError
 
-    def create(self, time, guid, factory_id, parameters):
+    def connect(self, object1_guid, object2_guid, connect_code): 
         raise NotImplementedError
 
-    def connect(self, time, connection_guid, 
-            object1_guid, object2_guid, connetor1_id, connector2_id): 
+    def do_connect(self):
         raise NotImplementedError
 
-    def set(self, time, guid, name, value):
+    def enable_trace(self, guid, trace_id):
         raise NotImplementedError
 
-    def get(self, time, guid, name):
+    def add_adddress(self, guid):
+        #TODO
+        raise NotImplementedError
+
+    def add_route(self, guid):
+        #TODO
         raise NotImplementedError
 
-    def start(self, time, guid):
+    def do_configure(self):
         raise NotImplementedError
 
-    def stop(self, time, guid):
+    def cross_connect(self, guid, connect_code, paremeters):
         raise NotImplementedError
 
-    def status(self, time, guid):
+    def do_cross_connect(self):
         raise NotImplementedError
 
-    def enable_trace(self, time, guid, trace_id):
+    def set(self, time, guid, name, value):
         raise NotImplementedError
 
-    def disable_trace(self, time, guid, trace_id):
+    def get(self, time, guid, name):
         raise NotImplementedError
 
-    def get_trace(self, time, guid, trace_id):
+    def start(self, time):
         raise NotImplementedError
 
-    def add_adddress(self, time, guid):
-        #TODO
+    def stop(self, time):
         raise NotImplementedError
 
-    def add_route(self, time, guid):
-        #TODO
+    def status(self, guid):
+        raise NotImplementedError
+
+    def get_trace(self, time, guid, trace_id):
         raise NotImplementedError
 
     def shutdown(self):
diff --git a/src/nepi/testbeds/__init__.py b/src/nepi/testbeds/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/nepi/testbeds/netns/__init__.py b/src/nepi/testbeds/netns/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/nepi/utils/__init__.py b/src/nepi/utils/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/nepi/utils/guid_generator.py b/src/nepi/utils/guid_generator.py
new file mode 100644 (file)
index 0000000..7e28552
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+class GuidGenerator(object):
+    def __init__(self, guid = 0):
+        self._last_guid = guid
+
+    def next(self):
+        self._last_guid += 1
+        return self._last_guid
+