default = None,
allowed = ["PLAIN", "AES", "Blowfish", "DES", "DES3"],
type = Types.Enumerate,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cipher_key = Attribute("cipherKey",
"Specify a symmetric encryption key with which to protect "
"packets across the tunnel. python-crypto must be installed "
"on the system." ,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
txqueuelen = Attribute("txQueueLen",
"Specifies the interface's transmission queue length. "
"Defaults to 1000. ",
type = Types.Integer,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
bwlimit = Attribute("bwLimit",
"Specifies the interface's emulated bandwidth in bytes "
"per second.",
type = Types.Integer,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cls._register_attribute(cipher)
cls._register_attribute(cipher_key)
self.do_discover()
self.do_provision()
- self.debug("----- READY ---- ")
self.set_ready()
def do_start(self):
result = None
delay = 1.0
- for i in xrange(4):
+ for i in xrange(20):
(out, err), proc = endpoint.node.check_output(
self.run_home(endpoint), filename)
reschedule_delay = "0.5s"
@clsinit_copy
- class OVSWitch(LinuxApplication):
-
- _rtype = "OVSWitch"
+ class OVSSwitch(LinuxApplication):
+ """
+ .. class:: Class Args :
+
+ :param ec: The Experiment controller
+ :type ec: ExperimentController
+ :param guid: guid of the RM
+ :type guid: int
+
+ """
+
+ _rtype = "OVSSwitch"
_help = "Runs an OpenVSwitch on a PlanetLab host"
_backend = "planetlab"
@classmethod
def _register_attributes(cls):
- """ Register the attributes of OVSWitch RM
+ """ Register the attributes of OVSSwitch RM
"""
bridge_name = Attribute("bridge_name", "Name of the switch/bridge",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
virtual_ip_pref = Attribute("virtual_ip_pref", "Virtual IP/PREFIX of the switch",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
controller_ip = Attribute("controller_ip", "IP of the controller",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
controller_port = Attribute("controller_port", "Port of the controller",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cls._register_attribute(bridge_name)
cls._register_attribute(virtual_ip_pref)
:type guid: int
"""
- super(OVSWitch, self).__init__(ec, guid)
- self._pid = None
- self._ppid = None
- self._home = "ovswitch-%s" % self.guid
+ super(OVSSwitch, self).__init__(ec, guid)
+ self._home = "ovsswitch-%s" % self.guid
self._checks = "ovsChecks-%s" % self.guid
@property
def node(self):
+ """ Node wthat run the switch
+ """
node = self.get_connected(PlanetlabNode.get_rtype())
if node: return node[0]
return None
+ def log_message(self, msg):
+ return " guid %d - OVSSwitch - %s " % (self.guid, msg)
+
@property
def ovs_home(self):
return os.path.join(self.node.exp_home, self._home)
def ovs_checks(self):
return os.path.join(self.ovs_home, self._checks)
- @property
- def pid(self):
- return self._pid
+ def valid_connection(self, guid):
+ """ Check if the connection with the guid in parameter is possible. Only meaningful connections are allowed.
- @property
- def ppid(self):
- return self._ppid
-
- # def valid_connection(self, guid):
- # """ Check if the connection with the guid in parameter is possible. Only meaningful connections are allowed.
-
- # :param guid: Guid of the current RM
- # :type guid: int
- # :rtype: Boolean
-
- # """
- # rm = self.ec.get_resource(guid)
- # if rm.get_rtype() in self._authorized_connections:
- # msg = "Connection between %s %s and %s %s accepted" % \
- # (self.get_rtype(), self._guid, rm.get_rtype(), guid)
- # self.debug(msg)
- # return True
- # msg = "Connection between %s %s and %s %s refused" % \
- # (self.get_rtype(), self._guid, rm.get_rtype(), guid)
- # self.debug(msg)
- # return False
+ :param guid: Guid of the current RM
+ :type guid: int
+ :rtype: Boolean
- def valid_connection(self, guid):
- # TODO: Validate!
- return True
+ """
+ rm = self.ec.get_resource(guid)
+ if rm.get_rtype() in self._authorized_connections:
+ msg = "Connection between %s %s and %s %s accepted" % \
+ (self.get_rtype(), self._guid, rm.get_rtype(), guid)
+ self.debug(msg)
+ return True
+ msg = "Connection between %s %s and %s %s refused" % \
+ (self.get_rtype(), self._guid, rm.get_rtype(), guid)
+ self.debug(msg)
+ return False
def do_provision(self):
+ """ Create the different OVS folder.
+ """
+
# create home dir for ovs
self.node.mkdir(self.ovs_home)
# create dir for ovs checks
self.node.mkdir(self.ovs_checks)
- super(OVSWitch, self).do_provision()
+ super(OVSSwitch, self).do_provision()
+
+ def do_deploy(self):
+ """ Deploy the OVS Switch : Turn on the server, create the bridges
+ and assign the controller
+ """
+
+ if not self.node or self.node.state < ResourceState.READY:
+ self.ec.schedule(reschedule_delay, self.deploy)
+ return
+
+ self.do_discover()
+ self.do_provision()
+
+ self.check_sliver_ovs()
+ self.servers_on()
+ self.create_bridge()
+ self.assign_controller()
+ self.ovs_status()
+
+ super(OVSSwitch, self).do_deploy()
def check_sliver_ovs(self):
- """ Check if sliver-ovs exists. If it does not exist, we interrupt
- the execution immediately.
+ """ Check if sliver-ovs exists. If it does not exist, the execution is stopped
"""
+
cmd = "compgen -c | grep sliver-ovs"
out = err = ""
raise RuntimeError, msg
msg = "Command sliver-ovs exists"
- self.debug(msg)
-
- def do_deploy(self):
- """ Wait until node is associated and deployed
- """
- node = self.node
- if not node or node.state < ResourceState.READY:
- #self.debug("---- RESCHEDULING DEPLOY ---- node state %s " % self.node.state )
- self.ec.schedule(reschedule_delay, self.deploy)
- return
-
- self.do_discover()
- self.do_provision()
- self.check_sliver_ovs()
- self.servers_on()
- self.create_bridge()
- self.assign_controller()
- self.ovs_status()
-
- super(OVSWitch, self).do_deploy()
+ self.debug(msg)
def servers_on(self):
- """ Start the openvswitch servers and also checking
- if they started successfully
+ """ Start the openvswitch servers and check it
"""
- self.info("Starting the OVSWitch servers")
- command = ("sliver-ovs start")
-
+
+ # Start the server
+ command = "sliver-ovs start"
out = err = ""
(out, err), proc = self.node.run_and_wait(command, self.ovs_checks,
shfile = "start_srv.sh",
raise_on_error = True,
stdout = "start_srv_stdout",
stderr = "start_srv_stderr")
-
(out, err), proc = self.node.check_output(self.ovs_checks, 'start_srv_exitcode')
if out != "0\n":
self.error("Servers have not started")
raise RuntimeError, msg
+ # Check if the servers are running or not
cmd = "ps -A | grep ovsdb-server"
out = err = ""
(out, err), proc = self.node.run_and_wait(cmd, self.ovs_checks,
sudo = True,
stdout = "status_srv_stdout",
stderr = "status_srv_stderr")
-
- # Check if the servers are running or not
(out, err), proc = self.node.check_output(self.ovs_checks, 'status_srv_exitcode')
if out != "0\n":
- self.error("Servers are not running")
+ msg = "Servers are not running"
+ self.error(msg)
raise RuntimeError, msg
- self.info("Servers started")
-
- def del_old_br(self):
- # TODO: Delete old bridges that might exist maybe by adding atribute
- """ With ovs-vsctl list-br
- """
- pass
+ self.info("Server OVS Started Correctly")
def create_bridge(self):
- """ Create the bridge/switch and we check if we have any
- error during the SSH connection
+ """ Create the bridge/switch and check error during SSH connection
"""
+ # TODO: Check if previous bridge exist and delete them. Use ovs-vsctl list-br
# TODO: Add check for virtual_ip belonging to vsys_tag
- self.del_old_br()
+
if not (self.get("bridge_name") and self.get("virtual_ip_pref")):
msg = "No assignment in one or both attributes"
self.error(msg)
- self.debug("Bridge name is %s and virtual_ip_pref is %s" %\
- (self.get("bridge_name"), self.get("virtual_ip_pref")) )
raise AttributeError, msg
-
- bridge_name = self.get("bridge_name")
- virtual_ip_pref = self.get("virtual_ip_pref")
- self.info(" Creating the bridge %s and assigning %s" %\
- (bridge_name, virtual_ip_pref) )
+
cmd = "sliver-ovs create-bridge '%s' '%s'" %\
- (bridge_name, virtual_ip_pref)
+ (self.get("bridge_name"), self.get("virtual_ip_pref"))
out = err = ""
(out, err), proc = self.node.run_and_wait(cmd, self.ovs_checks,
shfile = "create_br.sh",
sudo = True,
stdout = "create_br_stdout",
stderr = "create_br_stderr")
-
(out, err), proc = self.node.check_output(self.ovs_checks, 'create_br_exitcode')
+
if out != "0\n":
msg = "No such pltap netdev\novs-appctl: ovs-vswitchd: server returned an error"
- self.debug("Check again the virtual IP")
+ self.error(msg)
raise RuntimeError, msg
- self.info("Bridge %s created" % bridge_name)
+ self.info(" Bridge %s Created and Assigned to %s" %\
+ (self.get("bridge_name"), self.get("virtual_ip_pref")) )
def assign_controller(self):
""" Set the controller IP
"""
- if self.get("controller_ip") and self.get("controller_port"):
- controller_ip = self.get("controller_ip")
- controller_port = self.get("controller_port")
- self.info("Assigning the controller to the %s" % self.get("bridge_name"))
- cmd = "ovs-vsctl set-controller %s tcp:%s:%s" %\
- (self.get("bridge_name"), controller_ip, controller_port)
- out = err = ""
- (out, err), proc = self.node.run(cmd, self.ovs_checks,
- sudo = True,
- stdout = "stdout",
- stderr = "stderr")
- if err != "":
- self.debug("SSH connection refusing in assign_contr")
- raise RuntimeError, msg
- self.info("Controller assigned")
+
+ if not (self.get("controller_ip") and self.get("controller_port")):
+ msg = "No assignment in one or both attributes"
+ self.error(msg)
+ raise AttributeError, msg
+
+ cmd = "ovs-vsctl set-controller %s tcp:%s:%s" %\
+ (self.get("bridge_name"), self.get("controller_ip"), self.get("controller_port"))
+ out = err = ""
+ (out, err), proc = self.node.run(cmd, self.ovs_checks,
+ sudo = True,
+ stdout = "stdout",
+ stderr = "stderr")
+
+ if err != "":
+ msg = "SSH connection in the method assign_controller"
+ self.error(msg)
+ raise RuntimeError, msg
+
+ self.info("Controller assigned to the bridge %s" % self.get("bridge_name"))
def ovs_status(self):
- """ Print the status of the created bridge
+ """ Print the status of the bridge
"""
+
cmd = "sliver-ovs show | tail -n +2"
out = err = ""
(out, err), proc = self.node.run_and_wait(cmd, self.ovs_home,
stdout = "show_stdout",
stderr = "show_stderr")
(out, err), proc = self.node.check_output(self.ovs_home, 'show_stdout')
- self.info(out)
+
+ if out == "":
+ msg = "Error when checking the status of the OpenVswitch"
+ self.error(msg)
+ raise RuntimeError, msg
+
+ self.debug(out)
def do_release(self):
- """ Delete the bridge and
- close the servers
+ """ Delete the bridge and close the server.
+
+ .. note : It need to wait for the others RM (OVSPort and OVSTunnel)
+ to be released before releasing itself
+
"""
- # Node needs to wait until all associated RMs are released
- # to be released
+
from nepi.resources.planetlab.openvswitch.ovsport import OVSPort
rm = self.get_connected(OVSPort.get_rtype())
- if rm[0].state < ResourceState.STOPPED:
+ if rm[0].state < ResourceState.RELEASED:
self.ec.schedule(reschedule_delay, self.release)
return
- msg = "Deleting the bridge %s" % self.get('bridge_name')
- self.info(msg)
cmd = "sliver-ovs del-bridge %s" % self.get('bridge_name')
(out, err), proc = self.node.run(cmd, self.ovs_checks,
sudo = True)
+
cmd = "sliver-ovs stop"
(out, err), proc = self.node.run(cmd, self.ovs_checks,
sudo = True)
+
+ msg = "Deleting the bridge %s" % self.get('bridge_name')
+ self.info(msg)
if proc.poll():
self.error(msg, out, err)
raise RuntimeError, msg
- super(OVSWitch, self).do_release()
+ super(OVSSwitch, self).do_release()
from nepi.execution.attribute import Attribute, Flags, Types
from nepi.execution.resource import ResourceManager, clsinit_copy, \
ResourceState
- from nepi.resources.planetlab.openvswitch.ovs import OVSWitch
+ from nepi.resources.planetlab.openvswitch.ovs import OVSSwitch
from nepi.resources.planetlab.node import PlanetlabNode
from nepi.resources.linux.application import LinuxApplication
_help = "Runs an OpenVSwitch on a PlanetLab host"
_backend = "planetlab"
- _authorized_connections = ["OVSWitch", "Tunnel"]
+ _authorized_connections = ["OVSSwitch", "OVSTunnel"]
@classmethod
def _register_attributes(cls):
"""
port_name = Attribute("port_name", "Name of the port",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cls._register_attribute(port_name)
self._port_number = None
self.port_info = []
+ def log_message(self, msg):
+ return " guid %d - OVSPort - %s " % (self.guid, msg)
+
@property
def node(self):
- rm_list = self.get_connected(OVSWitch.get_rtype())
+ """ Node that run the switch and the ports
+ """
+ rm_list = self.get_connected(OVSSwitch.get_rtype())
if rm_list:
for elt in rm_list:
node = elt.get_connected(PlanetlabNode.get_rtype())
return node[0]
@property
- def ovswitch(self):
- ovswitch = self.get_connected(OVSWitch.get_rtype())
- if ovswitch: return ovswitch[0]
+ def ovsswitch(self):
+ """ Switch where the port is created
+ """
+ ovsswitch = self.get_connected(OVSSwitch.get_rtype())
+ if ovsswitch: return ovsswitch[0]
return None
@property
return self._port_number
def valid_connection(self, guid):
- # TODO: Validate!
- return True
-
- # def valid_connection(self, guid):
- # """ Check if the connection is available.
-
- # :param guid: Guid of the current RM
- # :type guid: int
- # :rtype: Boolean
-
- # """
- # rm = self.ec.get_resource(guid)
- # if rm.get_rtype() in self._authorized_connections:
- # msg = "Connection between %s %s and %s %s accepted" % (self.get_rtype(), self._guid, rm.get_rtype(), guid)
- # self.debug(msg)
- # return True
- # msg = "Connection between %s %s and %s %s refused" % (self.get_rtype(), self._guid, rm.get_rtype(), guid)
- # self.debug(msg)
-
- def get_host_ip(self):
- """ Get the hostname of the node that
- the port belongs to. We use it for tunnel.
+ """ Check if the connection is available.
+
+ :param guid: Guid of the current RM
+ :type guid: int
+ :rtype: Boolean
+
"""
- get_host_ip = self.node
- if not get_host_ip:
- msg = "info_list is empty"
+ rm = self.ec.get_resource(guid)
+ if rm.get_rtype() in self._authorized_connections:
+ msg = "Connection between %s %s and %s %s accepted" % (self.get_rtype(), self._guid, rm.get_rtype(), guid)
self.debug(msg)
- raise RuntimeError, msg
+ return True
+ msg = "Connection between %s %s and %s %s refused" % (self.get_rtype(), self._guid, rm.get_rtype(), guid)
+ self.debug(msg)
- import socket
- self.port_info.append(get_host_ip.get('hostname'))
- self.port_info.append(socket.gethostbyname(self.port_info[0]))
-
def create_port(self):
""" Create the desired port
"""
- port_name = self.get('port_name')
+ msg = "Creating the port %s" % self.get('port_name')
+ self.debug(msg)
- if not (port_name or self.ovswitch):
- msg = "The rm_list is empty or the port name is not assigned\n Failed to create port"
+ if not self.get('port_name'):
+ msg = "The port name is not assigned"
self.error(msg)
- self.debug("ovswitch_list = %s and port_name = %s" % (self.ovswitch, port_name) )
raise AttributeError, msg
- self.info("Create the port %s on switch %s" % (port_name, self.ovswitch.get('bridge_name')))
- self.port_info.append(port_name)
- self.port_info.append(self.ovswitch.get('virtual_ip_pref'))
- cmd = "sliver-ovs create-port %s %s" % (self.ovswitch.get('bridge_name'), port_name)
- self.node.run(cmd, self.ovswitch.ovs_checks,
- stderr = "stdout-%s" % port_name,
- stdout = "stderr-%s" % port_name,
+ if not self.ovsswitch:
+ msg = "The OVSwitch RM is not running"
+ self.error(msg)
+ raise AttributeError, msg
+
+ cmd = "sliver-ovs create-port %s %s" % (self.ovsswitch.get('bridge_name'),
+ self.get('port_name'))
+ self.node.run(cmd, self.ovsswitch.ovs_checks,
+ stderr = "stdout-%s" % self.get('port_name'),
+ stdout = "stderr-%s" % self.get('port_name'),
sudo = True)
+
+ self.info("Created the port %s on switch %s" % (self.get('port_name'),
+ self.ovsswitch.get('bridge_name')))
def get_local_end(self):
""" Get the local_endpoint of the port
"""
- msg = "Discovering the number of the port %s"\
- % self.get('port_name')
- self.info(msg)
- command = "sliver-ovs get-local-endpoint %s"\
- % self.get('port_name')
+ msg = "Discovering the number of the port %s" % self.get('port_name')
+ self.debug(msg)
+
+ command = "sliver-ovs get-local-endpoint %s" % self.get('port_name')
out = err = ""
- (out, err), proc = self.node.run_and_wait(command, self.ovswitch.ovs_checks,
+ (out, err), proc = self.node.run_and_wait(command,
+ self.ovsswitch.ovs_checks,
shfile = "port_number-%s.sh" % self.get('port_name'),
pidfile = "port_number_pidfile-%s" % self.get('port_name'),
ecodefile = "port_number_exitcode-%s" % self.get('port_name'),
stderr = "stderr-%s" % self.get('port_name'))
if err != "":
- msg = "No assignment in attribute port_name"
+ msg = "Error retrieving the local endpoint of the port"
self.error(msg)
- self.debug("You are in the method get_local_end and the port_name = %s" % self.get('port_name'))
raise AttributeError, msg
- self._port_number = None
- self._port_number = int(out)
- self.port_info.append(self._port_number)
- self.info("The number of the %s is %s" % (self.get('port_name'), self._port_number))
+ if out:
+ self._port_number = int(out)
+
+ self.info("The number of the %s is %s" % (self.get('port_name'),
+ self.port_number))
+ def set_port_info(self):
+ """ Set all the information about the port inside a list
+ """
+
+ info = []
+ info.append(self.node.get('hostname'))
+
+ #Return the ip of the node
+ import socket
+ ip = socket.gethostbyname(self.node.get('hostname'))
+ info.append(ip)
+
+ info.append(self.get('port_name'))
+ info.append(self.ovsswitch.get('virtual_ip_pref'))
+ info.append(self.port_number)
+ return info
+
def switch_connect_command(self, local_port_name,
remote_ip, remote_port_num):
- """ Script for switch links
+ """ Script to create the connection from a switch to a
+ remote endpoint
"""
+
command = ["sliver-ovs"]
command.append("set-remote-endpoint ")
command.append("%s " % local_port_name)
return command
def do_deploy(self):
- """ Wait until ovswitch is started
+ """ Deploy the OVS port after the OVS Switch
"""
- ovswitch = self.ovswitch
- if not ovswitch or ovswitch.state < ResourceState.READY:
- self.debug("---- RESCHEDULING DEPLOY ---- node state %s " % self.ovswitch.state )
+ if not self.ovsswitch or self.ovsswitch.state < ResourceState.READY:
+ self.debug("---- RESCHEDULING DEPLOY ---- OVSwitch state %s " % self.ovsswitch.state )
self.ec.schedule(reschedule_delay, self.deploy)
return
self.do_discover()
self.do_provision()
- self.get_host_ip()
+
self.create_port()
self.get_local_end()
- self.ovswitch.ovs_status()
+
+ #Check the status of the OVS Switch
+ self.ovsswitch.ovs_status()
+
+ # Save all the information inside a list
+ self.port_info = self.set_port_info()
super(OVSPort, self).do_deploy()
def do_release(self):
- """ Release the port RM means delete the ports
+ """ Delete the port on the OVSwitch. It needs to wait for the tunnel
+ to be released.
"""
- # OVS needs to wait until all associated RMs are released
- # to be released
+
from nepi.resources.planetlab.openvswitch.tunnel import OVSTunnel
rm = self.get_connected(OVSTunnel.get_rtype())
- if rm and rm[0].state < ResourceState.STOPPED:
+ if rm and rm[0].state < ResourceState.RELEASED:
self.ec.schedule(reschedule_delay, self.release)
return
- msg = "Deleting the port %s" % self.get('port_name')
- self.info(msg)
cmd = "sliver-ovs del_port %s" % self.get('port_name')
- (out, err), proc = self.node.run(cmd, self.ovswitch.ovs_checks,
+ (out, err), proc = self.node.run(cmd, self.ovsswitch.ovs_checks,
sudo = True)
+ msg = "Deleting the port %s" % self.get('port_name')
+ self.info(msg)
+
if proc.poll():
self.error(msg, out, err)
raise RuntimeError, msg
ResourceState
from nepi.resources.linux.application import LinuxApplication
from nepi.resources.planetlab.node import PlanetlabNode
- from nepi.resources.planetlab.openvswitch.ovs import OVSWitch
+ from nepi.resources.planetlab.openvswitch.ovs import OVSSwitch
from nepi.util.timefuncs import tnow, tdiffsec
from nepi.resources.planetlab.vroute import PlanetlabVroute
from nepi.resources.planetlab.tap import PlanetlabTap
@classmethod
def _register_attributes(cls):
- """ Register the attributes of Connection RM
+ """ Register the attributes of OVSTunnel RM
"""
network = Attribute("network", "IPv4 Network Address",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cipher = Attribute("cipher",
"Cipher to encript communication. "
default = None,
allowed = ["PLAIN", "AES", "Blowfish", "DES", "DES3"],
type = Types.Enumerate,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cipher_key = Attribute("cipherKey",
"Specify a symmetric encryption key with which to protect "
"packets across the tunnel. python-crypto must be installed "
"on the system." ,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
txqueuelen = Attribute("txQueueLen",
"Specifies the interface's transmission queue length. "
"Defaults to 1000. ",
type = Types.Integer,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
bwlimit = Attribute("bwLimit",
"Specifies the interface's emulated bandwidth in bytes "
"per second.",
type = Types.Integer,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cls._register_attribute(network)
cls._register_attribute(cipher)
super(OVSTunnel, self).__init__(ec, guid)
self._home = "tunnel-%s" % self.guid
self.port_info_tunl = []
- self._nodes = []
self._pid = None
self._ppid = None
self._vroute = None
-
+ self._node_endpoint1 = None
+ self._node_endpoint2 = None
def log_message(self, msg):
return " guid %d - Tunnel - %s " % (self.guid, msg)
- @property
- def node(self):
- if self._nodes:
- return self._nodes[0]
-
def app_home(self, node):
- return os.path.join(self.node.exp_home, self._home)
+ return os.path.join(node.exp_home, self._home)
def run_home(self, node):
return os.path.join(self.app_home(node), self.ec.run_id)
- def port_endpoints(self):
- # Switch-Switch connection
- connected = []
+ @property
+ def tap(self):
+ """ Return the Tap RM if it exists """
+ rclass = ResourceFactory.get_resource_type(PlanetlabTap.get_rtype())
for guid in self.connections:
rm = self.ec.get_resource(guid)
- if hasattr(rm, "create_port"):
- connected.append(rm)
- return connected
+ if isinstance(rm, rclass):
+ return rm
-
- def mixed_endpoints(self):
- # Switch-Host connection
- connected = [1, 2]
+ @property
+ def ovsswitch(self):
+ """ Return the 1st switch """
+ for guid in self.connections:
+ rm_port = self.ec.get_resource(guid)
+ if hasattr(rm_port, "create_port"):
+ rm_list = rm_port.get_connected(OVSSwitch.get_rtype())
+ if rm_list:
+ return rm_list[0]
+
+ @property
+ def check_switch_host_link(self):
+ """ Check if the links are between switches
+ or switch-host. Return False for the latter.
+ """
+ if self.tap :
+ return True
+ return False
+
+
+ def endpoints(self):
+ """ Return the list with the two connected elements.
+ Either Switch-Switch or Switch-Host
+ """
+ connected = [1, 1]
+ position = 0
for guid in self.connections:
rm = self.ec.get_resource(guid)
if hasattr(rm, "create_port"):
- connected[0] = rm
+ connected[position] = rm
+ position += 1
elif hasattr(rm, "udp_connect_command"):
connected[1] = rm
return connected
def get_node(self, endpoint):
- # Get connected to the nodes
- res = []
+ """ Get the nodes of the endpoint
+ """
+ rm = []
if hasattr(endpoint, "create_port"):
- rm_list = endpoint.get_connected(OVSWitch.get_rtype())
+ rm_list = endpoint.get_connected(OVSSwitch.get_rtype())
if rm_list:
rm = rm_list[0].get_connected(PlanetlabNode.get_rtype())
else:
rm = endpoint.get_connected(PlanetlabNode.get_rtype())
if rm :
- res.append(rm[0])
- return res
+ return rm[0]
@property
def endpoint1(self):
- if self.check_endpoints:
- port_endpoints = self.port_endpoints()
- if port_endpoints: return port_endpoints[0]
- else:
- mixed_endpoints = self.mixed_endpoints()
- if mixed_endpoints: return mixed_endpoints[0]
+ """ Return the first endpoint : Always a Switch
+ """
+ endpoint = self.endpoints()
+ return endpoint[0]
@property
def endpoint2(self):
- if self.check_endpoints:
- port_endpoints = self.port_endpoints()
- if port_endpoints: return port_endpoints[1]
- else:
- mixed_endpoints = self.mixed_endpoints()
- if mixed_endpoints: return mixed_endpoints[1]
-
- @property
- def check_endpoints(self):
- """ Check if the links are between switches
- or switch-host. Return False for latter.
+ """ Return the second endpoint : Either a Switch or a TAP
"""
- port_endpoints = self.port_endpoints()
- if len(port_endpoints) == 2:
- return True
- return False
+ endpoint = self.endpoints()
+ return endpoint[1]
- def get_port_info(self, endpoint, rem_endpoint):
+ def get_port_info(self, endpoint1, endpoint2):
+ #TODO : Need to change it. Really bad to have method that return different type of things !!!!!
""" Retrieve the port_info list for each port
- :param port_info_tunl: [hostname, publ_IP_addr, port_name,
- virtual_ip, local_port_Numb]
- :type port_info_tunl: list
- """
- self.port_info_tunl = []
- if self.check_endpoints:
- # Use for the link switch-->switch
- self.port_info_tunl.append(endpoint.port_info)
- host0, ip0, pname0, virt_ip0, pnumber0 = self.port_info_tunl[0]
- self.port_info_tunl.append(rem_endpoint.port_info)
- host1, ip1, pname1, virt_ip1, pnumber1 = self.port_info_tunl[1]
- return (pname0, ip1, pnumber1)
-
- # Use for the link host-->switch
- self.port_info_tunl.append(endpoint.port_info)
- host0, ip0, pname0, virt_ip0, pnumber0 = self.port_info_tunl[0]
- return pnumber0
-
- def udp_connect(self, endpoint, rem_endpoint):
- # Collect info from rem_endpoint
- self._nodes = self.get_node(rem_endpoint)
- remote_ip = socket.gethostbyname(self.node.get("hostname"))
- # Collect info from endpoint
- self._nodes = self.get_node(endpoint)
- local_port_file = os.path.join(self.run_home(self.node),
- "local_port")
- remote_port_file = os.path.join(self.run_home(self.node),
- "remote_port")
- ret_file = os.path.join(self.run_home(self.node),
- "ret_file")
- cipher = self.get("cipher")
- cipher_key = self.get("cipherKey")
- bwlimit = self.get("bwLimit")
- txqueuelen = self.get("txQueueLen")
-
- rem_port = str(self.get_port_info(rem_endpoint, endpoint))
- # Upload the remote port in a file
- self.node.upload(rem_port,
- remote_port_file,
- text = True,
- overwrite = False)
-
- udp_connect_command = endpoint.udp_connect_command(
- remote_ip, local_port_file, remote_port_file,
- ret_file, cipher, cipher_key, bwlimit, txqueuelen)
-
- # upload command to host_connect.sh script
- shfile = os.path.join(self.app_home(self.node), "host_connect.sh")
- self.node.upload(udp_connect_command,
- shfile,
- text = True,
- overwrite = False)
-
- # invoke connect script
- cmd = "bash %s" % shfile
- (out, err), proc = self.node.run(cmd, self.run_home(self.node),
- sudo = True,
- stdout = "udp_stdout",
- stderr = "udp_stderr")
-
- # check if execution errors
- msg = "Failed to connect endpoints"
-
- if proc.poll():
- self.error(msg, out, err)
- raise RuntimeError, msg
-
- msg = "Connection on host %s configured" \
- % self.node.get("hostname")
- self.debug(msg)
-
- # Wait for pid file to be generated
- self._nodes = self.get_node(endpoint)
- pid, ppid = self.node.wait_pid(self.run_home(self.node))
-
- # If the process is not running, check for error information
- # on the remote machine
- if not pid or not ppid:
- (out, err), proc = self.node.check_errors(self.run_home(self.node))
- # Out is what was written in the stderr file
- if err:
- msg = " Failed to start command '%s' " % command
- self.error(msg, out, err)
- raise RuntimeError, msg
-
- return (pid, ppid)
-
- def switch_connect(self, endpoint, rem_endpoint):
- """ Get switch connect command
"""
- # Get and configure switch connection command
- (local_port_name, remote_ip, remote_port_num) = self.get_port_info(
- endpoint, rem_endpoint)
- switch_connect_command = endpoint.switch_connect_command(
- local_port_name, remote_ip, remote_port_num)
- self._nodes = self.get_node(endpoint)
-
- # Upload command to the file sw_connect.sh
- shfile = os.path.join(self.app_home(self.node), "sw_connect.sh")
- self.node.upload(switch_connect_command,
- shfile,
- text = True,
- overwrite = False)
+ if self.check_switch_host_link :
+ host0, ip0, pname0, virt_ip0, pnumber0 = endpoint1.port_info
+ return pnumber0
- #invoke connect script
- cmd = "bash %s" % shfile
- (out, err), proc = self.node.run(cmd, self.run_home(self.node),
- sudo = True,
- stdout = "sw_stdout",
- stderr = "sw_stderr")
-
- # check if execution errors occured
- if proc.poll():
- msg = "Failed to connect endpoints"
- self.error(msg, out, err)
- raise RuntimeError, msg
-
- # For debugging
- msg = "Connection on port %s configured" % local_port_name
- self.info(msg)
+ host0, ip0, pname0, virt_ip0, pnumber0 = endpoint1.port_info
+ host1, ip1, pname1, virt_ip1, pnumber1 = endpoint2.port_info
- def wait_local_port(self):
+ return pname0, ip1, pnumber1
+
+ def wait_local_port(self, node_endpoint):
""" Waits until the if_name file for the command is generated,
and returns the if_name for the device """
+
local_port = None
delay = 1.0
+ #TODO : Need to change it with reschedule to avoid the problem
+ # of the order of connection
for i in xrange(10):
- (out, err), proc = self.node.check_output(self.run_home(self.node), 'local_port')
-
+ (out, err), proc = node_endpoint.check_output(self.run_home(node_endpoint), 'local_port')
if out:
local_port = int(out)
break
return local_port
- def sw_host_connect(self, endpoint, rem_endpoint):
- """Link switch--> host
+ def connection(self, local_endpoint, rm_endpoint):
+ """ Create the connect command for each case :
+ - Host - Switch,
+ - Switch - Switch,
+ - Switch - Host
"""
- # Retrieve remote port number from rem_endpoint
- local_port_name = endpoint.get('port_name')
- self._nodes = self.get_node(rem_endpoint)
-
- # time.sleep(4) # Without this, sometimes I get nothing in remote_port_num
- out = err= ''
- remote_port_num = self.wait_local_port()
- remote_ip = socket.gethostbyname(self.node.get("hostname"))
- switch_connect_command = endpoint.switch_connect_command(
- local_port_name, remote_ip, remote_port_num)
-
- # Upload command to the file sw_connect.sh
- self._nodes = self.get_node(endpoint)
- shfile = os.path.join(self.app_home(self.node), "sw_connect.sh")
- self.node.upload(switch_connect_command,
+ local_node = self.get_node(local_endpoint)
+ local_node.mkdir(self.run_home(local_node))
+
+ rm_node = self.get_node(rm_endpoint)
+ rm_node.mkdir(self.run_home(rm_node))
+
+ # Host to switch
+ if self.check_switch_host_link and local_endpoint == self.endpoint2 :
+ # Collect info from rem_endpoint
+ remote_ip = socket.gethostbyname(rm_node.get("hostname"))
+
+ # Collect info from endpoint
+ local_port_file = os.path.join(self.run_home(local_node), "local_port")
+ rem_port_file = os.path.join(self.run_home(local_node), "remote_port")
+ ret_file = os.path.join(self.run_home(local_node), "ret_file")
+ cipher = self.get("cipher")
+ cipher_key = self.get("cipherKey")
+ bwlimit = self.get("bwLimit")
+ txqueuelen = self.get("txQueueLen")
+
+ rem_port = str(self.get_port_info(rm_endpoint,local_endpoint))
+
+ # Upload the remote port in a file
+ local_node.upload(rem_port, rem_port_file,
+ text = True,
+ overwrite = False)
+
+ connect_command = local_endpoint.udp_connect_command(
+ remote_ip, local_port_file, rem_port_file,
+ ret_file, cipher, cipher_key, bwlimit, txqueuelen)
+
+ self.connection_command(connect_command, local_node, rm_node)
+
+ # Wait for pid file to be generated
+ self._pid, self._ppid = local_node.wait_pid(self.run_home(local_node))
+
+ if not self._pid or not self._ppid:
+ (out, err), proc = local_node.check_errors(self.run_home(local_node))
+ # Out is what was written in the stderr file
+ if err:
+ msg = " Failed to start connection of the OVS Tunnel "
+ self.error(msg, out, err)
+ raise RuntimeError, msg
+ return
+
+ # Switch to Host
+ if self.check_switch_host_link and local_endpoint == self.endpoint1:
+ local_port_name = local_endpoint.get('port_name')
+ remote_port_num = self.wait_local_port(rm_node)
+ remote_ip = socket.gethostbyname(rm_node.get("hostname"))
+
+ # Switch to Switch
+ if not self.check_switch_host_link :
+ local_port_name, remote_ip, remote_port_num = self.get_port_info(local_endpoint, rm_endpoint)
+
+ connect_command = local_endpoint.switch_connect_command(
+ local_port_name, remote_ip, remote_port_num)
+
+ self.connection_command(connect_command, local_node, rm_node)
+
+ def connection_command(self, command, node_endpoint, rm_node_endpoint):
+ """ Execute the connection command on the node and check if the processus is
+ correctly running on the node.
+ """
+ shfile = os.path.join(self.app_home(node_endpoint), "sw_connect.sh")
+ node_endpoint.upload(command,
shfile,
text = True,
overwrite = False)
# Invoke connect script
+ out = err= ''
cmd = "bash %s" % shfile
- (out, err), proc = self.node.run(cmd, self.run_home(self.node),
+ (out, err), proc = node_endpoint.run(cmd, self.run_home(node_endpoint),
sudo = True,
stdout = "sw_stdout",
stderr = "sw_stderr")
raise RuntimeError, msg
# For debugging
- msg = "Connection on port %s configured" % local_port_name
- self.debug(msg)
+ msg = "Connection on port configured"
+ self.debug(msg)
def do_provision(self):
""" Provision the tunnel
"""
- # Create folders
- self._nodes = self.get_node(self.endpoint1)
- self.node.mkdir(self.run_home(self.node))
- self._nodes = self.get_node(self.endpoint2)
- self.node.mkdir(self.run_home(self.node))
-
- if self.check_endpoints:
- #Invoke connect script between switches
- self.switch_connect(self.endpoint1, self.endpoint2)
- self.switch_connect(self.endpoint2, self.endpoint1)
-
- else:
- # Invoke connect script between switch & host
- (self._pid, self._ppid) = self.udp_connect(self.endpoint2, self.endpoint1)
- self.sw_host_connect(self.endpoint1, self.endpoint2)
-
- super(OVSTunnel, self).do_provision()
+
+ #TODO : The order of the connection is important for now !
+ # Need to change the code of wait local port
+ self.connection(self.endpoint2, self.endpoint1)
+ self.connection(self.endpoint1, self.endpoint2)
- @property
- def tap(self):
- rclass = ResourceFactory.get_resource_type(PlanetlabTap.get_rtype())
- for guid in self.connections:
- rm = self.ec.get_resource(guid)
- if isinstance(rm, rclass):
- return rm
+ def configure_route(self):
+ """ Configure the route for the tap device
- @property
- def ovswitch(self):
- for guid in self.connections:
- rm_port = self.ec.get_resource(guid)
- if hasattr(rm_port, "create_port"):
- rm_list = rm_port.get_connected(OVSWitch.get_rtype())
- if rm_list:
- return rm_list[0]
+ .. note : In case of a conection between a switch and a host, a route
+ was missing on the node with the Tap Device. This method create
+ the missing route.
+ """
- def configure(self):
- if not self.check_endpoints:
+ if self.check_switch_host_link:
self._vroute = self.ec.register_resource("PlanetlabVroute")
self.ec.set(self._vroute, "action", "add")
self.ec.set(self._vroute, "network", self.get("network"))
self.ec.register_connection(self._vroute, self.tap.guid)
- # schedule deploy
self.ec.deploy(guids=[self._vroute], group = self.deployment_group)
-
def do_deploy(self):
+ """ Deploy the tunnel after the endpoint get ready
+ """
if (not self.endpoint1 or self.endpoint1.state < ResourceState.READY) or \
(not self.endpoint2 or self.endpoint2.state < ResourceState.READY):
self.ec.schedule(reschedule_delay, self.deploy)
self.do_discover()
self.do_provision()
- self.configure()
-
- super(OVSTunnel, self).do_deploy()
+ self.configure_route()
+
+ # Cannot call the deploy of the linux application
+ # because of a log error.
+ # Need to investigate if it is right that the tunnel
+ # inherits from the linux application
+ # super(OVSTunnel, self).do_deploy()
+ self.set_ready()
def do_release(self):
- """ Release the udp_tunnel on endpoint2.
- On endpoint1 means nothing special.
+ """ Release the tunnel by releasing the Tap Device if exists
"""
- if not self.check_endpoints:
- # Kill the TAP devices
+ if self.check_switch_host_link:
# TODO: Make more generic Release method of PLTAP
+ tap_node = self.get_node(self.endpoint2)
if self._pid and self._ppid:
- self._nodes = self.get_node(self.endpoint2)
- (out, err), proc = self.node.kill(self._pid,
+ (out, err), proc = tap_node.kill(self._pid,
self._ppid, sudo = True)
+
if err or proc.poll():
- # check if execution errors occurred
msg = " Failed to delete TAP device"
- self.error(msg, err, err)
+ self.error(msg, out, err)
super(OVSTunnel, self).do_release()
@classmethod
def _register_attributes(cls):
ip4 = Attribute("ip4", "IPv4 Address",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
mac = Attribute("mac", "MAC Address",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
prefix4 = Attribute("prefix4", "IPv4 network prefix",
type = Types.Integer,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
mtu = Attribute("mtu", "Maximum transmition unit for device",
type = Types.Integer)
devname = Attribute("deviceName",
"Name of the network interface (e.g. eth0, wlan0, etc)",
- flags = Flags.ReadOnly)
+ flags = Flags.NoWrite)
up = Attribute("up", "Link up",
type = Types.Bool)
snat = Attribute("snat", "Set SNAT=1",
type = Types.Bool,
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
pointopoint = Attribute("pointopoint", "Peer IP address",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
tear_down = Attribute("tearDown", "Bash script to be executed before " + \
"releasing the resource",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cls._register_attribute(ip4)
cls._register_attribute(mac)
self.do_discover()
self.do_provision()
- self.debug("----- READY ---- ")
self.set_ready()
def do_start(self):
if_name = None
delay = 1.0
- for i in xrange(10):
+ for i in xrange(20):
(out, err), proc = self.node.check_output(self.run_home, "if_name")
if out: