Replacing _backend for _platform class attribute in ResourceManager
[nepi.git] / src / nepi / resources / planetlab / openvswitch / ovs.py
index bffc61e..171750f 100644 (file)
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 #    You should have received a copy of the GNU General Public License
 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
-# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
+# Authors: Alina Quereilhac <alina.quereilhac@inria.fr>
 #         Alexandros Kouvakas <alexandros.kouvakas@inria.fr>
 #         Alexandros Kouvakas <alexandros.kouvakas@inria.fr>
+#         Julien Tribino <julien.tribino@inria.fr>
 
 
 
 
-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
 
 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                    
 @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"
     _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):
 
     @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",
 
         """
         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",
         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",
         controller_ip = Attribute("controller_ip", "IP of the controller",
-                flags = Flags.ExecReadOnly)
+                flags = Flags.Design)  
         controller_port = Attribute("controller_port", "Port of the controller",
         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)
 
         cls._register_attribute(bridge_name)
         cls._register_attribute(virtual_ip_pref)
@@ -63,18 +72,21 @@ class OVSWitch(LinuxApplication):
         :type guid: int
     
         """
         :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):
         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
 
         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)
     @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)
 
     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)
         # 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):  
 
     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 = ""
 
         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')
                 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
         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):
 
     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",
         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")
                 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":
         (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    
                                
             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, 
         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")
                 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')
         (out, err), proc = self.node.check_output(self.ovs_checks, 'status_srv_exitcode')
+        
         if out != "0\n":
         if out != "0\n":
-            self.debug("Servers are not running")
+            msg = "Servers are not running"
+            self.error(msg)
             raise RuntimeError, 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):
 
     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
         # 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)
             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
 
             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
         """
         """ 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):
            
     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,
         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')
                 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
         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 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)
         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():
         
         if proc.poll():
-            self.fail()
             self.error(msg, out, err)
             raise RuntimeError, msg
             self.error(msg, out, err)
             raise RuntimeError, msg
-     
-        self._state = ResourceState.RELEASED
-        
+
+        super(OVSSwitch, self).do_release()
+