Salome HOME
- Fixes for BatchManager_Local
authorbarate <barate>
Fri, 18 Jan 2013 13:30:47 +0000 (13:30 +0000)
committerbarate <barate>
Fri, 18 Jan 2013 13:30:47 +0000 (13:30 +0000)
- Fixes for Windows

20 files changed:
src/CCC/BatchManager_CCC.cxx
src/Core/BatchManager.cxx
src/Core/CommunicationProtocol.cxx
src/Core/CommunicationProtocol.hxx
src/Core/CommunicationProtocolRSH.cxx
src/Core/CommunicationProtocolRSH.hxx
src/Core/CommunicationProtocolSH.cxx
src/Core/CommunicationProtocolSH.hxx
src/Core/CommunicationProtocolSSH.cxx
src/Core/CommunicationProtocolSSH.hxx
src/Core/Defines.hxx
src/Core/Test/batchtest.conf
src/Core/Utils.cxx
src/Core/Utils.hxx
src/Local/BatchManager_Local.cxx
src/Local/BatchManager_Local.hxx
src/Local/Test/CMakeLists.txt
src/Local/Test/Test_Local_RSH.cxx [deleted file]
src/Local/Test/Test_Local_SSH.cxx [deleted file]
src/SGE/BatchManager_SGE.cxx

index 1703e5b2dc81799a1c148f978f355dcff70a4fb4..715a51fc98ce6ab4124d9f4308a8b3435b57f4e0 100644 (file)
@@ -36,7 +36,6 @@
 #include <fstream>
 #include <sstream>
 #include <string>
-#include <sys/stat.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -256,7 +255,7 @@ namespace Batch {
     tempOutputFile.flush();
     tempOutputFile.close();
 
-    BATCH_CHMOD(TmpFileName.c_str(), 0x1ED);
+    Utils::chmod(TmpFileName.c_str(), 0x1ED);
     cerr << "Batch script file generated is: " << TmpFileName.c_str() << endl;
 
     int status = _protocol.copyFile(TmpFileName, "", "",
index 233ee46eedbc35d6c6c7797598f2d27946bbe116..c369f56c3965e81b8e9d7e2ef3766c09ed14a463 100644 (file)
 #include <iostream>
 #include <sstream>
 #include <string>
-#ifdef WIN32
-# include<winsock2.h>
-#else
-#include <unistd.h>
-# include <netdb.h>
-#endif
 
 #include "Constants.hxx"
 #include "Job.hxx"
 #include "JobId.hxx"
 #include "JobInfo.hxx"
-#include "InvalidArgumentException.hxx"
 #include "FactBatchManager.hxx"
 #include "BatchManager.hxx"
 #include "Utils.hxx"
 #include "NotYetImplementedException.hxx"
 
-#ifdef WIN32
-#define sleep(seconds) Sleep((seconds)*1000)
-#endif
-
 using namespace std;
 
 namespace Batch {
@@ -162,7 +151,7 @@ namespace Batch {
     cout << "State is \"" << state << "\"";
     while (!timeoutReached && state != FINISHED && state != FAILED) {
       cout << ", sleeping " << sleeptime << "s..." << endl;
-      sleep(sleeptime);
+      Utils::sleep(sleeptime);
       time += sleeptime;
       timeoutReached = (testTimeout && time >= timeout);
       sleeptime *= 2;
@@ -209,22 +198,24 @@ namespace Batch {
       }
 
 #ifdef WIN32
-      // On Windows, we make the remote file executable afterward because
-      // pscp does not preserve access permissions on files
-
-      string remoteExec = string(params[EXECUTABLE]);
-      remoteExec = remoteExec.substr(remoteExec.rfind("\\") + 1, remoteExec.length());
-      remoteExec = string(params[WORKDIR]) + "/" + executable;
-
-      string subCommand = string("chmod u+x ") + remoteExec;
-      string command = _protocol.getExecCommand(subCommand, _hostname, _username);
-      cerr << command.c_str() << endl;
-      status = system(command.c_str());
-      if (status) {
-        std::ostringstream oss;
-        oss << "Cannot change permissions of file " << remoteExec << " on host " << _hostname;
-        oss << ". Return status is " << status;
-        throw RunTimeException(oss.str());
+      if (_protocol.getType() != SH) {
+        // On Windows, we make the remote file executable afterward because
+        // pscp does not preserve access permissions on files
+
+        string remoteExec = string(params[EXECUTABLE]);
+        remoteExec = remoteExec.substr(remoteExec.rfind("/") + 1, remoteExec.length());
+        remoteExec = string(params[WORKDIR]) + "/" + remoteExec;
+
+        string subCommand = string("chmod u+x ") + remoteExec;
+        string command = _protocol.getExecCommand(subCommand, _hostname, _username);
+        cerr << command.c_str() << endl;
+        status = system(command.c_str());
+        if (status) {
+          std::ostringstream oss;
+          oss << "Cannot change permissions of file " << remoteExec << " on host " << _hostname;
+          oss << ". Return status is " << status;
+          throw RunTimeException(oss.str());
+        }
       }
 #endif
     }
index 416b1ee83b1567cb6f7b3dba546c55762544d75b..b365bbac946c3c03edcc4a441bda64b887c63a28 100644 (file)
@@ -49,6 +49,11 @@ using namespace std;
 
 namespace Batch {
 
+  CommunicationProtocol::CommunicationProtocol(CommunicationProtocolType type)
+  : _type(type)
+  {
+  }
+
   CommunicationProtocol::~CommunicationProtocol()
   {
   }
@@ -164,4 +169,9 @@ namespace Batch {
     return commandStr;
   }
 
+  CommunicationProtocolType CommunicationProtocol::getType() const
+  {
+    return _type;
+  }
+
 }
index afd508ed3a57b93aaf5c363fab2a4fc6aeb11344..43c31fa9d963a8dca676cb06ac997cb7dbcae685 100644 (file)
@@ -68,8 +68,12 @@ namespace Batch {
                               const std::string & host,
                               const std::string & user) const;
 
+    CommunicationProtocolType getType() const;
+
   protected:
 
+    CommunicationProtocol(CommunicationProtocolType type = SH);
+
     virtual std::vector<std::string> getCopyCommandArgs(const std::string & sourcePath,
                                                         const std::string & sourceHost,
                                                         const std::string & sourceUser,
@@ -83,6 +87,8 @@ namespace Batch {
 
     std::string commandStringFromArgs(const std::vector<std::string> & args) const;
 
+    CommunicationProtocolType _type;
+
   };
 
 }
index bb7a308813ac7e0100d8d18ba79df238adbb6e90..59caf2d28789cab4b565557ea7e4b6e4ebcc2e55 100644 (file)
@@ -41,6 +41,11 @@ using namespace std;
 
 namespace Batch {
 
+  CommunicationProtocolRSH::CommunicationProtocolRSH()
+  : CommunicationProtocol(RSH)
+  {
+  }
+
   vector<string> CommunicationProtocolRSH::getExecCommandArgs(const string & subCommand,
                                                               const string & host,
                                                               const string & user) const
index 6a32d08d7e9f2c00dd2f656b017a0c323acbae0f..c62fc9a0577c753845ce61a9ff45a2f235873104 100644 (file)
@@ -39,6 +39,8 @@ namespace Batch {
 
   class BATCH_EXPORT CommunicationProtocolRSH : public CommunicationProtocol
   {
+    friend class CommunicationProtocol;
+
   public:
     std::vector<std::string> getExecCommandArgs(const std::string & subCommand,
                                                 const std::string & host,
@@ -62,12 +64,18 @@ namespace Batch {
                  const std::string & destinationHost,
                  const std::string & destinationUser) const;
 
+#endif
+
   protected:
 
+#ifdef WIN32
+
     char getDriveLetter(const std::string & path, std::string * pathWithoutDrive = NULL) const;
 
 #endif
 
+    CommunicationProtocolRSH();
+
   };
 
 }
index 546e97ce540533f917542ee7ec1320b176db1151..89968d9588b383dcaef1cfac4e9ad12b8f3013ae 100644 (file)
 #include <config.h>
 
 #include "CommunicationProtocolSH.hxx"
+#include "Utils.hxx"
 
 using namespace std;
 
 namespace Batch {
 
-  // Simple method to fix path strings depending on the platform. On Windows, it will replace
-  // forward slashes '/' by backslashes '\'. On Unix, the path is just copied without change.
-  string CommunicationProtocolSH::fixPath(const string & path) const
+  CommunicationProtocolSH::CommunicationProtocolSH()
+  : CommunicationProtocol(SH)
   {
-    string fixedPath = path;
-  #ifdef WIN32
-    for (unsigned int i=0 ; i<fixedPath.size() ; i++) {
-      if (fixedPath[i] == '/') fixedPath[i] = '\\';
-    }
-  #endif
-    return fixedPath;
   }
 
   vector<string> CommunicationProtocolSH::getExecCommandArgs(const string & subCommand,
@@ -53,7 +46,7 @@ namespace Batch {
   {
     vector<string> cmd;
 
-    cmd.push_back(fixPath(SH_COMMAND));
+    cmd.push_back(Utils::fixPath(SH_COMMAND));
 
 #ifdef WIN32
     cmd.push_back("/c");
@@ -61,7 +54,7 @@ namespace Batch {
     cmd.push_back("-c");
 #endif
 
-    cmd.push_back(fixPath(subCommand));
+    cmd.push_back(Utils::fixPath(subCommand));
 
     return cmd;
   }
@@ -78,14 +71,14 @@ namespace Batch {
 #ifndef WIN32
     cmd.push_back("-r");
 #endif
-    cmd.push_back(fixPath(sourcePath));
-    cmd.push_back(fixPath(destinationPath));
+    cmd.push_back(Utils::fixPath(sourcePath));
+    cmd.push_back(Utils::fixPath(destinationPath));
     return cmd;
   }
 
   string CommunicationProtocolSH::getRemoveSubCommand(const string & path) const
   {
-    return string(RM_COMMAND) + " " + fixPath(path);
+    return string(RM_COMMAND) + " " + Utils::fixPath(path);
   }
 
   string CommunicationProtocolSH::getMakeDirectorySubCommand(const string & path) const
@@ -94,7 +87,7 @@ namespace Batch {
 #ifndef WIN32
     subCommand += " -p";
 #endif
-    subCommand += " " + fixPath(path);
+    subCommand += " " + Utils::fixPath(path);
     return subCommand;
   }
 
index 778d5f9267ed597dea1d9884523ec3df259bbe46..b6b9a782977fd07f5e63d20d685c070a4e73ff0c 100644 (file)
@@ -39,6 +39,8 @@ namespace Batch {
 
   class BATCH_EXPORT CommunicationProtocolSH : public CommunicationProtocol
   {
+    friend class CommunicationProtocol;
+
   public:
     std::vector<std::string> getExecCommandArgs(const std::string & subCommand,
                                                 const std::string & host,
@@ -53,12 +55,12 @@ namespace Batch {
 
   protected:
 
+    CommunicationProtocolSH();
+
     std::string getRemoveSubCommand(const std::string & path) const;
 
     std::string getMakeDirectorySubCommand(const std::string & path) const;
 
-    std::string fixPath(const std::string & path) const;
-
   };
 
 }
index 3a40db19ec360c82b9b7935453e674e61d97a8ed..b6883a48ec937eb299c80e6de90f99a1fdff8838 100644 (file)
@@ -34,6 +34,11 @@ using namespace std;
 
 namespace Batch {
 
+  CommunicationProtocolSSH::CommunicationProtocolSSH()
+  : CommunicationProtocol(SSH)
+  {
+  }
+
   vector<string> CommunicationProtocolSSH::getExecCommandArgs(const string & subCommand,
                                                               const string & host,
                                                               const string & user) const
index 54145ce98d1359ee0c087fcae891e99b427be48c..3aadcceb462f5750877bc760a775cb4cb8d13d01 100644 (file)
@@ -39,6 +39,8 @@ namespace Batch {
 
   class BATCH_EXPORT CommunicationProtocolSSH : public CommunicationProtocol
   {
+    friend class CommunicationProtocol;
+
   public:
     std::vector<std::string> getExecCommandArgs(const std::string & subCommand,
                                                 const std::string & host,
@@ -53,6 +55,8 @@ namespace Batch {
 
   protected:
 
+    CommunicationProtocolSSH();
+
   };
 
 }
index 1a22c8d0ca58578a761cafdc2f71433c454312ef..0cecc1a5be55298c82fbfbbb720328b0e3653836 100644 (file)
@@ -27,7 +27,7 @@
 #define _BATCH_Defines_HXX_
 
 #ifdef WIN32
-# if defined EXPORTS
+# if defined batch_EXPORTS
 #  define BATCH_EXPORT __declspec( dllexport )
 # else
 #  define BATCH_EXPORT __declspec( dllimport )
 # define BATCH_EXPORT
 #endif
 
-#ifdef WIN32
-#define BATCH_CHMOD(name, mode) _chmod(name, mode)
-#else
-#define BATCH_CHMOD(name, mode) chmod(name, mode)
-#endif
-
 #endif
index 9deb2de8a884d8e62f9a7cd1bba4d64cad86a8e6..7ff4583eaa2145c653aade2082acf69665317953 100644 (file)
@@ -9,17 +9,10 @@ TEST_LOCAL_SH_WORK_DIR = "/tmp"               # Work directory for local SH Batc
 TEST_LOCAL_SH_TIMEOUT = 2                     # Execution timeout (in seconds) for local SH Batch test
 TEST_LOCAL_SH_FINALIZATION_TIME = 2           # Finalization time (in seconds) for local SH Batch test
 
-TEST_LOCAL_RSH_EXECUTION_HOST = "localhost"   # Execution host for RSH Batch test
-TEST_LOCAL_RSH_USER = "username"              # User name on the execution host for RSH Batch test
-TEST_LOCAL_RSH_WORK_DIR = "/tmp"              # Work directory for RSH Batch test
-TEST_LOCAL_RSH_TIMEOUT = 10                   # Execution timeout (in seconds) for local RSH Batch test
-TEST_LOCAL_RSH_FINALIZATION_TIME = 5          # Finalization time (in seconds) for local RSH Batch test
-
-TEST_LOCAL_SSH_EXECUTION_HOST = "localhost"   # Execution host for SSH Batch test
-TEST_LOCAL_SSH_USER = "username"              # User name on the execution host for SSH Batch test
-TEST_LOCAL_SSH_WORK_DIR = "/tmp"              # Work directory for SSH Batch test
-TEST_LOCAL_SSH_TIMEOUT = 10                   # Execution timeout (in seconds) for local SSH Batch test
-TEST_LOCAL_SSH_FINALIZATION_TIME = 5          # Finalization time (in seconds) for local SSH Batch test
+TEST_LOCAL_HOST = "localhost"                 # Execution host for LOCAL Batch test
+TEST_LOCAL_USER = "username"                  # User name on the execution host for LOCAL Batch test
+TEST_LOCAL_WORKDIR = "/tmp"                   # Work directory for LOCAL Batch test
+TEST_LOCAL_TIMEOUT = 10                       # Execution timeout (in seconds) for LOCAL Batch test
 
 TEST_EPBS_HOST = "localhost"                  # PBS server host
 TEST_EPBS_USER = "username"                   # Login for the PBS server
index a75a90ee88c1d8fd9d8fe11e2fbf0fa1689c64d3..623bb600f4dc900db5f95b1e0e29cb5739f0f435 100644 (file)
 
 #include <cstdlib>
 #include <cstdio>
-#include <unistd.h>
 #include <iostream>
 #include <fstream>
 
+#ifdef WIN32
+#include <Windows.h>
+#include <time.h>
+#include <io.h>
+#else
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+
 #include <config.h>
 #include "Utils.hxx"
 #include "RunTimeException.hxx"
@@ -70,6 +78,11 @@ bool Utils::isAbsolutePath(const string & path)
 {
   if (path.size() == 0)
     return false;
+#ifdef WIN32
+  // On Windows, absolute paths may begin with something like "C:"
+  if (path[1] == ':')
+    return true;
+#endif
   return path[0] == '/';
 }
 
@@ -95,7 +108,7 @@ string Utils::createAndOpenTemporaryFile(const string & prefix, ofstream & outpu
   do {
     sprintf(randstr, "%06d", rand() % 1000000);
     fileName.replace(fileName.size()-6, 6, randstr);
-  } while (EXISTS(fileName.c_str()));
+  } while (_access_s(fileName.c_str(), 0) == 0);
 
   // Open the file as binary to avoid problems with Windows newlines
   outputStream.open(fileName.c_str(), ios_base::binary | ios_base::out);
@@ -125,4 +138,33 @@ string Utils::createAndOpenTemporaryFile(const string & prefix, ofstream & outpu
   return fileName;
 }
 
+int Utils::chmod(const char *path, int mode)
+{
+#ifdef WIN32
+  return _chmod(path, mode);
+#else
+  return ::chmod(path, mode);
+#endif
+}
+
+void Utils::sleep(unsigned int seconds)
+{
+#ifdef WIN32
+  Sleep((seconds)*1000);
+#else
+  ::sleep(seconds);
+#endif
+}
+
+string Utils::fixPath(const string & path)
+{
+  string fixedPath = path;
+#ifdef WIN32
+  for (unsigned int i=0 ; i<fixedPath.size() ; i++) {
+    if (fixedPath[i] == '/') fixedPath[i] = '\\';
+  }
+#endif
+  return fixedPath;
+}
+
 }
index 0c6f51587949be8a486b0c67d7dfcc208fb3dd2a..f5fb5d8de136709937cdc958642eeec925c85ace 100644 (file)
@@ -63,6 +63,22 @@ public:
   static std::string createAndOpenTemporaryFile(const std::string & prefix,
                                                 std::ofstream & outputStream);
 
+  /**
+   * Change permissions of a file
+   */
+  static int chmod(const char *path, int mode);
+
+  /**
+   * Sleep for the number of specified seconds
+   */
+  static void sleep(unsigned int seconds);
+
+  /**
+   * Simple method to fix path strings depending on the platform. On Windows, it will replace
+   * forward slashes '/' by backslashes '\'. On Unix, the path is just copied without change.
+   */
+  static std::string fixPath(const std::string & path);
+
 private:
 
   // No instanciation possible as this class provides only static methods
index fc44883966e8aa10c61b561572f27f42f560edec..edf8182cc13342194cceb0f7aab699e0b8016f10 100644 (file)
@@ -55,6 +55,7 @@
 #include "IOMutex.hxx"
 #include "BatchManager_Local.hxx"
 #include "RunTimeException.hxx"
+#include "Utils.hxx"
 
 using namespace std;
 
@@ -250,53 +251,143 @@ namespace Batch {
     return running;
   }
 
-
-  vector<string> BatchManager_Local::exec_command(const Parametre & param) const
+  string BatchManager_Local::ThreadAdapter::buildCommandFile(const Job_Local & job)
   {
-    ostringstream exec_sub_cmd;
+    Parametre param = job.getParametre();
+
+    // Mandatory parameters
+    string workDir = "";
+    if (param.find(WORKDIR) != param.end())
+      workDir = param[WORKDIR].str();
+    else
+      throw RunTimeException("param[WORKDIR] is not defined. Please define it, cannot submit this job.");
+    string fileToExecute = "";
+    if (param.find(EXECUTABLE) != param.end())
+      fileToExecute = param[EXECUTABLE].str();
+    else
+      throw RunTimeException("param[EXECUTABLE] is not defined. Please define it, cannot submit this job.");
+
+    string::size_type p1 = fileToExecute.find_last_of("/");
+    string::size_type p2 = fileToExecute.find_last_of(".");
+    string rootNameToExecute = fileToExecute.substr(p1+1,p2-p1-1);
+    string fileNameToExecute = fileToExecute.substr(p1+1);
+    string remotePath = workDir + "/" + rootNameToExecute + "_launch_job";
+
+    // Create batch submit file
+    ofstream tempOutputFile;
+    string tmpFileName = Utils::createAndOpenTemporaryFile("launch-job", tempOutputFile);
 
 #ifdef WIN32
-    char drive[_MAX_DRIVE];
-    _splitpath(string(param[WORKDIR]).c_str(), drive, NULL, NULL, NULL);
-    if (strlen(drive) > 0) exec_sub_cmd << drive << " && ";
+    if (_bm._protocol.getType() == SH) {
+      char drive[_MAX_DRIVE];
+      _splitpath(workDir.c_str(), drive, NULL, NULL, NULL);
+      if (strlen(drive) > 0) tempOutputFile << drive << endl;
+      tempOutputFile << "cd " << Utils::fixPath(workDir) << endl;
+      // Launch the executable
+      tempOutputFile << fileNameToExecute;
+      if (param.find(ARGUMENTS) != param.end()) {
+        Versatile V = param[ARGUMENTS];
+        for(Versatile::const_iterator it=V.begin(); it!=V.end(); it++) {
+          StringType argt = * static_cast<StringType *>(*it);
+          string     arg  = argt;
+          tempOutputFile << " " << arg;
+        }
+      }
+      remotePath += ".bat";
+    } else {
 #endif
 
-    string fileToExecute = param[EXECUTABLE].str();
-    string::size_type p1 = fileToExecute.find_last_of("/");
-    string fileNameToExecute = fileToExecute.substr(p1+1);
+    tempOutputFile << "#!/bin/sh" << endl;
+    tempOutputFile << "cd " << workDir << endl;
+
+    // Optional parameters
+    //if (param.find(MAXWALLTIME) != param.end())
+    //  tempOutputFile << "#SBATCH --time=" << param[MAXWALLTIME] << endl;
+    //if (param.find(MAXRAMSIZE) != param.end())
+    //  tempOutputFile << "#SBATCH --mem=" << param[MAXRAMSIZE] << endl;
+
+    // Define environment for the job
+    Environnement env = job.getEnvironnement();
+    for (Environnement::const_iterator iter = env.begin() ; iter != env.end() ; ++iter) {
+      tempOutputFile << "export " << iter->first << "=" << iter->second << endl;
+    }
 
-    exec_sub_cmd << "cd " << param[WORKDIR] << " && ./" << fileNameToExecute;
+    // generate nodes file
+    tempOutputFile << "LIBBATCH_NODEFILE=`mktemp nodefile-XXXXXXXXXX`" << endl;
+    tempOutputFile << "echo `hostname` > $LIBBATCH_NODEFILE" << endl;
+    tempOutputFile << "export LIBBATCH_NODEFILE" << endl;
 
+    // Launch the executable
+    tempOutputFile << "./" + fileNameToExecute;
     if (param.find(ARGUMENTS) != param.end()) {
       Versatile V = param[ARGUMENTS];
       for(Versatile::const_iterator it=V.begin(); it!=V.end(); it++) {
         StringType argt = * static_cast<StringType *>(*it);
         string     arg  = argt;
-        exec_sub_cmd << " " << arg;
+        tempOutputFile << " " << arg;
       }
     }
 
+    // Standard input and output
     if (param.find(INFILE) != param.end()) {
       Versatile V = param[INFILE];
       for(Versatile::const_iterator it=V.begin(); it!=V.end(); it++) {
         Couple cpl = * static_cast<CoupleType*>(*it);
         string remote = cpl.getRemote();
         if (remote == "stdin")
-        exec_sub_cmd << " <stdin";
+          tempOutputFile << " <stdin";
       }
     }
 
+    string stdoutFile = workDir + "/logs/output.log." + rootNameToExecute;
+    string stderrFile = workDir + "/logs/error.log." + rootNameToExecute;
     if (param.find(OUTFILE) != param.end()) {
       Versatile V = param[OUTFILE];
       for(Versatile::const_iterator it=V.begin(); it!=V.end(); it++) {
         Couple cpl = * static_cast<CoupleType*>(*it);
         string remote = cpl.getRemote();
-        if (remote == "stdout") exec_sub_cmd << " 1>stdout";
-        if (remote == "stderr") exec_sub_cmd << " 2>stderr";
+        if (remote == "stdout") stdoutFile = "stdout";
+        if (remote == "stderr") stderrFile = "stderr";
       }
     }
+    tempOutputFile << " 1>" << stdoutFile << " 2>" << stderrFile << endl;
 
-    return _protocol.getExecCommandArgs(exec_sub_cmd.str(), _hostname, _username);
+    // Remove the node file
+    tempOutputFile << "rm $LIBBATCH_NODEFILE" << endl;
+
+#ifdef WIN32
+    }
+#endif
+
+    tempOutputFile.flush();
+    tempOutputFile.close();
+
+    cerr << "Batch script file generated is: " << tmpFileName << endl;
+
+    Utils::chmod(tmpFileName.c_str(), 0x1ED);
+    int status = _bm._protocol.copyFile(tmpFileName, "", "",
+                                        remotePath, _bm._hostname, _bm._username);
+    if (status)
+      throw RunTimeException("Cannot copy command file on host " + _bm._hostname);
+
+#ifdef WIN32
+    if (_bm._protocol.getType() != SH) {
+      // On Windows, we make the remote file executable afterward because
+      // pscp does not preserve access permissions on files
+      string subCommand = string("chmod u+x ") + remotePath;
+      string command = _bm._protocol.getExecCommand(subCommand, _bm._hostname, _bm._username);
+      cerr << command.c_str() << endl;
+      status = system(command.c_str());
+      if (status) {
+        std::ostringstream oss;
+        oss << "Cannot change permissions of file " << remotePath << " on host " << _bm._hostname;
+        oss << ". Return status is " << status;
+        throw RunTimeException(oss.str());
+      }
+    }
+#endif
+
+    return remotePath;
   }
 
 
@@ -576,17 +667,13 @@ namespace Batch {
     Parametre param = _job.getParametre();
     Parametre::iterator it;
 
-      //char *const parmList[] = {"/usr/bin/ssh", "localhost", "-l", "aribes", "sleep 1 && echo end", NULL};
-      //int result = execv("/usr/bin/ssh", parmList);
-      //UNDER_LOCK( cout << "*** debug_command = " << result << endl );
-      //UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl );
     try {
 
-      // EXECUTABLE is MANDATORY, if missing, we exit with failure notification
-      vector<string> command;
-      if (param.find(EXECUTABLE) != param.end()) {
-        command = _bm.exec_command(param);
-      } else exit(1);
+      // build script file to launch the job and copy it on the server
+      string cmdFilePath = buildCommandFile(_job);
+
+      // define command to submit the job
+      vector<string> command = _bm._protocol.getExecCommandArgs(cmdFilePath, _bm._hostname, _bm._username);
 
       // Build the argument array argv from the command
       char ** argv = new char * [command.size() + 1];
@@ -594,43 +681,10 @@ namespace Batch {
       for (string::size_type i=0 ; i<command.size() ; i++) {
         argv[i] = new char[command[i].size() + 1];
         strncpy(argv[i], command[i].c_str(), command[i].size() + 1);
-        if (i>0) comstr += " # ";
-        comstr += command[i];
+        comstr += command[i] + " ";
       }
-
       argv[command.size()] = NULL;
-
       UNDER_LOCK( cout << "*** debug_command = " << comstr << endl );
-      UNDER_LOCK( cout << "*** debug_command = " << argv[0] << endl );
-
-      // Create the environment for the new process. Note (RB): Here we change the environment for
-      // the process launched in local. It would seem more logical to set the environment for the
-      // remote process.
-      Environnement env = _job.getEnvironnement();
-
-      char ** envp = NULL;
-      if(env.size() > 0) {
-        envp = new char * [env.size() + 1]; // 1 pour le NULL terminal
-        int i = 0;
-        for(Environnement::const_iterator it=env.begin(); it!=env.end(); it++, i++) {
-          const string  & key   = (*it).first;
-          const string  & value = (*it).second;
-          ostringstream oss;
-          oss << key << "=" << value;
-          envp[i]         = new char [oss.str().size() + 1];
-          strncpy(envp[i], oss.str().c_str(), oss.str().size() + 1);
-        }
-
-        // assert (i == env.size())
-        envp[i] = NULL;
-      }
-
-      //char *const parmList[] = {"/usr/bin/ssh", "localhost", "-l", "aribes", "sleep 1 && echo end", NULL};
-      //int result = execv("/usr/bin/ssh", parmList);
-      //UNDER_LOCK( cout << "*** debug_command = " << result << endl );
-      //UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl );
-
-
 
       // On positionne les limites systeme imposees au fils
       // This part is deactivated because those limits should be set on the job process, not on
@@ -661,26 +715,18 @@ namespace Batch {
       }
       */
 
-
-      //char *const parmList[] = {"/usr/bin/ssh", "localhost", "-l", "aribes", "sleep 1 && echo end", NULL};
-      //int result = execv("/usr/bin/ssh", parmList);
-      //UNDER_LOCK( cout << "*** debug_command = " << result << endl );
-      //UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl );
-
       // On cree une session pour le fils de facon a ce qu'il ne soit pas
       // detruit lorsque le shell se termine (le shell ouvre une session et
       // tue tous les process appartenant a la session en quittant)
       setsid();
 
-
       // On ferme les descripteurs de fichiers standards
       //close(STDIN_FILENO);
       //close(STDOUT_FILENO);
       //close(STDERR_FILENO);
 
-
       // On execute la commande du fils
-      execve(argv[0], argv, envp);
+      execv(argv[0], argv);
       UNDER_LOCK( cout << "*** debug_command = " << strerror(errno) << endl );
       // No need to deallocate since nothing happens after a successful exec
 
@@ -706,46 +752,21 @@ namespace Batch {
 
     try {
 
-      // EXECUTABLE is MANDATORY, if missing, we throw an exception
-      vector<string> exec_command;
-      if (param.find(EXECUTABLE) != param.end()) {
-        exec_command = _bm.exec_command(param);
-      } else {
-        throw RunTimeException("Parameter \"EXECUTABLE\" is mandatory for local batch submission");
-      }
+      // build script file to launch the job and copy it on the server
+      string cmdFilePath = buildCommandFile(_job);
+
+      // define command to submit the job
+      vector<string> command = _bm._protocol.getExecCommandArgs(cmdFilePath, _bm._hostname, _bm._username);
 
       // Build the command string from the command argument vector
       string comstr;
-      for (unsigned int i=0 ; i<exec_command.size() ; i++) {
+      for (unsigned int i=0 ; i<command.size() ; i++) {
         if (i>0) comstr += " ";
-        comstr += exec_command[i];
+        comstr += command[i];
       }
 
       UNDER_LOCK( cout << "*** debug_command = " << comstr << endl );
 
-      // Create the environment for the new process. Note (RB): Here we change the environment for
-      // the process launched in local. It would seem more logical to set the environment for the
-      // remote process.
-      // Note that if no environment is specified, we reuse the current environment.
-      Environnement env = _job.getEnvironnement();
-      char * chNewEnv = NULL;
-
-      if(env.size() > 0) {
-        chNewEnv = new char[4096];
-        LPTSTR lpszCurrentVariable = chNewEnv;
-        for(Environnement::const_iterator it=env.begin() ; it!=env.end() ; it++) {
-          const string  & key   = (*it).first;
-          const string  & value = (*it).second;
-          string envvar = key + "=" + value;
-          envvar.copy(lpszCurrentVariable, envvar.size());
-          lpszCurrentVariable[envvar.size()] = '\0';
-          lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
-        }
-        // Terminate the block with a NULL byte.
-        *lpszCurrentVariable = '\0';
-      }
-
-
       STARTUPINFO si;
       ZeroMemory( &si, sizeof(si) );
       si.cb = sizeof(si);
@@ -756,7 +777,7 @@ namespace Batch {
 
       // launch the new process
       bool res = CreateProcess(NULL, buffer, NULL, NULL, FALSE,
-                               CREATE_NO_WINDOW, chNewEnv, NULL, &si, &pi);
+                               CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
 
       if (buffer) free(buffer);
       if (!res) throw RunTimeException("Error while creating new process");
index 4946d6a6661ec32fde8b1f6770416e7615d54e1c..8058a3c148e697517b3d2730ddc9141c45691348 100644 (file)
@@ -92,6 +92,12 @@ namespace Batch {
       Process launchWin32ChildProcess();
 #endif
 
+      /**
+       * Create script to launch the remote command and copy it on the server.
+       * Return the path of the remote script.
+       */
+      std::string buildCommandFile(const Job_Local & job);
+
     };
 
     enum Commande {
@@ -143,9 +149,6 @@ namespace Batch {
     pthread_mutex_t _threads_mutex;
     std::map<Id, Child > _threads;
 
-    // Methode qui renvoie la commande a executer
-    std::vector<std::string> exec_command(const Parametre & param) const;
-
   private:
     static  void kill_child_on_exit(void * p_pid);
     static  void delete_on_exit(void * arg);
index 69b86d32bc361dc46279ace5ae74159b6276bed3..9a919e1cfbb04b765e49c92102633c47b6d10904 100644 (file)
@@ -50,13 +50,9 @@ IF (HAS_SH)
 ENDIF (HAS_SH)
 
 IF (HAS_SSH)
-    add_executable(Test_Local_SSH Test_Local_SSH.cxx)
-    target_link_libraries(Test_Local_SSH batch SimpleParser)
-    ADD_TEST(Local_SSH Test_Local_SSH)
+    ADD_TEST(LOCAL_SSH ${CMAKE_BINARY_DIR}/src/Core/Test/Test_BatchManager LOCAL SSH)
 ENDIF (HAS_SSH)
 
 IF (HAS_RSH)
-    add_executable(Test_Local_RSH Test_Local_RSH.cxx)
-    target_link_libraries(Test_Local_RSH batch SimpleParser)
-    ADD_TEST(Local_RSH Test_Local_RSH)
+    ADD_TEST(LOCAL_RSH ${CMAKE_BINARY_DIR}/src/Core/Test/Test_BatchManager LOCAL RSH)
 ENDIF (HAS_RSH)
diff --git a/src/Local/Test/Test_Local_RSH.cxx b/src/Local/Test/Test_Local_RSH.cxx
deleted file mode 100644 (file)
index 25133a8..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-//  Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
-//
-//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-/*
- * Test_Local_RSH.cxx :
- *
- * Author : Renaud BARATE - EDF R&D
- * Date   : April 2009
- *
- */
-
-#include <iostream>
-#include <fstream>
-
-#include <Constants.hxx>
-#include <Job.hxx>
-#include <BatchManagerCatalog.hxx>
-#include <FactBatchManager.hxx>
-#include <BatchManager.hxx>
-
-#include <SimpleParser.hxx>
-
-using namespace std;
-using namespace Batch;
-
-int main(int argc, char** argv)
-{
-  cout << "*******************************************************************************************" << endl;
-  cout << "This program tests the local batch submission based on RSH. Passwordless RSH authentication" << endl;
-  cout << "must be used for this test to pass (this can be configured with the .rhosts file)." << endl;
-  cout << "*******************************************************************************************" << endl;
-
-  // eventually remove any previous result
-  remove("result.txt");
-
-  try {
-    // Parse the test configuration file
-    SimpleParser parser;
-    parser.parseTestConfigFile();
-    const string & workdir = parser.getValue("TEST_LOCAL_RSH_WORK_DIR");
-    const string & exechost = parser.getValue("TEST_LOCAL_RSH_EXECUTION_HOST");
-    const string & user = parser.getValue("TEST_LOCAL_RSH_USER");
-    int timeout = parser.getValueAsInt("TEST_LOCAL_RSH_TIMEOUT");
-
-    // Define the job...
-    Job job;
-    // ... and its parameters ...
-    Parametre p;
-    p[EXECUTABLE]    = "test-script.sh";
-    p[NAME]          = "Test_Local_RSH";
-    p[WORKDIR]       = workdir;
-    p[INFILE]        = Couple("seta.sh", workdir + "/copied-seta.sh");
-    p[INFILE]       += Couple("setb.sh", workdir + "/copied-setb.sh");
-    p[OUTFILE]       = Couple("result.txt", workdir + "/orig-result.txt");
-    job.setParametre(p);
-    // ... and its environment
-    Environnement e;
-    job.setEnvironnement(e);
-    cout << job << endl;
-
-    // Get the catalog
-    BatchManagerCatalog& c = BatchManagerCatalog::getInstance();
-
-    // Create a BatchManager of type Local_RSH on localhost
-    FactBatchManager * fbm = c("LOCAL");
-    if (fbm == NULL) {
-      cerr << "Can't get RSH batch manager factory" << endl;
-      return 1;
-    }
-    BatchManager * bm = (*fbm)(exechost.c_str(), user.c_str(), RSH);
-
-    // Submit the job to the BatchManager
-    JobId jobid = bm->submitJob(job);
-    cout << jobid.__repr__() << endl;
-
-    // Wait for the end of the job
-    string state = bm->waitForJobEnd(jobid, timeout);
-
-    if (state == FINISHED) {
-      cout << "Job " << jobid.__repr__() << " is done" << endl;
-      bm->importOutputFiles(job, "resultdir/seconddirname");
-    } else if (state == FAILED) {
-      cerr << "Job " << jobid.__repr__() << " finished in error" << endl;
-      bm->importOutputFiles(job, "resultdir/seconddirname");
-      return 1;
-    } else {
-      cerr << "Timeout while executing job" << endl;
-      return 1;
-    }
-
-  } catch (GenericException e) {
-    cerr << "Error: " << e << endl;
-    return 1;
-  } catch (ParserException e) {
-    cerr << "Parser error: " << e.what() << endl;
-    return 1;
-  }
-
-  // test the result file
-  string exp = "c = 12";
-  string res;
-  ifstream f("resultdir/seconddirname/result.txt");
-  getline(f, res);
-  f.close();
-
-  cout << "result found : " << res << ", expected : " << exp << endl;
-
-  if (res == exp)
-    return 0;
-  else
-    return 1;
-}
diff --git a/src/Local/Test/Test_Local_SSH.cxx b/src/Local/Test/Test_Local_SSH.cxx
deleted file mode 100644 (file)
index 82e857d..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-//  Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
-//
-//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
-//
-//  This library is free software; you can redistribute it and/or
-//  modify it under the terms of the GNU Lesser General Public
-//  License as published by the Free Software Foundation; either
-//  version 2.1 of the License.
-//
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
-//
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-/*
- * Test_Local_SSH.cxx :
- *
- * Author : Renaud BARATE - EDF R&D
- * Date   : April 2009
- *
- */
-
-#include <iostream>
-#include <fstream>
-#include <cstdlib>
-
-#include <Constants.hxx>
-#include <Job.hxx>
-#include <BatchManagerCatalog.hxx>
-#include <FactBatchManager.hxx>
-#include <BatchManager.hxx>
-
-#include <SimpleParser.hxx>
-
-using namespace std;
-using namespace Batch;
-
-int main(int argc, char** argv)
-{
-  cout << "*******************************************************************************************" << endl;
-  cout << "This program tests the local batch submission based on SSH. Passwordless SSH authentication" << endl;
-  cout << "must be used for this test to pass (this can be configured with ssh-agent for instance)." << endl;
-  cout << "*******************************************************************************************" << endl;
-
-  // eventually remove any previous result
-  remove("result.txt");
-
-  try {
-    // Parse the test configuration file
-    SimpleParser parser;
-    parser.parseTestConfigFile();
-    const string & workdir = parser.getValue("TEST_LOCAL_SSH_WORK_DIR");
-    const string & exechost = parser.getValue("TEST_LOCAL_SSH_EXECUTION_HOST");
-    const string & user = parser.getValue("TEST_LOCAL_SSH_USER");
-    int timeout = parser.getValueAsInt("TEST_LOCAL_SSH_TIMEOUT");
-
-    // Define the job...
-    Job job;
-    // ... and its parameters ...
-    Parametre p;
-    p[EXECUTABLE]    = "test-script.sh";
-    p[NAME]          = "Test_Local_SSH";
-    p[WORKDIR]       = workdir;
-    p[INFILE]        = Couple("seta.sh", workdir + "/copied-seta.sh");
-    p[INFILE]       += Couple("setb.sh", workdir + "/copied-setb.sh");
-    p[OUTFILE]       = Couple("result.txt", workdir + "/orig-result.txt");
-    job.setParametre(p);
-    // ... and its environment (SSH_AUTH_SOCK env var is important for ssh agent authentication)
-    Environnement e;
-    const char * sshAuthSock = getenv("SSH_AUTH_SOCK");
-    if (sshAuthSock != NULL) e["SSH_AUTH_SOCK"] = sshAuthSock;
-    job.setEnvironnement(e);
-    cout << job << endl;
-
-    // Get the catalog
-    BatchManagerCatalog& c = BatchManagerCatalog::getInstance();
-
-    // Create a BatchManager of type Local_SSH on localhost
-    FactBatchManager * fbm = c("LOCAL");
-    if (fbm == NULL) {
-      cerr << "Can't get SSH batch manager factory" << endl;
-      return 1;
-    }
-    BatchManager * bm = (*fbm)(exechost.c_str(), user.c_str(), SSH);
-
-    // Submit the job to the BatchManager
-    JobId jobid = bm->submitJob(job);
-    cout << jobid.__repr__() << endl;
-
-    // Wait for the end of the job
-    string state = bm->waitForJobEnd(jobid, timeout);
-
-    if (state == FINISHED) {
-      cout << "Job " << jobid.__repr__() << " is done" << endl;
-      bm->importOutputFiles(job, "resultdir/seconddirname");
-    } else if (state == FAILED) {
-      cerr << "Job " << jobid.__repr__() << " finished in error" << endl;
-      bm->importOutputFiles(job, "resultdir/seconddirname");
-      return 1;
-    } else {
-      cerr << "Timeout while executing job" << endl;
-      return 1;
-    }
-
-  } catch (GenericException e) {
-    cerr << "Error: " << e << endl;
-    return 1;
-  } catch (ParserException e) {
-    cerr << "Parser error: " << e.what() << endl;
-    return 1;
-  }
-
-  // test the result file
-  string exp = "c = 12";
-  string res;
-  ifstream f("resultdir/seconddirname/result.txt");
-  getline(f, res);
-  f.close();
-
-  cout << "result found : " << res << ", expected : " << exp << endl;
-
-  if (res == exp)
-    return 0;
-  else
-    return 1;
-}
index 6e6df0878e44a87cdf66deba9ec524c3654f5f1a..72d8b3cd644f8baa1aadcc02fd4f57bf6f8f44cb 100644 (file)
@@ -35,7 +35,6 @@
 #include <iostream>
 #include <fstream>
 #include <sstream>
-#include <sys/stat.h>
 
 #include <stdlib.h>
 #include <string.h>
@@ -219,7 +218,7 @@ namespace Batch {
     tempOutputFile.flush();
     tempOutputFile.close();
 
-    BATCH_CHMOD(TmpFileName.c_str(), 0x1ED);
+    Utils::chmod(TmpFileName.c_str(), 0x1ED);
     cerr << "Batch script file generated is: " << TmpFileName.c_str() << endl;
 
     int status = _protocol.copyFile(TmpFileName, "", "",