applied the except and raise fixers to the master branch to close the gap with py3
[nepi.git] / src / nepi / resources / linux / application.py
index af6ae34..1574f63 100644 (file)
@@ -3,9 +3,8 @@
 #    Copyright (C) 2013 INRIA
 #
 #    This program is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
+#    it under the terms of the GNU General Public License version 2 as
+#    published by the Free Software Foundation;
 #
 #    This program is distributed in the hope that it will be useful,
 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,7 +19,7 @@
 from nepi.execution.attribute import Attribute, Flags, Types
 from nepi.execution.trace import Trace, TraceAttr
 from nepi.execution.resource import ResourceManager, clsinit_copy, \
-        ResourceState, reschedule_delay
+        ResourceState
 from nepi.resources.linux.node import LinuxNode
 from nepi.util.sshfuncs import ProcStatus
 from nepi.util.timefuncs import tnow, tdiffsec
@@ -81,9 +80,9 @@ class LinuxApplication(ResourceManager):
 
     """
 
-    _rtype = "LinuxApplication"
+    _rtype = "linux::Application"
     _help = "Runs an application on a Linux host with a BASH command "
-    _backend_type = "linux"
+    _platform = "linux"
 
     @classmethod
     def _register_attributes(cls):
@@ -173,7 +172,9 @@ class LinuxApplication(ResourceManager):
         super(LinuxApplication, self).__init__(ec, guid)
         self._pid = None
         self._ppid = None
+        self._node = None
         self._home = "app-%s" % self.guid
+
         # whether the command should run in foreground attached
         # to a terminal
         self._in_foreground = False
@@ -194,9 +195,16 @@ class LinuxApplication(ResourceManager):
 
     @property
     def node(self):
-        node = self.get_connected(LinuxNode.get_rtype())
-        if node: return node[0]
-        return None
+        if not self._node:
+            node = self.get_connected(LinuxNode.get_rtype())
+            if not node: 
+                msg = "Application %s guid %d NOT connected to Node" % (
+                        self._rtype, self.guid)
+                raise RuntimeError(msg)
+
+            self._node = node[0]
+
+        return self._node
 
     @property
     def app_home(self):
@@ -286,7 +294,8 @@ class LinuxApplication(ResourceManager):
                 for line in out.strip().split("\n"):
                     parts = line.strip().split(" ")
                     procs[parts[0]] = parts[1]
-                pickle.dump(procs, open("/tmp/save.proc", "wb"))
+                with open("/tmp/save.proc", "wb") as pickle_file:
+                    pickle.dump(procs, pickle_file)
             
         # create run dir for application
         self.node.mkdir(self.run_home)
@@ -346,7 +355,6 @@ class LinuxApplication(ResourceManager):
 
             # replace application specific paths in the command
             command = self.replace_paths(command)
-            
             # replace application specific paths in the environment
             env = self.get("env")
             env = env and self.replace_paths(env)
@@ -360,6 +368,13 @@ class LinuxApplication(ResourceManager):
 
     def execute_deploy_command(self, command, prefix="deploy"):
         if command:
+            # replace application specific paths in the command
+            command = self.replace_paths(command)
+            
+            # replace application specific paths in the environment
+            env = self.get("env")
+            env = env and self.replace_paths(env)
+
             # Upload the command to a bash script and run it
             # in background ( but wait until the command has
             # finished to continue )
@@ -510,8 +525,8 @@ class LinuxApplication(ResourceManager):
         # 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)
+            self.debug("---- RESCHEDULING DEPLOY ---- node state %s " % self.node.state)
+            self.ec.schedule(self.reschedule_delay, self.deploy)
         else:
             command = self.get("command") or ""
             self.info("Deploying command '%s' " % command)
@@ -558,7 +573,7 @@ class LinuxApplication(ResourceManager):
 
         if self._proc.poll():
             self.error(msg, out, err)
-            raise RuntimeError, msg
+            raise RuntimeError(msg)
 
     def _run_in_background(self):
         command = self.get("command")
@@ -587,7 +602,7 @@ class LinuxApplication(ResourceManager):
         
         if proc.poll():
             self.error(msg, out, err)
-            raise RuntimeError, msg
+            raise RuntimeError(msg)
     
         # Wait for pid file to be generated
         pid, ppid = self.node.wait_pid(self.run_home)
@@ -604,7 +619,7 @@ class LinuxApplication(ResourceManager):
             if err:
                 msg = " Failed to start command '%s' " % command
                 self.error(msg, out, err)
-                raise RuntimeError, msg
+                raise RuntimeError(msg)
     
     def do_stop(self):
         """ Stops application execution
@@ -628,11 +643,13 @@ class LinuxApplication(ResourceManager):
                     (out, err), proc = self.node.kill(self.pid, self.ppid,
                             sudo = self._sudo_kill)
 
+                    """
                     # TODO: check if execution errors occurred
                     if (proc and proc.poll()) or err:
                         msg = " Failed to STOP command '%s' " % self.get("command")
                         self.error(msg, out, err)
-        
+                    """
+
             super(LinuxApplication, self).do_stop()
 
     def do_release(self):
@@ -702,38 +719,49 @@ class LinuxApplication(ResourceManager):
         return self._state
 
     def execute_command(self, command, 
-            env = None,
-            sudo = False,
-            forward_x11 = False,
-            blocking = False):
+            env=None,
+            sudo=False,
+            tty=False,
+            forward_x11=False,
+            blocking=False):
 
         environ = ""
         if env:
-            environ = self.node.format_environment(env, inline = True)
+            environ = self.node.format_environment(env, inline=True)
         command = environ + command
         command = self.replace_paths(command)
 
         return self.node.execute(command,
-                sudo = sudo,
-                forward_x11 = forward_x11,
-                blocking = blocking)
+                sudo=sudo,
+                tty=tty,
+                forward_x11=forward_x11,
+                blocking=blocking)
 
-    def replace_paths(self, command):
+    def replace_paths(self, command, node=None, app_home=None, run_home=None):
         """
         Replace all special path tags with shell-escaped actual paths.
         """
+        if not node:
+            node=self.node
+
+        if not app_home:
+            app_home=self.app_home
+
+        if not run_home:
+            run_home = self.run_home
+
         return ( command
-            .replace("${USR}", self.node.usr_dir)
-            .replace("${LIB}", self.node.lib_dir)
-            .replace("${BIN}", self.node.bin_dir)
-            .replace("${SRC}", self.node.src_dir)
-            .replace("${SHARE}", self.node.share_dir)
-            .replace("${EXP}", self.node.exp_dir)
-            .replace("${EXP_HOME}", self.node.exp_home)
-            .replace("${APP_HOME}", self.app_home)
-            .replace("${RUN_HOME}", self.run_home)
-            .replace("${NODE_HOME}", self.node.node_home)
-            .replace("${HOME}", self.node.home_dir)
+            .replace("${USR}", node.usr_dir)
+            .replace("${LIB}", node.lib_dir)
+            .replace("${BIN}", node.bin_dir)
+            .replace("${SRC}", node.src_dir)
+            .replace("${SHARE}", node.share_dir)
+            .replace("${EXP}", node.exp_dir)
+            .replace("${EXP_HOME}", node.exp_home)
+            .replace("${APP_HOME}", app_home)
+            .replace("${RUN_HOME}", run_home)
+            .replace("${NODE_HOME}", node.node_home)
+            .replace("${HOME}", node.home_dir)
             )
 
     def valid_connection(self, guid):