diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/IPathCopier.java b/common/source/java/ch/systemsx/cisd/common/filesystem/IPathCopier.java index f08adda72e40eaae87cfe56d501ad65c4c2f6024..b4c68f7a9fed870a479165ef18b6b03fa9e8d81f 100644 --- a/common/source/java/ch/systemsx/cisd/common/filesystem/IPathCopier.java +++ b/common/source/java/ch/systemsx/cisd/common/filesystem/IPathCopier.java @@ -59,10 +59,13 @@ public interface IPathCopier extends ITerminable, ISelfTestable * null if it is local. * @param rsyncModuleNameOrNull The name of the rsync module to use in the rsync protocol, or * <code>null</code>, if the bulk transfer should be using an ssh tunnel. + * @param rsyncPasswordFileOrNull The name of the password file to use if an rsync server is + * used. May be <code>null</code> or the name of a non-existent file, in which case + * no password is used when accessing the rsync server. * @return The status of the operation, {@link Status#OK} if everything went OK. */ Status copyToRemote(File sourcePath, File destinationDirectory, String destinationHostOrNull, - String rsyncModuleNameOrNull); + String rsyncModuleNameOrNull, String rsyncPasswordFileOrNull); /** * Copies <var>sourcePath</var> on <var>sourceHost</var> to <var>destinationDir</var>. @@ -75,16 +78,18 @@ public interface IPathCopier extends ITerminable, ISelfTestable * will be overwritten. * @param rsyncModuleNameOrNull The name of the rsync module to use in the rsync protocol, or * <code>null</code>, if the bulk transfer should be using an ssh tunnel. + * @param rsyncPasswordFileOrNull The name of the password file to use if an rsync server is + * used. May be <code>null</code> or the name of a non-existent file, in which case + * no password is used when accessing the rsync server. * @return The status of the operation, {@link Status#OK} if everything went OK. */ Status copyFromRemote(File sourcePath, String sourceHost, File destinationDirectory, - String rsyncModuleNameOrNull); - - + String rsyncModuleNameOrNull, String rsyncPasswordFileOrNull); + /** * Try to connect to this server now and see whether we can list the module. * - * @return <code>true</code> if the connection was successfull and <code>false</code> otherwise. + * @return <code>true</code> if the connection was successful and <code>false</code> otherwise. */ - boolean checkRsyncConnection(String host, String rsyncModule); + boolean checkRsyncConnection(String host, String rsyncModule, String rsyncPassworFileOrNull); } diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java b/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java index a84a103b99918e527321bcebeecbefbc0809f1de..546bced00b44c59d1bddea9c5aceb1578d259af2 100644 --- a/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java +++ b/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java @@ -146,19 +146,23 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier public final Status copy(final File sourcePath, final File destinationDirectory) { - return copy(sourcePath, null, destinationDirectory, null, null); + return copy(sourcePath, null, destinationDirectory, null, null, null); } public final Status copyFromRemote(final File sourcePath, final String sourceHost, - final File destinationDirectory, String rsyncModuleNameOrNull) + final File destinationDirectory, String rsyncModuleNameOrNull, + String rsyncPasswordFileOrNull) { - return copy(sourcePath, sourceHost, destinationDirectory, null, rsyncModuleNameOrNull); + return copy(sourcePath, sourceHost, destinationDirectory, null, rsyncModuleNameOrNull, + rsyncPasswordFileOrNull); } public final Status copyToRemote(final File sourcePath, final File destinationDirectory, - final String destinationHost, String rsyncModuleNameOrNull) + final String destinationHost, String rsyncModuleNameOrNull, + String rsyncPasswordFileOrNull) { - return copy(sourcePath, null, destinationDirectory, destinationHost, rsyncModuleNameOrNull); + return copy(sourcePath, null, destinationDirectory, destinationHost, rsyncModuleNameOrNull, + rsyncPasswordFileOrNull); } // @@ -278,10 +282,16 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier return false; } - public boolean checkRsyncConnection(String host, String rsyncModule) + public boolean checkRsyncConnection(String host, String rsyncModule, + String rsyncPasswordFileOrNull) { final List<String> commandLineList = new ArrayList<String>(); commandLineList.add(rsyncExecutable); + if (rsyncPasswordFileOrNull != null && new File(rsyncPasswordFileOrNull).exists()) + { + commandLineList.add("--password-file"); + commandLineList.add(rsyncPasswordFileOrNull); + } commandLineList.add(buildPath(host, new File("/"), rsyncModule, false)); final ProcessResult processResult = runCommand(commandLineList); return processResult.isOK(); @@ -289,7 +299,7 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier private final Status copy(final File sourcePath, final String sourceHostOrNull, final File destinationDirectory, final String destinationHostOrNull, - final String rsyncModuleNameOrNull) + final String rsyncModuleNameOrNull, final String rsyncPasswordFileOrNull) { assert sourcePath != null; assert sourceHostOrNull != null || sourcePath.exists() : logNonExistent(sourcePath); @@ -299,7 +309,7 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier assert sourceHostOrNull == null || destinationHostOrNull == null; final List<String> commandLine = createCommandLineForMutableCopy(sourcePath, sourceHostOrNull, destinationDirectory, - destinationHostOrNull, rsyncModuleNameOrNull); + destinationHostOrNull, rsyncModuleNameOrNull, rsyncPasswordFileOrNull); return createStatus(runCommand(commandLine)); } @@ -317,7 +327,7 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier @Private final List<String> createCommandLineForMutableCopy(final File sourcePath, final String sourceHost, final File destinationDirectory, final String destinationHost, - final String rsyncModuleNameOrNull) + final String rsyncModuleNameOrNull, final String rsyncPasswordFileOrNull) { assert sourcePath != null && (sourceHost != null || sourcePath.exists()); assert destinationDirectory != null @@ -342,6 +352,12 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier commandLineList.add("--rsh"); commandLineList.add(getSshExecutableArgument(sshExecutable)); } + if (rsyncModuleNameOrNull != null && rsyncPasswordFileOrNull != null + && new File(rsyncPasswordFileOrNull).exists()) + { + commandLineList.add("--password-file"); + commandLineList.add(rsyncPasswordFileOrNull); + } if (additionalCmdLineFlags != null) { commandLineList.addAll(additionalCmdLineFlags); diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java index ef9c23be29a8cc06460a64a66b698bdc6126acc7..5ce6c9f5a077c18b11d42bb1d3177cc761a4775d 100644 --- a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java +++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.apache.commons.io.FileUtils; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -112,18 +113,16 @@ public final class RsyncCopierTest } @Test - public void testCommandLineForMutableCopyLocal() throws IOException, - InterruptedException + public void testCommandLineForMutableCopyLocal() throws IOException, InterruptedException { final File rsyncBinary = createRsync(0); final RsyncCopier copier = new RsyncCopier(rsyncBinary, rsyncBinary, false, false); final List<String> cmdLine = copier.createCommandLineForMutableCopy(sourceDirectory, null, destinationDirectory, - null, null); + null, null, null); assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0)); assertEquals(sourceDirectory.getAbsolutePath(), cmdLine.get(cmdLine.size() - 2)); - assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine - .size() - 1)); + assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine.size() - 1)); } @Test @@ -135,7 +134,8 @@ public final class RsyncCopierTest final String host = "hst"; final RsyncCopier copier = new RsyncCopier(rsyncBinary, rsyncBinary, false, false); final List<String> cmdLine = - copier.createCommandLineForMutableCopy(sourceDirectory, null, dstPath, host, null); + copier.createCommandLineForMutableCopy(sourceDirectory, null, dstPath, host, null, + null); assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0)); assertEquals(sourceDirectory.getAbsolutePath(), cmdLine.get(cmdLine.size() - 2)); assertEquals(host + ":dst/", cmdLine.get(cmdLine.size() - 1)); @@ -152,8 +152,52 @@ public final class RsyncCopierTest final RsyncCopier copier = new RsyncCopier(rsyncBinary, rsyncBinary, false, false); final List<String> cmdLine = copier.createCommandLineForMutableCopy(sourceDirectory, null, dstPath, host, - rsyncModule); + rsyncModule, null); + assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0)); + assertEquals(sourceDirectory.getAbsolutePath(), cmdLine.get(cmdLine.size() - 2)); + assertEquals(host + "::" + rsyncModule + "/", cmdLine.get(cmdLine.size() - 1)); + } + + @Test + public void testCommandLineForMutableCopyToRemoteRsyncModuleWithPwFile() throws IOException, + InterruptedException + { + final File rsyncBinary = createRsync(0); + final File dstPath = new File("dst"); + final String host = "hst"; + final String rsyncModule = "rsmod"; + final File pwFile = new File(workingDirectory, "rsync.pwd"); + FileUtils.touch(pwFile); + pwFile.deleteOnExit(); + final RsyncCopier copier = new RsyncCopier(rsyncBinary, rsyncBinary, false, false); + final List<String> cmdLine = + copier.createCommandLineForMutableCopy(sourceDirectory, null, dstPath, host, + rsyncModule, pwFile.getPath()); + assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0)); + assertEquals("--password-file", cmdLine.get(cmdLine.size() - 4)); + assertEquals(workingDirectory + "/rsync.pwd", cmdLine.get(cmdLine.size() - 3)); + assertEquals(sourceDirectory.getAbsolutePath(), cmdLine.get(cmdLine.size() - 2)); + assertEquals(host + "::" + rsyncModule + "/", cmdLine.get(cmdLine.size() - 1)); + } + + @Test + public void testCommandLineForMutableCopyToRemoteRsyncModuleWithNonExistentPwFile() + throws IOException, InterruptedException + { + final File rsyncBinary = createRsync(0); + final File dstPath = new File("dst"); + final String host = "hst"; + final String rsyncModule = "rsmod"; + final File pwFile = new File(workingDirectory, "rsync.pwd"); + pwFile.delete(); + assertFalse(pwFile.exists()); + final RsyncCopier copier = new RsyncCopier(rsyncBinary, rsyncBinary, false, false); + final List<String> cmdLine = + copier.createCommandLineForMutableCopy(sourceDirectory, null, dstPath, host, + rsyncModule, pwFile.getPath()); assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0)); + assertFalse("--password-file".equals(cmdLine.get(cmdLine.size() - 4))); + assertFalse((workingDirectory + "/rsync.pwd").equals(cmdLine.get(cmdLine.size() - 3))); assertEquals(sourceDirectory.getAbsolutePath(), cmdLine.get(cmdLine.size() - 2)); assertEquals(host + "::" + rsyncModule + "/", cmdLine.get(cmdLine.size() - 1)); } @@ -167,11 +211,10 @@ public final class RsyncCopierTest final RsyncCopier copier = new RsyncCopier(rsyncBinary, rsyncBinary, false, false); final List<String> cmdLine = copier.createCommandLineForMutableCopy(sourceDirectory, host, destinationDirectory, - null, null); + null, null, null); assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0)); assertEquals(host + ":" + sourceDirectory.getPath(), cmdLine.get(cmdLine.size() - 2)); - assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine - .size() - 1)); + assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine.size() - 1)); } @Test @@ -181,14 +224,18 @@ public final class RsyncCopierTest final File rsyncBinary = createRsync(0); final String host = "hst"; final String rsyncModule = "rsmod"; + final File pwFile = new File(workingDirectory, "rsync.pwd"); + FileUtils.touch(pwFile); + pwFile.deleteOnExit(); final RsyncCopier copier = new RsyncCopier(rsyncBinary, rsyncBinary, false, false); final List<String> cmdLine = copier.createCommandLineForMutableCopy(sourceDirectory, host, destinationDirectory, - null, rsyncModule); + null, rsyncModule, pwFile.getPath()); assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0)); + assertEquals("--password-file", cmdLine.get(cmdLine.size() - 4)); + assertEquals(workingDirectory + "/rsync.pwd", cmdLine.get(cmdLine.size() - 3)); assertEquals(host + "::" + rsyncModule, cmdLine.get(cmdLine.size() - 2)); - assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine - .size() - 1)); + assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine.size() - 1)); } @Test(groups = diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/DatamoverConstants.java b/datamover/source/java/ch/systemsx/cisd/datamover/DatamoverConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..9b3d917b5080ce5d677d85dc82be97c99f793305 --- /dev/null +++ b/datamover/source/java/ch/systemsx/cisd/datamover/DatamoverConstants.java @@ -0,0 +1,31 @@ +/* + * Copyright 2008 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.datamover; + +/** + * Global constants used in datamover. + * + * @author Bernd Rinn + */ +public class DatamoverConstants +{ + static final String SERVICE_PROPERTIES_FILE = "etc/service.properties"; + + public static final String RSYNC_PASSWORD_FILE_INCOMING = "etc/rsync_incoming.passwd"; + + public static final String RSYNC_PASSWORD_FILE_OUTGOING = "etc/rsync_outgoing.passwd"; +} diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/Parameters.java b/datamover/source/java/ch/systemsx/cisd/datamover/Parameters.java index 4cf1354d98a43a0bf3796c0d5ee7833a26b80932..ff60424def5b6198bc5913a359d34816f8d7f007 100644 --- a/datamover/source/java/ch/systemsx/cisd/datamover/Parameters.java +++ b/datamover/source/java/ch/systemsx/cisd/datamover/Parameters.java @@ -552,7 +552,7 @@ public final class Parameters implements ITimingParameters, IFileSysParameters final Properties properties = new Properties(); try { - final InputStream is = new FileInputStream(PropertyNames.SERVICE_PROPERTIES_FILE); + final InputStream is = new FileInputStream(DatamoverConstants.SERVICE_PROPERTIES_FILE); try { properties.load(is); @@ -565,7 +565,7 @@ public final class Parameters implements ITimingParameters, IFileSysParameters { final String msg = "Could not load the service properties from resource '" - + PropertyNames.SERVICE_PROPERTIES_FILE + "'."; + + DatamoverConstants.SERVICE_PROPERTIES_FILE + "'."; operationLog.warn(msg, ex); throw new ConfigurationFailureException(msg, ex); } diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/PropertyNames.java b/datamover/source/java/ch/systemsx/cisd/datamover/PropertyNames.java index caf45e071fa8afc61f675b3cc332b557bc2e457d..cfffb54a59e2d5f853e3dfc8b3019aa21481dfa2 100644 --- a/datamover/source/java/ch/systemsx/cisd/datamover/PropertyNames.java +++ b/datamover/source/java/ch/systemsx/cisd/datamover/PropertyNames.java @@ -77,8 +77,6 @@ public final class PropertyNames static final String USE_RSYNC_FOR_EXTRA_COPIES = "use-rsync-for-extra-copies"; - static final String SERVICE_PROPERTIES_FILE = "etc/service.properties"; - static final String SSH_EXECUTABLE = "ssh-executable"; static final String TREAT_INCOMING_AS_REMOTE = "treat-incoming-as-remote"; diff --git a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/AbstractFileStore.java b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/AbstractFileStore.java index dc3f416fee4601520d038a937afed20a7fd07930..96f8b5f48cdc05f364c6f6bce412da322ead2a86 100644 --- a/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/AbstractFileStore.java +++ b/datamover/source/java/ch/systemsx/cisd/datamover/filesystem/intf/AbstractFileStore.java @@ -29,6 +29,7 @@ import ch.systemsx.cisd.common.filesystem.IPathCopier; import ch.systemsx.cisd.common.highwatermark.HostAwareFileWithHighwaterMark; import ch.systemsx.cisd.common.utilities.FileUtilities; import ch.systemsx.cisd.common.utilities.StoreItem; +import ch.systemsx.cisd.datamover.DatamoverConstants; /** * The abstract super-class of classes that represent a file store. @@ -112,13 +113,15 @@ public abstract class AbstractFileStore implements IFileStore } else { return copier.copyToRemote(srcItem, destPath, destHostOrNull, - destinationStore.tryGetRsyncModuleName()); + destinationStore.tryGetRsyncModuleName(), + DatamoverConstants.RSYNC_PASSWORD_FILE_OUTGOING); } } else { assert destHostOrNull == null; return copier.copyFromRemote(srcItem, srcHostOrNull, destPath, - tryGetRsyncModuleName()); + tryGetRsyncModuleName(), + DatamoverConstants.RSYNC_PASSWORD_FILE_INCOMING); } } @@ -131,22 +134,24 @@ public abstract class AbstractFileStore implements IFileStore { if (srcHostOrNull != null && tryGetRsyncModuleName() != null) { - check(srcHostOrNull, tryGetRsyncModuleName()); + check(srcHostOrNull, tryGetRsyncModuleName(), + DatamoverConstants.RSYNC_PASSWORD_FILE_INCOMING); } if (destHostOrNull != null && destinationStore.tryGetRsyncModuleName() != null) { - check(destHostOrNull, destinationStore.tryGetRsyncModuleName()); + check(destHostOrNull, destinationStore.tryGetRsyncModuleName(), + DatamoverConstants.RSYNC_PASSWORD_FILE_OUTGOING); } } - private void check(String host, String rsyncModule) + private void check(String host, String rsyncModule, String rsyncPasswordFileOrNull) { - final boolean connectionOK = copier.checkRsyncConnection(host, rsyncModule); + final boolean connectionOK = + copier.checkRsyncConnection(host, rsyncModule, rsyncPasswordFileOrNull); if (connectionOK == false) { throw new ConfigurationFailureException(String.format( - "Connection to rsync module %s::%s failed", srcHostOrNull, - tryGetRsyncModuleName())); + "Connection to rsync module %s::%s failed", host, rsyncModule)); } } diff --git a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/SelfTestTest.java b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/SelfTestTest.java index 26b6c6e56d7217b3e1bc8a5f2b991bc63df7fccb..7faee105f3583a07a594ca9625c38872942ab3f4 100644 --- a/datamover/sourceTest/java/ch/systemsx/cisd/datamover/SelfTestTest.java +++ b/datamover/sourceTest/java/ch/systemsx/cisd/datamover/SelfTestTest.java @@ -105,13 +105,15 @@ public class SelfTestTest } public Status copyFromRemote(File sourcePath, String sourceHost, - File destinationDirectory, String rsyncModuleNameOrNull) + File destinationDirectory, String rsyncModuleNameOrNull, + String rsyncPasswordFileOrNull) { throw new AssertionError(); } public Status copyToRemote(File sourcePath, File destinationDirectory, - String destinationHostOrNull, String rsyncModuleNameOrNull) + String destinationHostOrNull, String rsyncModuleNameOrNull, + String rsyncPasswordFileOrNull) { throw new AssertionError(); } @@ -131,7 +133,8 @@ public class SelfTestTest return false; } - public boolean checkRsyncConnection(String host, String rsyncModule) + public boolean checkRsyncConnection(String host, String rsyncModule, + String rsyncPassworFileOrNull) { throw new AssertionError(); }