--- /dev/null
+# -*- 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
+ are going to be manipulated by the end-user in a script or GUI.
+ """
+ def __init__(self):
+ self._attributes = dict()
+
+ @property
+ 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
+
+ def set_attribute_readonly(self, name, value):
+ self._attributes[name].readonly = value
+
+ def get_attribute_value(self, name):
+ return self._attributes[name].value
+
+ def get_attribute_help(self, name):
+ return self._attributes[name].help
+
+ def get_attribute_type(self, name):
+ return self._attributes[name].type
+
+ def get_attribute_range(self, name):
+ return self._attributes[name].range
+
+ def get_attribute_allowed(self, name):
+ return self._attributes[name].allowed
+
+ def get_attribute_readonly(self, name):
+ return self._attributes[name].readonly
+
+ def add_attribute(self, name, help, type, value = None, range = None,
+ allowed = None, readonly = False):
+ if name in self._attributes:
+ raise AttributeError('Attribute %s already exists' % name))
+ attribute = Attribute(name, help, type, value, range, allowed, readonly)
+ self._attributes[name] = attribute
+
+ def del_attribute(self, name):
+ del self._attributes[name]
+
+ def has_attribute(self, name):
+ return name in self._attributes
+
+ def destroy(self):
+ self._attributes = dict()
+
+class Attribute(object):
+ STRING , BOOL, ENUM, DOUBLE, INTEGER, ENDPOINT, TIME = (
+ "STRING", "BOOL", "ENUM", "DOUBLE", "INTEGER", "ENDPOINT", "TIME")
+
+ types = [STRING, BOOL, ENUM, DOUBLE, INTEGER, ENDPOINT, TIME]
+
+ def __init__(self, name, help, type, value = None, range = None,
+ allowed = None, readonly = False):
+ 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.readonly = (readonly == True)
+ self.modified = False
+ # range: max and min possible values
+ self.range = range
+ # list of possible values
+ self.allowed = allowed
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:et:ai:sts=4
+from nepi.core.attributes import AttributesMap
+
+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, 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()
+ from nepi.core.connection import Connector
+ for connector_type in factory.connector_types:
+ connector = Connector(self, connector_type)
+ self._connectors[connector_type.name] = 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 connections(self):
+ r = set()
+ for c in self.connectors:
+ r.update(c.connections)
+ return r
+
+ @property
+ def connectors(self):
+ return self._connectors.values()
+
+ @property
+ def traces(self):
+ return self._traces.values()
+
+ @property
+ def instructions(self):
+ raise NotImplementedError
+
+ 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.connections:
+ c.disconnect()
+ if len(self.connections) != 0:
+ raise AttributeError('Some connections could not be disconnected')
+ 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, name, help, display_name, max = -1, min = 0):
+ from nepi.core.connection import ConnectorType
+ connector_type = ConnectorType(name, help, display_name, max, min)
+ self._connector_types.add(connector_type)
+
+ def create(self, guid, backend, 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 Backend(AttributeMap):
+ def __init__(self, guid_generator, testbed_id, provider):
+ super(Backend, 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 remove(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
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:et:ai:sts=4
+
+#TODO: DEF ERRORCODES
+#TODO: DEF PROTOCOL
+
+class Testbed(object):
+ def __init__(self):
+ self._testbeds = dict()
+
+ def create_testbed(self, guid, testbed_id, config, access_config = None):
+ # TODO: proxy
+ # guid: guid of the associated backend
+ self._testbeds[guid] = testbed
+
+ def destroy_testbed(self, guid):
+ tesbed = self._testbeds[guid]
+ tesbed.shutdown()
+ del self._testbeds[guid]
+
+ def forward(self, guid, instruction):
+ #TODO:
+ pass
+
+ def forward_batch(self, guid, batch):
+ raise NotImplementedError
+
+ def start(self):
+ raise NotImplementedError
+
+ def stop(self):
+ raise NotImplementedError
+
+ def status(self):
+ raise NotImplementedError
+
+ def shutdown(self):
+ raise NotImplementedError
+
--- /dev/null
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:et:ai:sts=4
+
+class Experiment(object):
+ def __init__(self):
+ self._backends = dict()
+
+ def add_backend(self, backend):
+ self._backends[backend.guid] = backend
+
+ def remove_backend(self, backend):
+ del self._backends[backend.guid]
+
+ def instructions(self):
+ #TODO
+ pass
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:et:ai:sts=4
+
+class Mobile(object):
+ pass
+
+class RoutingTable(object):
+ def entries(self):
+ pass
+
+ def add_entry(self):
+ pass
+
+ def remove_entry(self):
+ pass
+
+class Entry(object):
+ pass
+
+class Interface(object):
+ pass
+ """
+ Link encap:Local Loopback
+ inet addr:127.0.0.1
+ Mask:255.0.0.0
+ inet6 addr: ::1/128 Scope:Host
+ UP LOOPBACK RUNNING
+ MTU:16436
+ Metric:1
+ """
+
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:et:ai:sts=4
+from nepi.core.attributes import AttributesMap
+
+#TODO: DEF ERRORCODES
+#TODO: DEF PROTOCOL
+
+class Configuration(AttributesMap):
+ pass
+
+class Testbed(object):
+ def __init__(self, configuration):
+ pass
+
+ def execute(self, instruction):
+ #TODO:
+ pass
+
+ def execute_batch(self, batch):
+ raise NotImplementedError
+
+ def create(self, time, guid, factory_id, parameters):
+ raise NotImplementedError
+
+ def destroy(self, time, guid):
+ raise NotImplementedError
+
+ def connect(self, time, connection_guid,
+ object1_guid, object2_guid, connetor1_id, connector2_id):
+ raise NotImplementedError
+
+ def disconnect(self, time, connection_guid):
+ raise NotImplementedError
+
+ def set(self, time, guid, name, value):
+ raise NotImplementedError
+
+ def get(self, time, guid, name):
+ raise NotImplementedError
+
+ def start(self, time, guid):
+ raise NotImplementedError
+
+ def stop(self, time, guid):
+ raise NotImplementedError
+
+ def state(self, time, guid):
+ raise NotImplementedError
+
+ def trace_enable(self, time, guid, trace_id):
+ raise NotImplementedError
+
+ def trace_disable(self, time, guid, trace_id):
+ raise NotImplementedError
+
+ def get_trace(self, time, guid, trace_id):
+ raise NotImplementedError
+
+ def add_adddress(self, time, guid):
+ #TODO
+ raise NotImplementedError
+
+ def add_route(self, time, guid):
+ #TODO
+ raise NotImplementedError
+
+ def shutdown(self):
+ raise NotImplementedError
--- /dev/null
+# -*- coding: utf-8 -*-
+# vim:ts=4:sw=4:et:ai:sts=4
+import errno
+import os
+import select
+import socket
+import sys
+import threading
+
+CTRL_SOCK = "ctrl.sock"
+STD_ERR = "stderr.log"
+MAX_FD = 1024
+
+STOP_MSG = "STOP"
+
+class Server(object):
+ def __init__(self):
+ self.stop = False
+ self.ctrl_sock = None
+
+ def run(self):
+ if self.daemonize():
+ self.loop()
+ self.cleanup()
+
+ def daemonize(self):
+ if True:
+ return 1
+
+ pid1 = os.fork()
+ if pid1 > 0:
+ return 0
+
+ # Decouple from parent environment.
+ #os.chdir(?)
+ os.umask(0)
+ os.setsid()
+
+ # fork 2
+ pid2 = os.fork()
+ if pid2 > 0:
+ return 0
+
+ # close all open file descriptors.
+ for fd in range(0, MAX_FD):
+ try:
+ os.close(fd)
+ except OSError:
+ pass
+
+ # Redirect standard file descriptors.
+ stdout = stderr = file(STD_ERR, "a", 0)
+ stdin = open('/dev/null', 'r')
+ os.dup2(stdin.fileno(), sys.stdin.fileno())
+ os.dup2(stdout.fileno(), sys.stdout.fileno())
+ os.dup2(stderr.fileno(), sys.stderr.fileno())
+ return 1
+
+ def loop(self):
+ self.ctrl_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.ctrl_sock.bind(CTRL_SOCK)
+ self.ctrl_sock.listen(0)
+ while not self.stop:
+ print 'accept'
+ conn, addr = self.ctrl_sock.accept()
+ conn.settimeout(5)
+ while True:
+ try:
+ print 'recv'
+ data = conn.recv(1024)
+ except socket.timeout, e:
+ print e
+ break
+
+ if data == STOP_MSG:
+ self.stop = True
+ else:
+ conn.send("%s received" % data)
+ conn.close()
+
+ def cleanup(self):
+ self.ctrl_sock.close()
+ try:
+ s.remove(CTRL_SOCK)
+ except:
+ pass
+
+class Forwarder(object):
+ def __init__(self):
+ self.ctrl_sock = None
+
+ def forward(self):
+ self.connect()
+ while True:
+ msg = sys.stdin.readline()
+ self.send(msg)
+ reply = self.ctrl_sock.recv(1024)
+ sys.stdout.write(reply)
+
+ def send(self, msg):
+ try:
+ self.ctrl_sock.send(msg)
+ except IOError, e:
+ if e.errno == errno.EPIPE:
+ self.connect()
+ self.ctrl_sock.send(msg)
+ else:
+ raise e
+
+ def connect(self):
+ try:
+ self.ctrl_sock.close()
+ except:
+ pass
+ self.ctrl_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ self.ctrl_sock.connect(CTRL_SOCK)
+
+# Client
+# import subprocess
+# s = subprocess.Popen(['python' ,'-c' 'import server;c=server.Forwarder();c.forward()'], stdin = subprocess.PIPE)
+# s.stdin.write('aaaa\n')