Salome HOME
Add rsync as a new protocol for copy.
authorOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Mon, 5 Feb 2018 16:50:54 +0000 (17:50 +0100)
committerOvidiu Mircescu <ovidiu.mircescu@edf.fr>
Thu, 15 Feb 2018 15:48:07 +0000 (16:48 +0100)
CMakeModules/libbatchMacros.cmake
libbatch_config.h.in
src/Core/BatchManager.cxx
src/Core/CMakeLists.txt
src/Core/CommunicationProtocol.cxx
src/Core/CommunicationProtocol.hxx
src/Core/CommunicationProtocolRsync.cxx [new file with mode: 0644]
src/Core/CommunicationProtocolRsync.hxx [new file with mode: 0644]
src/Core/Utils.cxx
src/Core/Utils.hxx

index 4d9846b76b75796c5f1a39b03f7ed27396aa6a0d..465782b749b020d398feada750893d9ee0db2bf4 100644 (file)
@@ -65,14 +65,16 @@ MACRO(LIBBATCH_FIND_ALL_LOCAL_COMMANDS)
   FIND_LOCAL_COMMAND(LIBBATCH_RCP_COMMAND rcp rcp)
   FIND_LOCAL_COMMAND(LIBBATCH_SSH_COMMAND ssh plink)
   FIND_LOCAL_COMMAND(LIBBATCH_SCP_COMMAND scp pscp)
+  FIND_LOCAL_COMMAND(LIBBATCH_RSYNC_COMMAND rsync pscp)
 
   EVAL (HAS_SH LIBBATCH_SH_COMMAND AND LIBBATCH_CP_COMMAND AND LIBBATCH_RM_COMMAND AND LIBBATCH_MKDIR_COMMAND)
   EVAL (HAS_RSH LIBBATCH_RSH_COMMAND AND LIBBATCH_RCP_COMMAND)
   EVAL (HAS_SSH LIBBATCH_SSH_COMMAND AND LIBBATCH_SCP_COMMAND)
+  EVAL (HAS_RSYNC LIBBATCH_SSH_COMMAND AND LIBBATCH_RSYNC_COMMAND)
   
   # Mark shell commands as advanced options
   # and assign the names without the LIBBATCH_ in front:
-  SET (_cmds "RM;SH;CP;MKDIR;RSH;RCP;SSH;SCP")
+  SET (_cmds "RM;SH;CP;MKDIR;RSH;RCP;SSH;SCP;RSYNC")
   FOREACH(_cmd ${_cmds})    
     MARK_AS_ADVANCED(LIBBATCH_${_cmd}_COMMAND)
     SET(${_cmd}_COMMAND ${LIBBATCH_${_cmd}_COMMAND})
index 67b60a1a246e32d7c420bd067d1c2bc4624e84e2..941c00f8bc274c2fd0270b900c22631755269dc3 100644 (file)
 /* SSH tools (ssh, scp) found on the system */
 #cmakedefine HAS_SSH
 
+/* SSH tools and rsync found */
+#cmakedefine HAS_RSYNC
+
 /* A path to a ssh-like command */
 #cmakedefine SSH_COMMAND "@SSH_COMMAND@"
 
 /* A path to a scp-like command */
 #cmakedefine SCP_COMMAND "@SCP_COMMAND@"
 
+/* A path to a scp-like command */
+#cmakedefine RSYNC_COMMAND "@RSYNC_COMMAND@"
+
 #endif
index 047b1ed20e3cdc120d00e1ed62d1d0a05ff46b63..5fdacf5f1ff2348c6294300dcdb5aed165ccebde 100644 (file)
@@ -256,17 +256,14 @@ namespace Batch {
       CoupleType cpt  = *static_cast< CoupleType * >(*Vit);
       Couple outputFile = cpt;
       string remotePath = outputFile.getRemote();
-      if (!Utils::isAbsolutePath(remotePath)) {
-        remotePath = params[WORKDIR].str() + "/" + remotePath;
+      if (!Utils::isAbsolutePath(remotePath) && !Utils::isOption(remotePath)) {
+        // rsync creates the whole tree after /./ in the destination folder
+        remotePath = params[WORKDIR].str() + "/./" + remotePath;
       }
       string localPath = outputFile.getLocal();
       if (!Utils::isAbsolutePath(localPath)) {
         localPath = directory + "/" + localPath;
       }
-      status = CommunicationProtocol::getInstance(SH).makeDirectory(
-                                             Utils::dirname(localPath), "", "");
-      if (status)
-        LOG("Directory creation failed. Status is: " << status);
       status = _protocol.copyFile(remotePath, _hostname, _username,
                                   localPath, "", "");
       if (status)
index 6b4d8f7c0cff0a27e975a40489e6a002722ac337..491d99c4330b03da91d18e6ed1cdf20757b5a349 100644 (file)
@@ -67,6 +67,10 @@ IF (HAS_SSH)
     APPEND_CLASSES_TO_SRC_FILES(Core/CommunicationProtocolSSH)
 ENDIF (HAS_SSH)
 
+IF (HAS_RSYNC)
+    APPEND_CLASSES_TO_SRC_FILES(Core/CommunicationProtocolRsync)
+ENDIF (HAS_RSYNC)
+
 
 IF (LIBBATCH_BUILD_TESTS)
     ADD_SUBDIRECTORY(Test)
index 57a1d527e70a12c7c190a8e90bc8d754a7a51d51..1e50417926fd6fb98fd06eb54c8fdcf12c5618c0 100644 (file)
 #ifdef HAS_SSH
  #include "CommunicationProtocolSSH.hxx"
 #endif
+#ifdef HAS_RSYNC
+ #include "CommunicationProtocolRsync.hxx"
+#endif
 #include "APIInternalFailureException.hxx"
 #include "RunTimeException.hxx"
 #include "Log.hxx"
+#include "Utils.hxx"
 
 using namespace std;
 
@@ -82,6 +86,14 @@ namespace Batch {
 #else
       throw RunTimeException("Can't use SSH protocol (SSH tools were "
                              "not found on the system at compile time).");
+#endif
+    } else if (protocolType == RSYNC) {
+#ifdef HAS_RSYNC
+      static CommunicationProtocolRsync instanceRsync;
+      return instanceRsync;
+#else
+      throw RunTimeException("Can't use RSYNC protocol (RSYNC tools were "
+                             "not found on the system at compile time).");
 #endif
     } else
       throw APIInternalFailureException("Unknown communication protocol.");
@@ -169,7 +181,8 @@ namespace Batch {
 
       // if the argument contains spaces, we surround it with simple quotes (Linux)
       // or double quotes (Windows)
-      if (commandArgs[i].find(' ') != string::npos) {
+      if (commandArgs[i].find(' ') != string::npos &&
+          !Utils::isOption(commandArgs[i])){
         commandStr += string("\"") + commandArgs[i] + "\"";
       } else {
         commandStr += commandArgs[i];
index 3dc61331d02d497609110be8e0c11b842609097e..7b699808609abc30d987942f8bed196b38c53986 100644 (file)
@@ -36,7 +36,7 @@
 
 namespace Batch {
 
-  enum CommunicationProtocolType {SH, SSH, RSH};
+  enum CommunicationProtocolType {SH, SSH, RSH, RSYNC};
 
   class BATCH_EXPORT CommunicationProtocol
   {
diff --git a/src/Core/CommunicationProtocolRsync.cxx b/src/Core/CommunicationProtocolRsync.cxx
new file mode 100644 (file)
index 0000000..72d3a5a
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright (C) 2007-2015  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
+//
+/*
+ *  CommunicationProtocolRsync.cxx :
+ *
+ *  Author : EDF R&D
+ */
+
+#include <libbatch_config.h>
+#include "Utils.hxx"
+
+#include "CommunicationProtocolRsync.hxx"
+
+using namespace std;
+
+namespace Batch {
+
+  CommunicationProtocolRsync::CommunicationProtocolRsync()
+  : CommunicationProtocolSSH()
+  {
+    _type = RSYNC;
+  }
+
+  vector<string> CommunicationProtocolRsync::getCopyCommandArgs(const string & sourcePath,
+                                                              const string & sourceHost,
+                                                              const string & sourceUser,
+                                                              const string & destinationPath,
+                                                              const string & destinationHost,
+                                                              const string & destinationUser) const
+  {
+    vector<string> cmd;
+
+    string fullSource;
+
+    if(Utils::isOption(sourcePath))
+      fullSource += sourcePath;
+    else
+    {
+      if (sourceHost.size() != 0) {
+        if (sourceUser.size() != 0) {
+          fullSource += sourceUser + "@";
+        }
+        fullSource += sourceHost + ":";
+      }
+#ifndef WIN32
+      fullSource += "'";
+#endif
+      fullSource += sourcePath;
+#ifndef WIN32
+      fullSource += "'";
+#endif
+    }
+
+    string fullDestination;
+    if (destinationHost.size() != 0) {
+      if (destinationUser.size() != 0) {
+        fullDestination += destinationUser + "@";
+      }
+      fullDestination += destinationHost + ":";
+    }
+#ifndef WIN32
+    fullDestination += "'";
+#endif
+    fullDestination += destinationPath;
+#ifndef WIN32
+    fullDestination += "'";
+#endif
+
+    // 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);
+    if(!Utils::isOption(sourcePath))
+    {
+      cmd.push_back("-p");
+      cmd.push_back("-r");
+      if(Utils::usesRsyncRelativePath(sourcePath))
+        cmd.push_back("-R");
+    }
+    cmd.push_back(fullSource);
+    cmd.push_back(fullDestination);
+
+    return cmd;
+  }
+
+}
diff --git a/src/Core/CommunicationProtocolRsync.hxx b/src/Core/CommunicationProtocolRsync.hxx
new file mode 100644 (file)
index 0000000..7fa8e1c
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (C) 2007-2015  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
+//
+/*
+ *  CommunicationProtocolRsync.hxx :
+ *
+ *  Author : EDF R&D
+ */
+
+#ifndef _BATCHCOMMUNICATIONPROTOCOLRSYNC_H_
+#define _BATCHCOMMUNICATIONPROTOCOLRSYNC_H_
+
+#include <string>
+#include <vector>
+
+#include "Defines.hxx"
+#include "CommunicationProtocolSSH.hxx"
+
+namespace Batch {
+
+  class BATCH_EXPORT CommunicationProtocolRsync : public CommunicationProtocolSSH
+  {
+    friend class CommunicationProtocol;
+
+  public:
+    std::vector<std::string> getCopyCommandArgs(const std::string & sourcePath,
+                                                const std::string & sourceHost,
+                                                const std::string & sourceUser,
+                                                const std::string & destinationPath,
+                                                const std::string & destinationHost,
+                                                const std::string & destinationUser) const;
+
+  protected:
+
+    CommunicationProtocolRsync();
+
+  };
+
+}
+
+#endif
index cd3deb0455a59950ed2a0b0de7f51a2eee15206e..b7371f905b6e3acb041b7ff3936db28ec790f83e 100644 (file)
@@ -97,6 +97,16 @@ std::string Utils::dirname(const std::string & path)
     return std::string(".");
 }
 
+bool Utils::isOption(const std::string & val)
+{
+  return val.size() > 0 && val[0] == '-';
+}
+
+bool Utils::usesRsyncRelativePath(const std::string & path)
+{
+  return path.find("/./") != std::string::npos;
+}
+
 string Utils::createAndOpenTemporaryFile(const string & prefix, ofstream & outputStream)
 {
   if (outputStream.is_open())
index ed208125ea58825c20b722f3db8814af48882398..8df38c00be320d9cf330ab8fcae6fca14ce78458 100644 (file)
@@ -56,6 +56,17 @@ public:
    */
   static std::string dirname(const std::string & path);
 
+  /**
+   * Test if the string in parameter begins with '-' and it should be processed
+   * as an option, not as a path.
+   */
+  static bool isOption(const std::string & val);
+
+  /**
+   * Test if the path in parameter contains a "/./" sequence.
+   */
+  static bool usesRsyncRelativePath(const std::string & path);
+
   /**
    * Create a temporary file and open an output stream to write into this file.
    * The file is created with the pattern "<tmpdir>/libbatch-<prefix>-XXXXXX" where <tmpdir> is the