X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fresources%2Fplanetlab%2Fopenvswitch%2Fovs.py;h=171750fefdf3acd36e541c33a98c1c9c979853c9;hb=23d041fe2f0d9badf6d637009e2d42a4794325c1;hp=bffc61ef85c44ac45238ea582542bcd45bff85c9;hpb=4b0e922489532434f0968647886021542b77cece;p=nepi.git diff --git a/src/nepi/resources/planetlab/openvswitch/ovs.py b/src/nepi/resources/planetlab/openvswitch/ovs.py index bffc61ef..171750fe 100644 --- a/src/nepi/resources/planetlab/openvswitch/ovs.py +++ b/src/nepi/resources/planetlab/openvswitch/ovs.py @@ -15,40 +15,49 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -# Author: Alina Quereilhac +# Authors: Alina Quereilhac # Alexandros Kouvakas +# Julien Tribino -from nepi.execution.resource import ResourceManager, clsinit_copy, ResourceState +from nepi.execution.resource import ResourceManager, clsinit_copy, \ + ResourceState from nepi.execution.attribute import Attribute, Flags from nepi.resources.planetlab.node import PlanetlabNode from nepi.resources.linux.application import LinuxApplication import os -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 = "planetlab::OVSSwitch" _help = "Runs an OpenVSwitch on a PlanetLab host" - _backend = "planetlab" + _platform = "planetlab" - _authorized_connections = ["PlanetlabNode", "OVSPort", "LinuxNode"] + _authorized_connections = ["planetlab::Node", "planetla::OVSPort", "linux::Node"] @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) @@ -63,18 +72,21 @@ class OVSWitch(LinuxApplication): :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 = self.get_connected(PlanetlabNode.rtype()) + """ 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) @@ -83,47 +95,60 @@ class OVSWitch(LinuxApplication): 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.rtype() in self._authorized_connections: -# msg = "Connection between %s %s and %s %s accepted" % \ -# (self.rtype(), self._guid, rm.rtype(), guid) -# self.debug(msg) -# return True -# msg = "Connection between %s %s and %s %s refused" % \ -# (self.rtype(), self._guid, rm.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. + """ - def provision(self): # create home dir for ovs self.node.mkdir(self.ovs_home) # create dir for ovs checks self.node.mkdir(self.ovs_checks) + + 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(self.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 = "" @@ -136,43 +161,21 @@ class OVSWitch(LinuxApplication): stderr = "check_cmd_stderr") (out, err), proc = self.node.check_output(self.ovs_checks, 'check_cmd_exitcode') + if out != "0\n": msg = "Command sliver-ovs does not exist on the VM" self.debug(msg) raise RuntimeError, msg - msg = "Command sliver-ovs exists" - self.debug(msg) - def 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) - - else: - try: - self.discover() - self.provision() - self.check_sliver_ovs() - self.servers_on() - self.create_bridge() - self.assign_contr() - self.ovs_status() - except: - self._state = ResourceState.FAILED - raise - - self._state = ResourceState.READY + msg = "Command sliver-ovs exists" + 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", @@ -182,13 +185,13 @@ class OVSWitch(LinuxApplication): 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.debug("Servers have not started") + 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, @@ -198,78 +201,76 @@ class OVSWitch(LinuxApplication): 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.debug("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 self.get("bridge_name") and self.get("virtual_ip_pref"): - 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) - out = err = "" - (out, err), proc = self.node.run_and_wait(cmd, self.ovs_checks, - shfile = "create_br.sh", - pidfile = "create_br_pidfile", - ecodefile = "create_br_exitcode", - 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") - raise RuntimeError, msg - self.info("Bridge %s created" % bridge_name) - - else: + 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 - def assign_contr(self): + cmd = "sliver-ovs create-bridge '%s' '%s'" %\ + (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", + pidfile = "create_br_pidfile", + ecodefile = "create_br_exitcode", + 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.error(msg) + raise RuntimeError, msg + + 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, @@ -277,46 +278,44 @@ class OVSWitch(LinuxApplication): 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 start(self): - """ Start the RM. It means nothing special for - ovswitch for now. - """ - pass + def do_release(self): + """ Delete the bridge and close the server. - def stop(self): - """ Stop the RM.It means nothing - for ovswitch for now. - """ - pass + .. note : It need to wait for the others RM (OVSPort and OVSTunnel) + to be released before releasing itself - def release(self): - """ Delete the bridge and - close the servers """ - # 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.rtype()) + rms = self.get_connected(OVSPort.get_rtype()) - if rm[0].state < ResourceState.FINISHED: - self.ec.schedule(reschedule_delay, self.release) - return + for rm in rms : + if rm.state < ResourceState.RELEASED: + self.ec.schedule(self.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.fail() self.error(msg, out, err) raise RuntimeError, msg - - self._state = ResourceState.RELEASED - + + super(OVSSwitch, self).do_release() +