self.slicename = None
self._traces = dict()
- import node, interfaces
+ import node, interfaces, application
self._node = node
self._interfaces = interfaces
+ self._app = application
@property
def home_directory(self):
return self._home_directory
+
+ @property
+ def plapi(self):
+ if not hasattr(self, '_plapi'):
+ import plcapi
+
+ if self.authUser:
+ self._plapi = plcapi.PLCAPI(
+ username = self.authUser,
+ password = self.authString)
+ else:
+ # anonymous access - may not be enough for much
+ self._plapi = plcapi.PLCAPI()
+ return self._plapi
+
+ @property
+ def slice_id(self):
+ if not hasattr(self, '_slice_id'):
+ slices = self.plapi.GetSlices(self.slicename, fields=('slice_id',))
+ if slices:
+ self._slice_id = slices[0]['slice_id']
+ else:
+ # If it wasn't found, don't remember this failure, keep trying
+ return None
+ return self._slice_id
def do_setup(self):
self._home_directory = self._attributes.\
get_attribute_value("homeDirectory")
self.slicename = self._attributes.\
get_attribute_value("slice")
+ self.authUser = self._attributes.\
+ get_attribute_value("authUser")
+ self.authString = self._attributes.\
+ get_attribute_value("authPass")
def do_create(self):
# Create node elements per XML data
# Wait for all nodes to be ready
self.wait_nodes()
+
+ def do_resource_discovery(self):
+ # Do what?
+ pass
+
+ def do_provisioning(self):
+ # Que te recontra?
+ pass
+
+ def wait_nodes(self):
+ # Suuure...
+ pass
def set(self, time, guid, name, value):
super(TestbedController, self).set(time, guid, name, value)
self._traces[trace_id] = trace
def _make_node(self, parameters):
- node = self._node.Node()
+ node = self._node.Node(self.plapi)
# Note: there is 1-to-1 correspondence between attribute names
# If that changes, this has to change as well
- for attr in parameters.get_attribute_names():
- setattr(node, attr, parameters.get_attribute_value(attr))
+ for attr,val in parameters.iteritems():
+ setattr(node, attr, val)
return node
def _make_node_iface(self, parameters):
- iface = self._interfaces.NodeIface()
+ iface = self._interfaces.NodeIface(self.plapi)
# Note: there is 1-to-1 correspondence between attribute names
# If that changes, this has to change as well
- for attr in parameters.get_attribute_names():
- setattr(iface, attr, parameters.get_attribute_value(attr))
+ for attr,val in parameters.iteritems():
+ setattr(iface, attr, val)
return iface
def _make_tun_iface(self, parameters):
- iface = self._interfaces.TunIface()
+ iface = self._interfaces.TunIface(self.plapi)
# Note: there is 1-to-1 correspondence between attribute names
# If that changes, this has to change as well
- for attr in parameters.get_attribute_names():
- setattr(iface, attr, parameters.get_attribute_value(attr))
+ for attr,val in parameters.iteritems():
+ setattr(iface, attr, val)
return iface
def _make_internet(self, parameters):
- return self._node.Internet()
+ return self._interfaces.Internet(self.plapi)
def _make_application(self, parameters):
- app = self._app.Application()
+ app = self._app.Application(self.plapi)
# Note: there is 1-to-1 correspondence between attribute names
# If that changes, this has to change as well
- for attr in parameters.get_attribute_names():
- setattr(app, attr, parameters.get_attribute_value(attr))
+ for attr,val in parameters.iteritems():
+ setattr(app, attr, val)
return app
self.address = None
self.lladdr = None
self.netprefix = None
+ self.netmask = None
self.broadcast = True
self._interface_id = None
# These get initialized when the iface is connected to the internet
self.has_internet = False
+ def __str__(self):
+ return "%s<ip:%s/%s up mac:%s>" % (
+ self.__class__.__name__,
+ self.address, self.netmask,
+ self.lladdr,
+ )
+
def add_address(self, address, netprefix, broadcast):
raise RuntimeError, "Cannot add explicit addresses to public interface"
siblings: other NodeIface elements attached to the same node
"""
- if (self.node or self.node._node_id) is None:
+ if self.node is None or self.node._node_id is None:
raise RuntimeError, "Cannot pick interface without an assigned node"
avail = self._api.GetInterfaces(
node_id=self.node._node_id,
is_primary=self.primary,
- fields=('interface_id','mac','netmask','ip') ))
+ fields=('interface_id','mac','netmask','ip') )
used = set([sibling._interface_id for sibling in siblings
if sibling._interface_id is not None])
self.address = candidate['ip']
self.lladdr = candidate['mac']
self.netprefix = candidate['netmask']
+ self.netmask = ipaddr2.ipv4_dot2mask(self.netprefix) if self.netprefix else None
return
else:
raise RuntimeError, "Cannot configure interface: cannot find suitable interface in PlanetLab node"
def validate(self):
- if not element.has_internet:
+ if not self.has_internet:
raise RuntimeError, "All external interface devices must be connected to the Internet"
# These get initialized when the iface is connected to its node
self.node = None
+ def __str__(self):
+ return "%s<ip:%s/%s %s%s>" % (
+ self.__class__.__name__,
+ self.address, self.netmask,
+ " up" if self.up else " down",
+ " snat" if self.snat else "",
+ )
+
def add_address(self, address, netprefix, broadcast):
if (self.address or self.netprefix or self.netmask) is not None:
raise RuntimeError, "Cannot add more than one address to TUN interfaces"
def create_nodeiface(testbed_instance, guid):
parameters = testbed_instance._get_parameters(guid)
- element = testbed_instance.create_node_iface(parameters)
+ element = testbed_instance._make_node_iface(parameters)
testbed_instance.elements[guid] = element
def create_tuniface(testbed_instance, guid):
parameters = testbed_instance._get_parameters(guid)
traces = testbed_instance._get_traces(guid)
app = testbed_instance.elements[guid]
- sudo = parameters["sudo"]
- command = parameters["command"]
app.stdout = testbed_instance.trace_filename(guid, "stdout")
app.stderr = testbed_instance.trace_filename(guid, "stderr")
return STATUS_NOT_STARTED
app = testbed_instance.elements[guid]
# TODO
- return STATUS_NOT_STARTED
+ return STATUS_FINISHED
### Configure functions ###
def configure_nodeiface(testbed_instance, guid):
element = testbed_instance._elements[guid]
- if not guid in testbed_instance._add_address:
- return
# Cannot explicitly configure addresses
- del testbed_instance._add_address[guid]
+ if guid in testbed_instance._add_address:
+ del testbed_instance._add_address[guid]
# Get siblings
node_guid = testbed_instance.get_connected(guid, "node", "devs")[0]
element = testbed_instance._elements[guid]
if not guid in testbed_instance._add_address:
return
+
addresses = testbed_instance._add_address[guid]
for address in addresses:
(address, netprefix, broadcast) = address
def configure_node(testbed_instance, guid):
element = testbed_instance._elements[guid]
+ # If we have only one candidate, simply use it
+ candidates = element.find_candidates(
+ filter_slice_id = testbed_instance.slice_id)
+ if len(candidates) == 1:
+ element.assign_node_id(iter(candidates).next())
+
# Do some validations
element.validate()
})
})
-create_order = [ NODE, NODEIFACE, TUNIFACE, APPLICATION ]
+create_order = [ INTERNET, NODE, NODEIFACE, TUNIFACE, APPLICATION ]
-configure_order = [ NODE, NODEIFACE, TUNIFACE, APPLICATION ]
+configure_order = [ INTERNET, NODE, NODEIFACE, TUNIFACE, APPLICATION ]
factories_info = dict({
NODE: dict({
"flags": Attribute.DesignOnly | Attribute.HasNoDefaultValue,
"validation_function": validation.is_string
}),
+ "auth_user": dict({
+ "name": "authUser",
+ "help": "The name of the PlanetLab user to use for API calls - it must have at least a User role.",
+ "type": Attribute.STRING,
+ "flags": Attribute.DesignOnly | Attribute.HasNoDefaultValue,
+ "validation_function": validation.is_string
+ }),
+ "auth_pass": dict({
+ "name": "authPass",
+ "help": "The PlanetLab user's password.",
+ "type": Attribute.STRING,
+ "flags": Attribute.DesignOnly | Attribute.HasNoDefaultValue,
+ "validation_function": validation.is_string
+ }),
})
class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
+ filter(has, self.TAGFILTERS.iterkeys())
)
- def find_candidates(self):
+ def find_candidates(self, filter_slice_id=None):
fields = ('node_id',)
replacements = {'timeframe':self.timeframe}
# get initial candidates (no tag filters)
basefilters = self.build_filters({}, self.BASEFILTERS)
+ if filter_slice_id:
+ basefilters['|slice_ids'] = (filter_slice_id,)
# keyword-only "pseudofilters"
extra = {}
return candidates
+ def assign_node_id(self, node_id):
+ self._node_id = node_id
+ self.fetch_node_info()
+
+ def fetch_node_info(self):
+ info = self._api.GetNodes(self._node_id)
+ tags = dict( (t['tagname'],t['value'])
+ for t in self._api.GetNodeTags(node_id=self._node_id, fields=('tagname','value')) )
+
+ self.min_num_external_ifaces = None
+ self.max_num_external_ifaces = None
+ self.timeframe = 'm'
+
+ replacements = {'timeframe':self.timeframe}
+ for attr, tag in self.BASEFILTERS.iteritems():
+ if tag in info:
+ value = info[tag]
+ setattr(self, attr, value)
+ for attr, (tag,_) in self.TAGFILTERS.iteritems():
+ tag = tag % replacements
+ if tag in tags:
+ value = tags[tag]
+ setattr(self, attr, value)
+
+ if 'peer_id' in info:
+ self.site = self._api.peer_map[info['peer_id']]
+
+ if 'interface_ids' in info:
+ self.min_num_external_ifaces = \
+ self.max_num_external_ifaces = len(info['interface_ids'])
+
def validate(self):
pass
(peer['peername'], peer['peer_id'])
for peer in peers
)
+ self._peer_map = dict(
+ (peer['peer_id'], peer['shortname'])
+ for peer in peers
+ )
return self._peer_map
else:
fieldstuple = ()
if interfaceIdOrIp is not None:
- return self.api.GetNodeTags(self.auth, interfaceIdOrIp, *fieldstuple)
+ return self.api.GetInterfaces(self.auth, interfaceIdOrIp, *fieldstuple)
else:
filters = kw.pop('filters',{})
filters.update(kw)
- return self.api.GetNodeTags(self.auth, filters, *fieldstuple)
+ return self.api.GetInterfaces(self.auth, filters, *fieldstuple)
+
+ def GetSlices(self, sliceIdOrName=None, fields=None, **kw):
+ if fields is not None:
+ fieldstuple = (fields,)
+ else:
+ fieldstuple = ()
+ if sliceIdOrName is not None:
+ return self.api.GetSlices(self.auth, sliceIdOrName, *fieldstuple)
+ else:
+ filters = kw.pop('filters',{})
+ filters.update(kw)
+ return self.api.GetSlices(self.auth, filters, *fieldstuple)
import getpass
from nepi.util.constants import STATUS_FINISHED
-from nepi.testbeds import netns
+from nepi.testbeds import planetlab
import os
import shutil
import tempfile
import test_util
import time
import unittest
+import re
class NetnsExecuteTestCase(unittest.TestCase):
def setUp(self):
def tearDown(self):
shutil.rmtree(self.root_dir)
+ def test_simple(self):
+ testbed_version = "01"
+ instance = planetlab.TestbedController(testbed_version)
+
+ instance.defer_configure("homeDirectory", self.root_dir)
+ instance.defer_configure("slice", "inria_nepi12")
+ instance.defer_configure("authUser", "claudio-daniel.freire@inria.fr")
+ instance.defer_configure("authPass", getpass.getpass())
+
+ instance.defer_create(2, "Node")
+ instance.defer_create_set(2, "hostname", "onelab11.pl.sophia.inria.fr")
+ instance.defer_create(3, "Node")
+ instance.defer_create_set(3, "hostname", "onelab10.pl.sophia.inria.fr")
+ instance.defer_create(4, "NodeInterface")
+ instance.defer_connect(2, "devs", 4, "node")
+ instance.defer_create(5, "NodeInterface")
+ instance.defer_connect(3, "devs", 5, "node")
+ instance.defer_create(6, "Internet")
+ instance.defer_connect(4, "inet", 6, "devs")
+ instance.defer_connect(5, "inet", 6, "devs")
+ instance.defer_create(7, "Application")
+ instance.defer_create_set(7, "command", "ping -qc1 {#GUID-3.addr[0].[ip]#}")
+ instance.defer_add_trace(7, "stdout")
+ instance.defer_connect(7, "node", 2, "apps")
+
+ instance.do_setup()
+ instance.do_create()
+ instance.do_connect()
+ instance.do_configure()
+
+ print instance.elements[4]
+ print instance.elements[5]
+
+ instance.start()
+ while instance.status(7) != STATUS_FINISHED:
+ time.sleep(0.5)
+ ping_result = instance.trace(7, "stdout")
+ comp_result = r"""PING .* \(.*) \d*\(\d*\) bytes of data.
+
+--- .* ping statistics ---
+1 packets transmitted, 1 received, 0% packet loss, time \d*ms.*
+"""
+ self.assertTrue(re.match(comp_result, ping_result, re.MULTILINE))
+ instance.stop()
+ instance.shutdown()
+
+
if __name__ == '__main__':
unittest.main()