Salome HOME
USER or LOGNAME is not defined in a Docker container: on Linux get username with...
[modules/kernel.git] / src / Launcher / Launcher_Job.cxx
index e046fd8cfc14d88b8f5ed7a3fed573a1873bdb47..b724958185a52363ba6549f74f733231b1e643f5 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2009-2017  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2009-2022  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include "Launcher_Job.hxx"
 #include "Launcher.hxx"
 
+#include <Basics_DirUtils.hxx>
+
+#include <boost/filesystem.hpp>
+
 #ifdef WITH_LIBBATCH
 #include <libbatch/Constants.hxx>
 #endif
 
 #include <sstream>
+#ifdef WIN32
+  static const char SEPARATOR = '\\';
+#include <process.h>
+#else
+  static const char SEPARATOR = '/';
+#include <pwd.h>
+#endif
 
 Launcher::Job::Job()
 {
@@ -40,12 +51,14 @@ Launcher::Job::Job()
   _job_file = "";
   _job_file_name = "";
   _job_file_name_complete = "";
+  _pre_command = "";
   _work_directory = "";
   _local_directory = "";
   _result_directory = "";
   _maximum_duration = "";
   _maximum_duration_in_second = -1;
   _queue = "";
+  _partition = "";
   _job_type = "";
   _exclusive = false;
   _mem_per_cpu = 0;
@@ -178,7 +191,16 @@ Launcher::Job::setResourceDefinition(const ParserResourcesType & resource_defini
   std::string user_name = "";
   if (resource_definition.UserName == "")
   {
-    user_name = getenv("USER");
+#ifndef WIN32
+    struct passwd *pwd = getpwuid(getuid());
+    if (pwd) {
+      user_name = std::string(pwd->pw_name);
+    }
+    if (user_name == "")
+      user_name = getenv("USER");
+#else
+    user_name = getenv("USERNAME");
+#endif
     if (user_name == "")
       user_name = getenv("LOGNAME");
     if (user_name == "")
@@ -211,7 +233,7 @@ Launcher::Job::setJobFile(const std::string & job_file)
   }
 
   _job_file = job_file;
-  std::string::size_type p1 = _job_file.find_last_of("/");
+  std::string::size_type p1 = _job_file.find_last_of(SEPARATOR);
   std::string::size_type p2 = _job_file.find_last_of(".");
   _job_file_name_complete = _job_file.substr(p1+1);
   _job_file_name = _job_file.substr(p1+1,p2-p1-1);
@@ -305,6 +327,12 @@ Launcher::Job::setQueue(const std::string & queue)
   _queue = queue;
 }
 
+void
+Launcher::Job::setPartition(const std::string & partition)
+{
+  _partition = partition;
+}
+
 void
 Launcher::Job::setExclusive(bool exclusive)
 {
@@ -406,6 +434,12 @@ Launcher::Job::getQueue() const
   return _queue;
 }
 
+std::string
+Launcher::Job::getPartition() const
+{
+  return _partition;
+}
+
 bool
 Launcher::Job::getExclusive() const
 {
@@ -442,6 +476,18 @@ Launcher::Job::getReference() const
   return _reference;
 }
 
+void
+Launcher::Job::setPreCommand(const std::string & preCommand)
+{
+  _pre_command = preCommand;
+}
+
+std::string
+Launcher::Job::getPreCommand() const
+{
+  return _pre_command;
+}
+
 void
 Launcher::Job::checkMaximumDuration(const std::string & maximum_duration)
 {
@@ -525,7 +571,7 @@ Launcher::Job::getLaunchDate() const
         launch_date[i] == ':' ||
         launch_date[i] == ' ')
       launch_date[i] = '_';
-  launch_date.erase(--launch_date.end()); // Last caracter is a \n
+  launch_date.erase(--launch_date.end()); // Last character is a \n
 
   return launch_date;
 }
@@ -569,7 +615,11 @@ Launcher::Job::common_job_params()
 
   params[Batch::NAME] = getJobName();
   params[Batch::NBPROC] = _resource_required_params.nb_proc;
-  params[Batch::NBPROCPERNODE] = _resource_required_params.nb_proc_per_node;
+  if(_resource_required_params.nb_proc_per_node > 0)
+    params[Batch::NBPROCPERNODE] = _resource_required_params.nb_proc_per_node;
+
+  if(_resource_required_params.nb_node > 0)
+    params[Batch::NBNODE] = _resource_required_params.nb_node;
 
   // Memory in megabytes
   if (_resource_required_params.mem_mb > 0)
@@ -592,50 +642,75 @@ Launcher::Job::common_job_params()
     {
       std::string date_dir = std::string("/job_") + date;
       std::ostringstream str_pid;
+#ifdef WIN32
+         str_pid << _getpid();
+#else
       str_pid << ::getpid();
+#endif
       std::string job_dir = date_dir + "-" + str_pid.str();
 
       _work_directory = _resource_definition.working_directory + job_dir;
     }
     else
     {
+#ifndef WIN32
       _work_directory = std::string("/$HOME/Batch/workdir_");
+#else
+      _work_directory = std::string("%USERPROFILE%\\Batch\\workdir_");
+#endif
       _work_directory += date;
     }
   }
   params[Batch::WORKDIR] = _work_directory;
+  std::string libbatch_pre_command("");
+  if(!_pre_command.empty())
+  {
+    boost::filesystem::path pre_command_path(_pre_command);
+    libbatch_pre_command += "./" + pre_command_path.filename().string();
+  }
+  params[Batch::PREPROCESS] = libbatch_pre_command;
 
   // Parameters for COORM
   params[Batch::LAUNCHER_FILE] = _launcher_file;
   params[Batch::LAUNCHER_ARGS] = _launcher_args;
 
-  // If result_directory is not defined, we use HOME environnement
+  // If result_directory is not defined, we use HOME environment
   if (_result_directory == "")
-    _result_directory = getenv("HOME");
+    _result_directory = Kernel_Utils::HomePath();
 
   // _in_files
   std::list<std::string> in_files(_in_files);
   in_files.push_back(_job_file);
   if (_env_file != "")
           in_files.push_back(_env_file);
+  if(!_pre_command.empty())
+     in_files.push_back(_pre_command);
   for(std::list<std::string>::iterator it = in_files.begin(); it != in_files.end(); it++)
   {
     std::string file = *it;
 
     // local file -> If file is not an absolute path, we apply _local_directory
     std::string local_file;
+#ifndef WIN32
     if (file.substr(0, 1) == std::string("/"))
+#else
+    // On Windows, absolute paths may begin with something like "C:"
+    if (file.substr(1, 1) == std::string(":"))
+#endif
+      local_file = file;
+    else if (file.substr(0, 1) == std::string("-")) // using rsync options
       local_file = file;
     else
 #ifndef WIN32
-      local_file = _local_directory + "/" + file;
+      // '/./' is used by rsync to find the root of the relative path
+      // /a/b/./c/f -> _working_directory/c/f
+      local_file = _local_directory + "/./" + file;
 #else
-      local_file = file;
+      local_file = _local_directory + SEPARATOR + file;
 #endif
 
     // remote file -> get only file name from in_files
-    size_t found = file.find_last_of("/");
-    std::string remote_file = _work_directory + "/" + file.substr(found+1);
+    std::string remote_file = _work_directory + "/";
 
     params[Batch::INFILE] += Batch::Couple(local_file, remote_file);
   }
@@ -653,10 +728,16 @@ Launcher::Job::common_job_params()
       size_t found = file.find_last_of("/");
       local_file = file.substr(found+1);
     }
+    else if (file.substr(0, 1) == std::string("-")) // using rsync options
+    {
+      remote_file = file;
+      local_file = "";
+    }
     else
     {
-      remote_file = _work_directory + "/" + file;
-      local_file = file;
+      // '/./' is used by rsync to find the root of the relative path
+      remote_file = _work_directory + "/./" + file;
+      local_file = "";
     }
 
     params[Batch::OUTFILE] += Batch::Couple(local_file, remote_file);
@@ -670,6 +751,10 @@ Launcher::Job::common_job_params()
   if (_queue != "")
     params[Batch::QUEUE] = _queue;
 
+  // Partition
+  if (_partition != "")
+    params[Batch::PARTITION] = _partition;
+
   // Exclusive
   if (getExclusive())
     params[Batch::EXCLUSIVE] = true;