Salome HOME
[bos #32518][EDF] (2022-T3)
authorMargarita KARPUNINA <margarita.karpunina@opencascade.com>
Fri, 28 Oct 2022 11:21:16 +0000 (14:21 +0300)
committerMargarita KARPUNINA <margarita.karpunina@opencascade.com>
Fri, 28 Oct 2022 11:21:16 +0000 (14:21 +0300)
Parametrize commands in LIBBATCH

CMakeLists.txt
src/Core/CMakeLists.txt
src/Core/CommandsOverloader.cxx [new file with mode: 0644]
src/Core/CommandsOverloader.hxx [new file with mode: 0644]
src/Core/CommunicationProtocolRSH.cxx
src/Core/CommunicationProtocolRsync.cxx
src/Core/CommunicationProtocolSH.cxx
src/Core/CommunicationProtocolSSH.cxx
src/Core/Test/batchtest.conf
src/Python/Test/config.py.in

index 62ed7b7507ed3b79379f0fccba207ea4366dc513..63750e5d519d74ffb4386569468b704788a114c2 100644 (file)
@@ -52,7 +52,7 @@ SET(INSTALL_INCLUDE_DIR include)
 
 SET(LIBBATCH_LOCAL_SUBMISSION TRUE CACHE BOOL "Build classes for local submission")
 SET(LIBBATCH_PYTHON_WRAPPING TRUE CACHE BOOL "Generate Python wrapping")
-SET(LIBBATCH_BUILD_TESTS FALSE CACHE BOOL "Enable testing")
+SET(LIBBATCH_BUILD_TESTS TRUE CACHE BOOL "Enable testing")
 
 IF(LIBBATCH_BUILD_TESTS)
   ENABLE_TESTING()
index ceb3e98b2cc3c65429180d6649434f25c57a79aa..54ea889f925f59ebdc5b0ad92e3fcdad48b08aa7 100644 (file)
@@ -24,6 +24,7 @@ SET(CLASS_LIST Core/APIInternalFailureException
                Core/BatchManager
                Core/BatchManagerCatalog
                Core/BoolType
+               Core/CommandsOverloader
                Core/CommunicationProtocol
                Core/Constants
                Core/Couple
diff --git a/src/Core/CommandsOverloader.cxx b/src/Core/CommandsOverloader.cxx
new file mode 100644 (file)
index 0000000..7ee23c3
--- /dev/null
@@ -0,0 +1,247 @@
+// Copyright (C) 2007-2021  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, or (at your option) any later version.
+//
+// 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
+//
+/*
+ * CommandsOverloader.cxx :
+ *
+ * Author : Margarita KARPUNINA - OCC
+ * Date   : October 2022
+ *
+ */
+
+#include <fstream>
+#include <set>
+#include <sstream>
+
+#include <libbatch_config.h>
+
+#include "CommandsOverloader.hxx"
+
+#include "RunTimeException.hxx"
+
+using namespace std;
+
+
+namespace Batch {
+
+  static set<string> supportedCmds({"RM", "SH", "CP", "MKDIR", "RSH", "RCP", "SSH", "SCP", "RSYNC"});
+
+  /*!
+   * Constructor.
+   */
+  CommandsOverloader::CommandsOverloader()
+  {    
+  }
+
+  /*!
+   * Destructor.
+   */
+  CommandsOverloader::~CommandsOverloader()
+  {
+  }
+
+  /*!
+   * Return the CommandsOverloader singleton.
+   */
+  CommandsOverloader& CommandsOverloader::getInstance () {
+    static CommandsOverloader instance;
+    return instance;
+  }
+
+  /*!
+   * Return an overridden definition of RM command.
+   */
+  string CommandsOverloader::RM_Command() {
+    string cmd = CMD_Command("RM");
+    return (cmd.empty() ? RM_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of SH command.
+   */
+  string CommandsOverloader::SH_Command() {
+    string cmd = CMD_Command("SH");
+    return (cmd.empty() ? SH_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of CP command.
+   */
+  string CommandsOverloader::CP_Command() {
+    string cmd = CMD_Command("CP");
+    return (cmd.empty() ? CP_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of MKDIR command.
+   */
+  string CommandsOverloader::MKDIR_Command() {
+    string cmd = CMD_Command("MKDIR");
+    return (cmd.empty() ? MKDIR_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of RSH command.
+   */
+  string CommandsOverloader::RSH_Command() {
+    string cmd = CMD_Command("RSH");
+    return (cmd.empty() ? RSH_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of RCP command.
+   */
+  string CommandsOverloader::RCP_Command() {
+    string cmd = CMD_Command("RCP");
+    return (cmd.empty() ? RCP_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of SSH command.
+   */
+  string CommandsOverloader::SSH_Command() {
+    string cmd = CMD_Command("SSH");
+    return (cmd.empty() ? SSH_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of SCP command.
+   */
+  string CommandsOverloader::SCP_Command() {
+    string cmd = CMD_Command("SCP");
+    return (cmd.empty() ? SCP_COMMAND : cmd);
+  }
+
+  /*!
+   * Return an overridden definition of RSYNC command.
+   */
+  string CommandsOverloader::RSYNC_Command() {
+    string cmd = CMD_Command("RSYNC");
+     return (cmd.empty() ? RSYNC_COMMAND : cmd);
+  }
+
+  /*!
+   * Parse text file with the given file name and fill in the map of 
+   * <CMD> - <associated command desired by the user at runtime>.
+   * \param theFilename the name of text file to be parsed
+   */
+  void CommandsOverloader::parse(const std::string & theFilename) {
+    ifstream fileStream(theFilename.c_str());
+    if (!fileStream) {
+      stringstream errMsg;
+      errMsg << "Can't open file with overridden commands definitions " << theFilename;
+      throw RunTimeException(errMsg.str());
+    }
+    string line;
+    int lineNumber = 1;
+    while (getline(fileStream, line)) {
+      string str = line;
+      if (!str.empty()) {
+        // Find ' ' symbol and split the line
+        size_t pos = str.find_first_of(' ');
+        if (pos == string::npos) {
+          stringstream errMsg;
+          errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
+                 << ": Syntax error (missing ' ' character between key and value): " << line;
+          throw RunTimeException(errMsg.str());
+        } else {
+          string key = str.substr(0, pos);
+          string value = str.substr(pos+1);
+
+          // Check non-completeness of the file.
+          string trimmedKey = trim(key);
+          string trimmedValue = trim(value);
+          if (trimmedKey.empty() || trimmedValue.empty()) {
+            stringstream errMsg;
+            errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
+                   << ": The non-completeness of the file: " << line;
+            throw RunTimeException(errMsg.str());
+          }
+
+          // Check the presence of an unsupported command.
+          if (supportedCmds.find(trimmedKey) == supportedCmds.end()) {
+            stringstream errMsg;
+            errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
+                   << ": The presence of an unsupported command: " << trimmedKey;
+            throw RunTimeException(errMsg.str());
+          }
+
+          if (!hasKey(trimmedKey)) {
+            _cmdmap[trimmedKey] = trimmedValue;
+          }
+          else {
+            // Redifinition of already overloaded command is found.
+            stringstream errMsg;
+            errMsg << "Wrong format of " << theFilename << " file on line " << lineNumber
+                   <<": A repetition of the " << trimmedKey << " key in several lines.";
+            throw RunTimeException(errMsg.str());
+          }
+        }
+      }
+      ++lineNumber;
+    }
+    fileStream.close();
+  }
+
+  /*!
+   * Strip leading and trailing spaces in the given string.
+   * \param theStr string to be stripped
+   * \return stripped string
+   */
+  std::string CommandsOverloader::trim(const std::string & theStr) const noexcept
+  {
+    size_t beg = theStr.find_first_not_of(" \t");
+    if (beg == string::npos) beg = 0;
+    size_t end = theStr.find_last_not_of(" \t");
+    return theStr.substr(beg, end-beg+1);
+  }
+
+  /*!
+   * Return an overridden definition of the given command.
+   * \param theKey command name
+   * \return overridden definition of the given command
+   */
+  string CommandsOverloader::CMD_Command(const std::string & theKey) {
+    if (_cmdmap.empty()) {
+      const char * filename = getenv("LIBBATCH_OVERRIDE_CMDS");
+      if (filename != NULL) {
+        // Environment variable LIBBATCH_OVERRIDE_CMDS is defined.
+        // Parse text file pointed by LIBBATCH_OVERRIDE_CMDS environment variable.
+        parse(filename);
+        // Note: If environment variable LIBBATCH_OVERRIDE_CMDS is not defined,
+        // use command configuration established at compile time.
+      }
+    }
+
+    return (hasKey(theKey) ? _cmdmap[theKey] : string());
+  }
+
+  /*!
+   * Check, if commands map contains the given command key.
+   * \param theKey command name
+   * \return true, if command key exists in the map
+   */
+  bool CommandsOverloader::hasKey(const string & theKey) const
+  {
+    return (_cmdmap.find(theKey) != _cmdmap.end());
+  }
+
+}
diff --git a/src/Core/CommandsOverloader.hxx b/src/Core/CommandsOverloader.hxx
new file mode 100644 (file)
index 0000000..ca1cf76
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright (C) 2007-2021  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, or (at your option) any later version.
+//
+// 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
+//
+/*
+ * CommandsOverloader.hxx :
+ *
+ * Author : Margarita KARPUNINA - OCC
+ * Date   : October 2022
+ *
+ */
+
+#ifndef _COMMANDSOVERLOADER_H_
+#define _COMMANDSOVERLOADER_H_
+
+#include "Defines.hxx"
+
+#include <map>
+#include <string>
+
+namespace Batch {
+
+  /*!
+   * This class is used to parametrize commands in LIBBATCH.
+   * It's a singleton that can be get only through the static method getInstance().
+   */
+  class BATCH_EXPORT CommandsOverloader
+  {
+  public:
+    static CommandsOverloader& getInstance();
+
+    std::string RM_Command();
+    std::string SH_Command();
+    std::string CP_Command();
+    std::string MKDIR_Command();
+    std::string RSH_Command();
+    std::string RCP_Command();
+    std::string SSH_Command();
+    std::string SCP_Command();
+    std::string RSYNC_Command();
+
+  protected:
+    CommandsOverloader();
+    virtual ~CommandsOverloader();
+
+    void parse(const std::string & theFilename);
+    std::string trim(const std::string & theStr) const noexcept;
+
+    std::string CMD_Command(const std::string & theKey);
+
+    bool hasKey(const std::string & theKey) const;
+
+    std::map<std::string, std::string> _cmdmap;
+
+  private:
+    // Forbid the use of copy constructor and assignment operator
+    CommandsOverloader(const CommandsOverloader &) {}
+    void operator=(const CommandsOverloader &) {}
+  };
+
+}
+
+#endif
index f00e135960923a99748d21dae49e112a89005a12..50bad5da95d80659d594023e9dc01c7d01958000 100644 (file)
@@ -36,6 +36,7 @@
 #include <libbatch_config.h>
 
 #include "CommunicationProtocolRSH.hxx"
+#include "CommandsOverloader.hxx"
 #include "Log.hxx"
 
 using namespace std;
@@ -53,7 +54,7 @@ namespace Batch {
   {
     vector<string> cmd;
 
-    cmd.push_back(RSH_COMMAND);
+    cmd.push_back(CommandsOverloader::getInstance().RSH_Command());
     cmd.push_back(host);
 
     if (user.size() > 0) {
@@ -107,7 +108,7 @@ namespace Batch {
     }
     fullDestination += destinationPath;
 
-    cmd.push_back(RCP_COMMAND);
+    cmd.push_back(CommandsOverloader::getInstance().RCP_Command());
     cmd.push_back("-r");
     cmd.push_back(fullSource);
     cmd.push_back(fullDestination);
index aaa18adc0ba4bb300369971f7240e64f35012208..0d9ef782fc1c73844d7813f2bdab702d2a35c6d5 100644 (file)
@@ -29,6 +29,7 @@
 #include "Utils.hxx"
 
 #include "CommunicationProtocolRsync.hxx"
+#include "CommandsOverloader.hxx"
 
 using namespace std;
 
@@ -87,7 +88,7 @@ namespace Batch {
 
     // Option -p is used to keep the same permissions for the destination file
     // (particularly useful to keep scripts executable when copying them)
-    cmd.push_back(RSYNC_COMMAND);
+    cmd.push_back(CommandsOverloader::getInstance().RSYNC_Command());
     if(!Utils::isOption(sourcePath))
     {
       cmd.push_back("-p");
index e59b4a1c701579246d8a8364732ba0cfa80c2742..c8f67401b167263e1b8fe8cf062336983da2826a 100644 (file)
@@ -29,6 +29,7 @@
 #include <libbatch_config.h>
 
 #include "CommunicationProtocolSH.hxx"
+#include "CommandsOverloader.hxx"
 #include "Utils.hxx"
 
 using namespace std;
@@ -46,7 +47,7 @@ namespace Batch {
   {
     vector<string> cmd;
 
-    cmd.push_back(Utils::fixPath(SH_COMMAND));
+    cmd.push_back(Utils::fixPath(CommandsOverloader::getInstance().SH_Command()));
 
 #ifdef WIN32
     cmd.push_back("/c");
@@ -67,7 +68,7 @@ namespace Batch {
                                                              const string & /*destinationUser*/) const
   {
     vector<string> cmd;
-    cmd.push_back(CP_COMMAND);
+    cmd.push_back(CommandsOverloader::getInstance().CP_Command());
 #ifndef WIN32
     cmd.push_back("-r");
 #endif
@@ -78,12 +79,12 @@ namespace Batch {
 
   string CommunicationProtocolSH::getRemoveSubCommand(const string & path) const
   {
-    return string(RM_COMMAND) + " " + Utils::fixPath(path);
+    return string(CommandsOverloader::getInstance().RM_Command()) + " " + Utils::fixPath(path);
   }
 
   string CommunicationProtocolSH::getMakeDirectorySubCommand(const string & path) const
   {
-    string subCommand = MKDIR_COMMAND;
+    string subCommand = CommandsOverloader::getInstance().MKDIR_Command();
 #ifndef WIN32
     subCommand += " -p";
 #endif
index cbe5af1762b8d511a9ec5fefbd20af9267bad912..1869cb602f48330528ce30e6f45ddcba0fcb2e96 100644 (file)
@@ -29,6 +29,7 @@
 #include <libbatch_config.h>
 
 #include "CommunicationProtocolSSH.hxx"
+#include "CommandsOverloader.hxx"
 
 using namespace std;
 
@@ -45,7 +46,7 @@ namespace Batch {
   {
     vector<string> cmd;
 
-    cmd.push_back(SSH_COMMAND);
+    cmd.push_back(CommandsOverloader::getInstance().SSH_Command());
     cmd.push_back(host);
 
     if (user.size() != 0) {
@@ -99,7 +100,7 @@ namespace Batch {
 
     // Option -p is used to keep the same permissions for the destination file
     // (particularly useful to keep scripts executable when copying them)
-    cmd.push_back(SCP_COMMAND);
+    cmd.push_back(CommandsOverloader::getInstance().SCP_Command());
     cmd.push_back("-p");
     cmd.push_back("-r");
     cmd.push_back(fullSource);
index 275af50c25b28d21ff363de016377bef5439b3b1..1a7f9ad5960178de6437dcdd8a6d787da77e46e3 100644 (file)
@@ -7,7 +7,7 @@
 
 TEST_LOCAL_SH_HOST = "localhost"              # Not used
 TEST_LOCAL_SH_USER = "me"                     # Not used
-TEST_LOCAL_SH_WORK_DIR = "/tmp"               # Work directory for local SH Batch test
+TEST_LOCAL_SH_WORKDIR = "/tmp"               # Work directory for local SH Batch test
 TEST_LOCAL_SH_TIMEOUT = 2                     # Execution timeout (in seconds) for local SH Batch test
 
 TEST_LOCAL_HOST = "localhost"                 # Execution host for LOCAL Batch test
index 023b7ccbc434701b34105c46fd4c99fd5303ddad..5b2ff227f8fae6e243437fc51709c32f528b25b4 100644 (file)
@@ -25,5 +25,7 @@ import os
 sys.path.append('${CMAKE_CURRENT_BINARY_DIR}/..')
 
 configfile = os.environ["${LIBBATCH_TEST_CONF_ENV_VAR}"]
-execfile(configfile)
+with open(configfile, "rb") as source_file:
+    code = compile(source_file.read(), configfile, "exec")
+exec(code)
 TEST_SOURCE_DIR = "${CMAKE_SOURCE_DIR}/src/Core/Test"