/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.brooklyn.util.core.ssh;
import static java.lang.String.format;
import static org.apache.brooklyn.util.ssh.BashCommands.sudo;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.core.task.BasicExecutionContext;
import org.apache.brooklyn.util.core.task.ssh.SshTasks;
import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
import org.apache.brooklyn.util.javalang.JavaClassNames;
import org.apache.brooklyn.util.net.Networking;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.ssh.BashCommands;
import org.apache.brooklyn.util.text.Identifiers;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation;
import org.apache.brooklyn.location.ssh.SshMachineLocation;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Files;
public class BashCommandsIntegrationTest {
private static final Logger log = LoggerFactory.getLogger(BashCommandsIntegrationTest.class);
private ManagementContext mgmt;
private BasicExecutionContext exec;
private File destFile;
private File sourceNonExistantFile;
private File sourceFile1;
private File sourceFile2;
private File tmpSudoersFile;
private String sourceNonExistantFileUrl;
private String sourceFileUrl1;
private String sourceFileUrl2;
private SshMachineLocation loc;
private String localRepoFilename = "localrepofile.txt";
private File localRepoBasePath;
private File localRepoEntityBasePath;
private String localRepoEntityVersionPath;
private File localRepoEntityFile;
@BeforeMethod(alwaysRun=true)
public void setUp() throws Exception {
mgmt = new LocalManagementContextForTests();
exec = new BasicExecutionContext(mgmt.getExecutionManager());
destFile = Os.newTempFile(getClass(), "commoncommands-test-dest.txt");
sourceNonExistantFile = new File("/this/does/not/exist/ERQBETJJIG1234");
sourceNonExistantFileUrl = sourceNonExistantFile.toURI().toString();
sourceFile1 = Os.newTempFile(getClass(), "commoncommands-test.txt");
sourceFileUrl1 = sourceFile1.toURI().toString();
Files.write("mysource1".getBytes(), sourceFile1);
sourceFile2 = Os.newTempFile(getClass(), "commoncommands-test2.txt");
sourceFileUrl2 = sourceFile2.toURI().toString();
Files.write("mysource2".getBytes(), sourceFile2);
localRepoEntityVersionPath = JavaClassNames.simpleClassName(this)+"-test-dest-"+Identifiers.makeRandomId(8);
localRepoBasePath = new File(format("%s/.brooklyn/repository", System.getProperty("user.home")));
localRepoEntityBasePath = new File(localRepoBasePath, localRepoEntityVersionPath);
localRepoEntityFile = new File(localRepoEntityBasePath, localRepoFilename);
localRepoEntityBasePath.mkdirs();
Files.write("mylocal1".getBytes(), localRepoEntityFile);
tmpSudoersFile = Os.newTempFile(getClass(), "sudoers" + Identifiers.makeRandomId(8));
String sudoers = ResourceUtils.create(this).getResourceAsString("classpath://brooklyn/util/ssh/test_sudoers");
Files.write(sudoers.getBytes(), tmpSudoersFile);
loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
}
@AfterMethod(alwaysRun=true)
public void tearDown() throws Exception {
if (sourceFile1 != null) sourceFile1.delete();
if (sourceFile2 != null) sourceFile2.delete();
if (destFile != null) destFile.delete();
if (localRepoEntityFile != null) localRepoEntityFile.delete();
if (tmpSudoersFile != null) tmpSudoersFile.delete();
if (localRepoEntityBasePath != null) FileUtils.deleteDirectory(localRepoEntityBasePath);
if (loc != null) loc.close();
if (mgmt != null) Entities.destroyAll(mgmt);
}
@Test(groups="Integration")
public void testRemoveRequireTtyFromSudoersFile() throws Exception {
String cmds = BashCommands.dontRequireTtyForSudo();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ByteArrayOutputStream errStream = new ByteArrayOutputStream();
String cmdsWithReplacedSudoersName = Strings.replaceAllNonRegex(cmds, "/etc/sudoers", tmpSudoersFile.getAbsolutePath());
int exitcode = loc.execCommands(ImmutableMap.of("out", outStream, "err", errStream), "removeRequireTtyFromSudoersFile", ImmutableList.of(cmdsWithReplacedSudoersName));
String outstr = new String(outStream.toByteArray());
String errstr = new String(errStream.toByteArray());
assertEquals(0, exitcode);
// visudo returns "parsed OK"
assertTrue(outstr.contains("parsed OK"), "out="+outstr+"; err="+errstr);
assertTrue(errstr.isEmpty(), "out="+outstr+"; err="+errstr);
}
@Test(groups="Integration")
public void testSudo() throws Exception {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
ByteArrayOutputStream errStream = new ByteArrayOutputStream();
String cmd = sudo("whoami");
int exitcode = loc.execCommands(ImmutableMap.of("out", outStream, "err", errStream), "test", ImmutableList.of(cmd));
String outstr = new String(outStream.toByteArray());
String errstr = new String(errStream.toByteArray());
assertEquals(exitcode, 0, "out="+outstr+"; err="+errstr);
assertTrue(outstr.contains("root"), "out="+outstr+"; err="+errstr);
}
public void testDownloadUrl() throws Exception {
List<String> cmds = BashCommands.commandsToDownloadUrlsAs(
ImmutableList.of(sourceFileUrl1),
destFile.getAbsolutePath());
int exitcode = loc.execCommands("test", cmds);
assertEquals(0, exitcode);
assertEquals(Files.readLines(destFile, Charsets.UTF_8), ImmutableList.of("mysource1"));
}
@Test(groups="Integration")
public void testDownloadFirstSuccessfulFile() throws Exception {
List<String> cmds = BashCommands.commandsToDownloadUrlsAs(
ImmutableList.of(sourceNonExistantFileUrl, sourceFileUrl1, sourceFileUrl2),
destFile.getAbsolutePath());
int exitcode = loc.execCommands("test", cmds);
assertEquals(0, exitcode);
assertEquals(Files.readLines(destFile, Charsets.UTF_8), ImmutableList.of("mysource1"));
}
@Test(groups="Integration")
public void testDownloadToStdout() throws Exception {
ProcessTaskWrapper<String> t = SshTasks.newSshExecTaskFactory(loc,
"cd "+destFile.getParentFile().getAbsolutePath(),
BashCommands.downloadToStdout(Arrays.asList(sourceFileUrl1))+" | sed s/my/your/")
.requiringZeroAndReturningStdout().newTask();
String result = exec.submit(t).get();
assertTrue(result.trim().equals("yoursource1"), "Wrong contents of stdout download: "+result);
}
@Test(groups="Integration")
public void testAlternativesWhereFirstSucceeds() throws Exception {
ProcessTaskWrapper<Integer> t = SshTasks.newSshExecTaskFactory(loc)
.add(BashCommands.alternatives(Arrays.asList("echo first", "exit 88")))
.newTask();
Integer returnCode = exec.submit(t).get();
String stdout = t.getStdout();
String stderr = t.getStderr();
log.info("alternatives for good first command gave: "+returnCode+"; err="+stderr+"; out="+stdout);
assertTrue(stdout.contains("first"), "errcode="+returnCode+"; stdout="+stdout+"; stderr="+stderr);
assertEquals(returnCode, (Integer)0);
}
@Test(groups="Integration")
public void testAlternatives() throws Exception {
ProcessTaskWrapper<Integer> t = SshTasks.newSshExecTaskFactory(loc)
.add(BashCommands.alternatives(Arrays.asList("asdfj_no_such_command_1", "exit 88")))
.newTask();
Integer returnCode = exec.submit(t).get();
log.info("alternatives for bad commands gave: "+returnCode+"; err="+new String(t.getStderr())+"; out="+new String(t.getStdout()));
assertEquals(returnCode, (Integer)88);
}
@Test(groups="Integration")
public void testRequireTestHandlesFailure() throws Exception {
ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
.add(BashCommands.requireTest("-f "+sourceNonExistantFile.getPath(),
"The requested file does not exist")).newTask();
exec.submit(t).get();
assertNotEquals(t.getExitCode(), (Integer)0);
assertTrue(t.getStderr().contains("The requested file"), "Expected message in: "+t.getStderr());
assertTrue(t.getStdout().contains("The requested file"), "Expected message in: "+t.getStdout());
}
@Test(groups="Integration")
public void testRequireTestHandlesSuccess() throws Exception {
ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
.add(BashCommands.requireTest("-f "+sourceFile1.getPath(),
"The requested file does not exist")).newTask();
exec.submit(t).get();
assertEquals(t.getExitCode(), (Integer)0);
assertTrue(t.getStderr().equals(""), "Expected no stderr messages, but got: "+t.getStderr());
}
@Test(groups="Integration")
public void testRequireFileHandlesFailure() throws Exception {
ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
.add(BashCommands.requireFile(sourceNonExistantFile.getPath())).newTask();
exec.submit(t).get();
assertNotEquals(t.getExitCode(), (Integer)0);
assertTrue(t.getStderr().contains("required file"), "Expected message in: "+t.getStderr());
assertTrue(t.getStderr().contains(sourceNonExistantFile.getPath()), "Expected message in: "+t.getStderr());
assertTrue(t.getStdout().contains("required file"), "Expected message in: "+t.getStdout());
assertTrue(t.getStdout().contains(sourceNonExistantFile.getPath()), "Expected message in: "+t.getStdout());
}
@Test(groups="Integration")
public void testRequireFileHandlesSuccess() throws Exception {
ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
.add(BashCommands.requireFile(sourceFile1.getPath())).newTask();
exec.submit(t).get();
assertEquals(t.getExitCode(), (Integer)0);
assertTrue(t.getStderr().equals(""), "Expected no stderr messages, but got: "+t.getStderr());
}
@Test(groups="Integration")
public void testRequireFailureExitsImmediately() throws Exception {
ProcessTaskWrapper<?> t = SshTasks.newSshExecTaskFactory(loc)
.add(BashCommands.requireTest("-f "+sourceNonExistantFile.getPath(),
"The requested file does not exist"))
.add("echo shouldnae come here").newTask();
exec.submit(t).get();
assertNotEquals(t.getExitCode(), (Integer)0);
assertTrue(t.getStderr().contains("The requested file"), "Expected message in: "+t.getStderr());
assertTrue(t.getStdout().contains("The requested file"), "Expected message in: "+t.getStdout());
Assert.assertFalse(t.getStdout().contains("shouldnae"), "Expected message in: "+t.getStdout());
}
@Test(groups="Integration")
public void testPipeMultiline() throws Exception {
String output = execRequiringZeroAndReturningStdout(loc,
BashCommands.pipeTextTo("hello world\n"+"and goodbye\n", "wc")).get();
assertEquals(Strings.replaceAllRegex(output, "\\s+", " ").trim(), "3 4 25");
}
@Test(groups="Integration")
public void testWaitForFileContentsWhenAbortingOnFail() throws Exception {
String fileContent = "mycontents";
String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.ONE_SECOND, true);
int exitcode = loc.execCommands("test", ImmutableList.of(cmd));
assertEquals(exitcode, 1);
Files.write(fileContent, destFile, Charsets.UTF_8);
int exitcode2 = loc.execCommands("test", ImmutableList.of(cmd));
assertEquals(exitcode2, 0);
}
@Test(groups="Integration")
public void testWaitForFileContentsWhenNotAbortingOnFail() throws Exception {
String fileContent = "mycontents";
String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.ONE_SECOND, false);
String output = execRequiringZeroAndReturningStdout(loc, cmd).get();
assertTrue(output.contains("Couldn't find"), "output="+output);
Files.write(fileContent, destFile, Charsets.UTF_8);
String output2 = execRequiringZeroAndReturningStdout(loc, cmd).get();
assertFalse(output2.contains("Couldn't find"), "output="+output2);
}
@Test(groups="Integration")
public void testWaitForFileContentsWhenContentsAppearAfterStart() throws Exception {
String fileContent = "mycontents";
String cmd = BashCommands.waitForFileContents(destFile.getAbsolutePath(), fileContent, Duration.THIRTY_SECONDS, false);
ProcessTaskWrapper<String> t = execRequiringZeroAndReturningStdout(loc, cmd);
exec.submit(t);
// sleep for long enough to ensure the ssh command is definitely executing
Thread.sleep(5*1000);
assertFalse(t.isDone());
Files.write(fileContent, destFile, Charsets.UTF_8);
String output = t.get();
assertFalse(output.contains("Couldn't find"), "output="+output);
}
@Test(groups="Integration", dependsOnMethods="testSudo")
public void testWaitForPortFreeWhenAbortingOnTimeout() throws Exception {
ServerSocket serverSocket = openServerSocket();
try {
int port = serverSocket.getLocalPort();
String cmd = BashCommands.waitForPortFree(port, Duration.ONE_SECOND, true);
int exitcode = loc.execCommands("test", ImmutableList.of(cmd));
assertEquals(exitcode, 1);
serverSocket.close();
assertTrue(Networking.isPortAvailable(port));
int exitcode2 = loc.execCommands("test", ImmutableList.of(cmd));
assertEquals(exitcode2, 0);
} finally {
serverSocket.close();
}
}
@Test(groups="Integration", dependsOnMethods="testSudo")
public void testWaitForPortFreeWhenNotAbortingOnTimeout() throws Exception {
ServerSocket serverSocket = openServerSocket();
try {
int port = serverSocket.getLocalPort();
String cmd = BashCommands.waitForPortFree(port, Duration.ONE_SECOND, false);
String output = execRequiringZeroAndReturningStdout(loc, cmd).get();
assertTrue(output.contains(port+" still in use"), "output="+output);
serverSocket.close();
assertTrue(Networking.isPortAvailable(port));
String output2 = execRequiringZeroAndReturningStdout(loc, cmd).get();
assertFalse(output2.contains("still in use"), "output="+output2);
} finally {
serverSocket.close();
}
}
@Test(groups="Integration", dependsOnMethods="testSudo")
public void testWaitForPortFreeWhenFreedAfterStart() throws Exception {
ServerSocket serverSocket = openServerSocket();
try {
int port = serverSocket.getLocalPort();
String cmd = BashCommands.waitForPortFree(port, Duration.THIRTY_SECONDS, false);
ProcessTaskWrapper<String> t = execRequiringZeroAndReturningStdout(loc, cmd);
exec.submit(t);
// sleep for long enough to ensure the ssh command is definitely executing
Thread.sleep(5*1000);
assertFalse(t.isDone());
serverSocket.close();
assertTrue(Networking.isPortAvailable(port));
String output = t.get();
assertFalse(output.contains("still in use"), "output="+output);
} finally {
serverSocket.close();
}
}
// Disabled by default because of risk of overriding /etc/hosts in really bad way if doesn't work properly!
// As a manual visual inspection test, consider first manually creating /etc/hostname and /etc/sysconfig/network
// so that it looks like debian+ubuntu / CentOS/RHEL.
@Test(groups={"Integration"}, enabled=false)
public void testSetHostnameUnqualified() throws Exception {
runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), null, false);
}
@Test(groups={"Integration"}, enabled=false)
public void testSetHostnameQualified() throws Exception {
runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase()+".brooklyn.incubator.apache.org", null, false);
}
@Test(groups={"Integration"}, enabled=false)
public void testSetHostnameNullDomain() throws Exception {
runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), null, true);
}
@Test(groups={"Integration"}, enabled=false)
public void testSetHostnameNonNullDomain() throws Exception {
runSetHostname("br-"+Identifiers.makeRandomId(8).toLowerCase(), "brooklyn.incubator.apache.org", true);
}
protected void runSetHostname(String newHostname, String newDomain, boolean includeDomain) throws Exception {
String fqdn = (includeDomain && Strings.isNonBlank(newDomain)) ? newHostname + "." + newDomain : newHostname;
LocalManagementContextForTests mgmt = new LocalManagementContextForTests();
SshMachineLocation loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts /etc/hosts-orig-testSetHostname")).get();
execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/hostname", sudo("cp /etc/hostname /etc/hostname-orig-testSetHostname"))).get();
execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/sysconfig/network", sudo("cp /etc/sysconfig/network /etc/sysconfig/network-orig-testSetHostname"))).get();
String origHostname = getHostnameNoArgs(loc);
assertTrue(Strings.isNonBlank(origHostname));
try {
List<String> cmd = (includeDomain) ? BashCommands.setHostname(newHostname, newDomain) : BashCommands.setHostname(newHostname);
execRequiringZeroAndReturningStdout(loc, cmd).get();
String actualHostnameUnqualified = getHostnameUnqualified(loc);
String actualHostnameFullyQualified = getHostnameFullyQualified(loc);
// TODO On OS X at least, we aren't actually setting the domain name; we're just letting
// the user pass in what the domain name is. We do add this properly to /etc/hosts
// (e.g. first line is "127.0.0.1 br-g4x5wgx8.brooklyn.incubator.apache.org br-g4x5wgx8 localhost")
// but subsequent calls to `hostname -f` returns the unqualified. Similarly, `domainname`
// returns blank. Therefore we can't assert that it equals our expected val (because we just made
// it up - "brooklyn.incubator.apache.org").
// assertEquals(actualHostnameFullyQualified, fqdn);
assertEquals(actualHostnameUnqualified, Strings.getFragmentBetween(newHostname, null, "."));
execRequiringZeroAndReturningStdout(loc, "ping -c1 -n -q "+actualHostnameUnqualified).get();
execRequiringZeroAndReturningStdout(loc, "ping -c1 -n -q "+actualHostnameFullyQualified).get();
String result = execRequiringZeroAndReturningStdout(loc, "grep -n "+fqdn+" /etc/hosts").get();
assertTrue(result.contains("localhost"), "line="+result);
log.info("result="+result);
} finally {
execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts-orig-testSetHostname /etc/hosts")).get();
execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/hostname-orig-testSetHostname", sudo("cp /etc/hostname-orig-testSetHostname /etc/hostname"))).get();
execRequiringZeroAndReturningStdout(loc, BashCommands.ifFileExistsElse0("/etc/sysconfig/network-orig-testSetHostname", sudo("cp /etc/sysconfig/network-orig-testSetHostname /etc/sysconfig/network"))).get();
execRequiringZeroAndReturningStdout(loc, sudo("hostname "+origHostname)).get();
}
}
// Marked disabled because not safe to run on your normal machine! It modifies /etc/hosts, which is dangerous if things go wrong!
@Test(groups={"Integration"}, enabled=false)
public void testModifyEtcHosts() throws Exception {
LocalManagementContextForTests mgmt = new LocalManagementContextForTests();
SshMachineLocation loc = mgmt.getLocationManager().createLocation(LocalhostMachineProvisioningLocation.spec()).obtain();
execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts /etc/hosts-orig-testModifyEtcHosts")).get();
int numLinesOrig = Integer.parseInt(execRequiringZeroAndReturningStdout(loc, "wc -l /etc/hosts").get().trim().split("\\s")[0]);
try {
String cmd = BashCommands.prependToEtcHosts("1.2.3.4", "myhostnamefor1234.at.start", "myhostnamefor1234b");
execRequiringZeroAndReturningStdout(loc, cmd).get();
String cmd2 = BashCommands.appendToEtcHosts("5.6.7.8", "myhostnamefor5678.at.end", "myhostnamefor5678");
execRequiringZeroAndReturningStdout(loc, cmd2).get();
String grepFirst = execRequiringZeroAndReturningStdout(loc, "grep -n myhostnamefor1234 /etc/hosts").get();
String grepLast = execRequiringZeroAndReturningStdout(loc, "grep -n myhostnamefor5678 /etc/hosts").get();
int numLinesAfter = Integer.parseInt(execRequiringZeroAndReturningStdout(loc, "wc -l /etc/hosts").get().trim().split("\\s")[0]);
log.info("result: numLinesBefore="+numLinesOrig+"; numLinesAfter="+numLinesAfter+"; first="+grepFirst+"; last="+grepLast);
assertTrue(grepFirst.startsWith("1:") && grepFirst.contains("1.2.3.4 myhostnamefor1234.at.start myhostnamefor1234"), "first="+grepFirst);
assertTrue(grepLast.startsWith((numLinesOrig+2)+":") && grepLast.contains("5.6.7.8 myhostnamefor5678.at.end myhostnamefor5678"), "last="+grepLast);
assertEquals(numLinesOrig + 2, numLinesAfter, "lines orig="+numLinesOrig+", after="+numLinesAfter);
} finally {
execRequiringZeroAndReturningStdout(loc, sudo("cp /etc/hosts-orig-testModifyEtcHosts /etc/hosts")).get();
}
}
private String getHostnameNoArgs(SshMachineLocation machine) {
String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname; echo AFTMARKER").get();
return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
}
private String getHostnameUnqualified(SshMachineLocation machine) {
String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname -s 2> /dev/null || hostname; echo AFTMARKER").get();
return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
}
private String getHostnameFullyQualified(SshMachineLocation machine) {
String hostnameStdout = execRequiringZeroAndReturningStdout(machine, "echo FOREMARKER; hostname --fqdn 2> /dev/null || hostname -f; echo AFTMARKER").get();
return Strings.getFragmentBetween(hostnameStdout, "FOREMARKER", "AFTMARKER").trim();
}
private ProcessTaskWrapper<String> execRequiringZeroAndReturningStdout(SshMachineLocation loc, Collection<String> cmds) {
return execRequiringZeroAndReturningStdout(loc, cmds.toArray(new String[cmds.size()]));
}
private ProcessTaskWrapper<String> execRequiringZeroAndReturningStdout(SshMachineLocation loc, String... cmds) {
ProcessTaskWrapper<String> t = SshTasks.newSshExecTaskFactory(loc, cmds)
.requiringZeroAndReturningStdout().newTask();
exec.submit(t);
return t;
}
private ServerSocket openServerSocket() {
int lowerBound = 40000;
int upperBound = 40100;
for (int i = lowerBound; i < upperBound; i++) {
try {
return new ServerSocket(i);
} catch (IOException e) {
// try next number
}
}
throw new IllegalStateException("No ports available in range "+lowerBound+" to "+upperBound);
}
}