bug4811: implemented Util.wait in different variants and used in a few places

This commit is contained in:
Axel Uhl committed 2021-01-13 12:47:39 +01:00
1 parent b8c9848a33
commit ca1108b2d1
20 files changed
+219 -140

No files matched your search

@@ -164,7 +164,7 @@ public class TestProcedures {
landscape.getApplicationReplicaSetsByTag(region, sailingAnalyticsServerTag, (theHost, dir)->{
try {
return new SailingAnalyticsProcessImpl<String>(theHost, dir, optionalTimeout, privateKeyEncryptionPassphrase);
} catch (NumberFormatException | JSchException | IOException | InterruptedException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
}, optionalTimeout, privateKeyEncryptionPassphrase);
@@ -1,11 +1,8 @@
package com.sap.sailing.landscape;
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Logger;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.sap.sse.common.Duration;
import com.sap.sse.landscape.application.ApplicationProcess;
@@ -14,7 +11,7 @@ public interface SailingAnalyticsProcess<ShardingKey> extends ApplicationProcess
static String HEALTH_CHECK_PATH = "/gwt/status";
default int getExpeditionUdpPort(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase)
throws NumberFormatException, JSchException, IOException, InterruptedException, SftpException {
throws Exception {
return Integer.parseInt(getEnvShValueFor(SailingAnalyticsProcessConfigurationVariable.EXPEDITION_PORT.name(),
optionalTimeout, privateKeyEncryptionPassphrase));
}
@@ -34,7 +34,7 @@ implements SailingAnalyticsProcess<ShardingKey> {
*/
public SailingAnalyticsProcessImpl(Host host, String serverDirectory, Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase)
throws NumberFormatException, JSchException, IOException, InterruptedException {
throws Exception {
super(host, serverDirectory, optionalTimeout, privateKeyEncryptionPassphrase);
}
@@ -1,6 +1,5 @@
package com.sap.sailing.landscape.procedures;
import java.io.IOException;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
@@ -8,8 +7,6 @@ import java.util.function.Function;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
import com.sap.sailing.landscape.SailingAnalyticsProcess;
import com.sap.sailing.landscape.impl.SailingAnalyticsProcessImpl;
@@ -125,8 +122,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsProce
ap->{
try {
return ap.getTelnetPortToOSGiConsole(getOptionalTimeout(), privateKeyEncryptionPassphrase);
} catch (NumberFormatException | JSchException | IOException | SftpException
| InterruptedException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
@@ -137,8 +133,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsProce
ap->{
try {
return ap.getExpeditionUdpPort(getOptionalTimeout(), privateKeyEncryptionPassphrase);
} catch (NumberFormatException | JSchException | IOException | InterruptedException
| SftpException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
}));
@@ -232,7 +227,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsProce
}
@Override
public void run() throws IOException, InterruptedException, JSchException, SftpException {
public void run() throws Exception {
assert getHostToDeployTo() != null;
final String serverDirectory = applicationConfiguration.getServerDirectory();
{
@@ -1,12 +1,10 @@
package com.sap.sailing.landscape.procedures;
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
@@ -97,7 +95,7 @@ implements StartFromSailingAnalyticsImage {
new ApplicationProcessHostImpl<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsProcess<ShardingKey>>(instanceId, az, landscape, (host, serverDirectory)->{
try {
return new SailingAnalyticsProcessImpl<ShardingKey>(host, serverDirectory, getOptionalTimeout(), getPrivateKeyEncryptionPassphrase());
} catch (NumberFormatException | JSchException | IOException | InterruptedException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
});
@@ -1,10 +1,8 @@
package com.sap.sailing.landscape.procedures;
import java.io.IOException;
import java.util.Optional;
import java.util.logging.Logger;
import com.jcraft.jsch.JSchException;
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
import com.sap.sailing.landscape.SailingAnalyticsProcess;
import com.sap.sailing.landscape.SailingReleaseRepository;
@@ -94,7 +92,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsProce
(host, serverDirectory)->{
try {
return new SailingAnalyticsProcessImpl<ShardingKey>(host, serverDirectory, getOptionalTimeout(), getPrivateKeyEncryptionPassphrase());
} catch (NumberFormatException | JSchException | IOException | InterruptedException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
});
@@ -1,6 +1,5 @@
package com.sap.sailing.landscape.procedures;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -9,7 +8,6 @@ import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.jcraft.jsch.JSchException;
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
import com.sap.sailing.landscape.SailingAnalyticsProcess;
import com.sap.sailing.landscape.impl.SailingAnalyticsProcessImpl;
@@ -209,7 +207,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsProce
(host, serverDirectory)->{
try {
return new SailingAnalyticsProcessImpl<ShardingKey>(host, serverDirectory, getOptionalTimeout(), getPrivateKeyEncryptionPassphrase());
} catch (NumberFormatException | JSchException | IOException | InterruptedException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
});
@@ -13,11 +13,16 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@@ -27,7 +32,8 @@ import com.sap.sse.common.util.NaturalComparator;
public class Util {
private static final Logger logger = Logger.getLogger(Util.class.getName());
public static class Pair<A, B> implements Serializable {
private static final long serialVersionUID = -7631774746419135931L;
@@ -1023,4 +1029,103 @@ public class Util {
}
};
}
/**
* Like {@link #wait(Callable, Optional, Duration, Level, String)}, but not producing log output
*/
public static boolean wait(Callable<Boolean> condition, Optional<Duration> optionalTimeoutEmptyMeansForever, Duration sleepBetweenAttempts) throws Exception {
return wait(condition, optionalTimeoutEmptyMeansForever, sleepBetweenAttempts, /* no logging */ null, /* no log message */ null);
}
/**
* Keeps evaluating {@code condition} until the result is {@code true} or the timeout, if provided in
* {@code optionalTimeoutEmptyMeansForever}, has expired. Sleeps {@code sleepBetweenAttempts} between subsequent
* attempts. Note that once decided for starting another evaluation, that evaluation may surpass the timeout; but no
* new evaluation will be started after the timeout has expired. The {@code condition} will be evaluated at least
* once, even if a timeout of zero seconds has been specified. If no timeout is provided, the method will keep
* evaluating the condition until it returns {@code true}.<p>
*
* Any exception thrown during the evaluation of {@code condition} will pass the exception on to the caller.<p>
*
* If a non-{@code null} {@code logLevel} and {@code retryLogMessage} are provided, upon failure and if the timeout permits
* for another round of sleep/retry, a message will be logged telling that {@code retryLogMessage} failed and that
* another attempt will be made in {@cod esleepBetweenAttempts} until the timeout has been reached.
*
* @return the last evaluation result of {@code condition}
*/
public static boolean wait(Callable<Boolean> condition, Optional<Duration> optionalTimeoutEmptyMeansForever, Duration sleepBetweenAttempts,
Level logLevel, String retryLogMessage) throws Exception, TimeoutException {
return wait(condition, result->result, /* retryOnException */ false, optionalTimeoutEmptyMeansForever, sleepBetweenAttempts, logLevel, retryLogMessage);
}
/**
* Keeps evaluating {@code callable} until the result is tested successfully by the {@code successPredicate}, or the
* timeout, if provided in {@code optionalTimeoutEmptyMeansForever}, has expired. Sleeps
* {@code sleepBetweenAttempts} between subsequent attempts. Note that once decided for starting another evaluation,
* that evaluation may surpass the timeout; but no new evaluation will be started after the timeout has expired. The
* {@code condition} will be evaluated at least once, even if a timeout of zero seconds has been specified. If no
* timeout is provided, the method will keep evaluating the {@code callable} until it passes the
* {@code successPredicate}.
* <p>
*
* If {@code retryOnException} is set to {@code true}, any exception thrown during the evaluation of
* {@code callable} will be considered a failed attempt that leads to a retry if there is still time; if
* {@code retryOnException} is {@code false}, the exception will be thrown by this method.
* <p>
*
* If a non-{@code null} {@code logLevel} and {@code retryLogMessage} are provided, upon failure and if the timeout
* permits for another round of sleep/retry, a message will be logged telling that {@code retryLogMessage} failed
* and that another attempt will be made in {@cod esleepBetweenAttempts} until the timeout has been reached.
* <p>
*
* @return the last evaluation result of {@code callable}; this one has successfully passed the
* {@code successPredicate}
* @throws TimeoutException
* if a {@code optionalTimeoutEmptyMeansForever} was provided and within this time no execution of the
* {@code callable} was considered a success by the {@code successPredicate}
*/
public static <T> T wait(Callable<T> callable, Predicate<T> successPredicate, boolean retryOnException,
Optional<Duration> optionalTimeoutEmptyMeansForever, Duration sleepBetweenAttempts, Level logLevel,
String retryLogMessage) throws Exception, TimeoutException {
final TimePoint start = TimePoint.now();
T result = null;
boolean success;
boolean timeForAnotherAttempt;
do {
try {
result = callable.call();
success = successPredicate.test(result);
if (success && logLevel != null && retryLogMessage != null) {
logger.log(logLevel, retryLogMessage+" succeeded.");
}
} catch (Exception e) {
if (retryOnException) {
success = false;
if (logLevel != null && retryLogMessage != null) {
logger.log(logLevel, retryLogMessage+" threw exception "+e.getMessage());
}
} else {
throw e;
}
}
timeForAnotherAttempt = optionalTimeoutEmptyMeansForever.map(timeout->TimePoint.now().plus(sleepBetweenAttempts).before(start.plus(timeout))).orElse(true);
if (!success) {
if (logLevel != null && retryLogMessage != null) {
logger.log(logLevel, retryLogMessage+" failed."+(timeForAnotherAttempt?
optionalTimeoutEmptyMeansForever.map(timeout->" Will time out in "+timeout.minus(start.until(TimePoint.now())).toString()).orElse("")
+"; sleeping for "+sleepBetweenAttempts+" now...":""));
}
if (timeForAnotherAttempt) {
Thread.sleep(sleepBetweenAttempts.asMillis());
}
}
} while (!success && timeForAnotherAttempt);
if (!success) {
if (logLevel != null && retryLogMessage != null) {
logger.log(logLevel, retryLogMessage+" timed out.");
}
throw new TimeoutException();
}
return result;
}
}
@@ -30,7 +30,6 @@ import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.KeyPair;
import com.jcraft.jsch.SftpException;
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
import com.sap.sailing.landscape.SailingReleaseRepository;
import com.sap.sailing.landscape.impl.SailingAnalyticsProcessImpl;
@@ -87,7 +86,7 @@ public class ConnectivityTest<ProcessT extends ApplicationProcess<String, Sailin
//@Ignore("Fill in key details for the key used to launch the central reverse proxy in the test landscape")
@Test
public void readAndStoreSSHKey() throws JSchException, IOException, InterruptedException {
public void readAndStoreSSHKey() throws Exception {
final String AXELS_KEY_NAME = "Axel";
final String PATH_TO_YOUR_PRIVATE_KEY = "c:/Users/d043530/.ssh/id_rsa";
landscape.deleteKeyPair(region, AXELS_KEY_NAME);
@@ -149,7 +148,7 @@ public class ConnectivityTest<ProcessT extends ApplicationProcess<String, Sailin
* Requires the key that was used for launching the central reverse proxy for the test landscape to be known in the {@link #landscape}.
*/
@Test
public void testApacheProxyBasics() throws InterruptedException, JSchException, IOException, SftpException {
public void testApacheProxyBasics() throws Exception {
final ReverseProxyCluster<String, SailingAnalyticsMetrics, ProcessT, RotatingFileBasedLog> proxy = landscape.getCentralReverseProxy(region);
final String hostname = "kw2021.sapsailing.com";
final AwsInstance<String, SailingAnalyticsMetrics> proxyHost = proxy.getHosts().iterator().next();
@@ -315,21 +314,21 @@ public class ConnectivityTest<ProcessT extends ApplicationProcess<String, Sailin
}
@Test
public void testSshConnectWithCreatedKey() throws JSchException, InterruptedException, IOException {
public void testSshConnectWithCreatedKey() throws Exception {
final String keyName = "MyKey-"+UUID.randomUUID();
createKeyPair(keyName);
testSshConnectWithKey(keyName);
}
@Test
public void testSshConnectWithImportedKey() throws JSchException, InterruptedException, IOException {
public void testSshConnectWithImportedKey() throws Exception {
final String keyName = "MyKey-"+UUID.randomUUID();
final KeyPair keyPair = KeyPair.genKeyPair(new JSch(), KeyPair.RSA, 4096);
landscape.importKeyPair(region, getPublicKeyBytes(keyPair), getDecryptedPrivateKeyBytes(keyPair, /* passphrase */ null), keyName);
testSshConnectWithKey(keyName);
}
private void testSshConnectWithKey(final String keyName) throws InterruptedException, JSchException, IOException {
private void testSshConnectWithKey(final String keyName) throws Exception {
final AwsInstance<String, SailingAnalyticsMetrics> host = landscape.launchHost(getLatestSailingImage(),
InstanceType.T3_SMALL, landscape.getAvailabilityZoneByName(region, "eu-west-2b"), keyName, Collections.singleton(()->"sg-0b2afd48960251280"), /* tags */ Optional.empty());
try {
@@ -1,10 +1,7 @@
package com.sap.sse.landscape.aws;
import java.io.IOException;
import java.util.Optional;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.sap.sse.common.Duration;
import com.sap.sse.landscape.RotatingFileBasedLog;
import com.sap.sse.landscape.application.ApplicationProcess;
@@ -31,10 +28,8 @@ extends AwsInstance<ShardingKey, MetricsT> {
/**
* Obtains the Sailing Analytics processes running on this host. Can be zero or more.
* @param optionalTimeout TODO
* @param privateKeyEncryptionPassphrase TODO
*/
Iterable<ProcessT> getApplicationProcesses(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws SftpException, JSchException, IOException, InterruptedException;
Iterable<ProcessT> getApplicationProcesses(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
AwsLandscape<ShardingKey, MetricsT, ProcessT> getLandscape();
}
@@ -1,10 +1,8 @@
package com.sap.sse.landscape.aws;
import java.io.IOException;
import java.util.Optional;
import java.util.UUID;
import com.jcraft.jsch.JSchException;
import com.sap.sse.common.Duration;
import com.sap.sse.landscape.Host;
import com.sap.sse.landscape.Log;
@@ -52,54 +50,48 @@ public interface ReverseProxy<ShardingKey, MetricsT extends ApplicationProcessMe
/**
* Configures a redirect in this reverse proxy such that requests for it will go to the
* {@code /index.html} landing page for the application replica set provided.
* @param privateKeyEncryptionPassphrase TODO
*/
void setPlainRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException;
void setPlainRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Configures a redirect in this reverse proxy such that requests for it will go to the
* {@code /gwt/Home.html} landing page for the application replica set provided.
* @param privateKeyEncryptionPassphrase TODO
*/
void setHomeRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException;
void setHomeRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Configures a redirect in this reverse proxy such that requests for it will go to the
* event page for the event with ID {@code eventId} that is expected to be hosted by the
* application replica set provided.
* @param privateKeyEncryptionPassphrase TODO
*/
void setEventRedirect(String hostname, ProcessT applicationProcess, UUID eventId, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException;
void setEventRedirect(String hostname, ProcessT applicationProcess, UUID eventId, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Configures a redirect in this reverse proxy such that requests for it will go to the event series page for the
* event series identified by the UUID of the leaderboard group that represents the series and which is expected to
* be hosted by the application replica set provided.
* @param privateKeyEncryptionPassphrase TODO
*/
void setEventSeriesRedirect(String hostname, ProcessT applicationProcess,
UUID leaderboardGroupId, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException;
UUID leaderboardGroupId, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Configures a rule for requests for anything from within {@code scope} such that those requests
* are sent to the {@code applicationReplicaSet}.
*/
void setScopeRedirect(Scope<ShardingKey> scope, ProcessT applicationProcess) throws InterruptedException, JSchException, IOException;
void setScopeRedirect(Scope<ShardingKey> scope, ProcessT applicationProcess) throws Exception;
/**
* Creates a mapping for the {@code /internal-server-status} path using the host's generic external ec2 host name
* @param privateKeyEncryptionPassphrase TODO
*/
void createInternalStatusRedirect(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException;
void createInternalStatusRedirect(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Removes any existing redirect mapping for the {@code hostname} provided. If no such mapping
* exists, the method does nothing.
* @param privateKeyEncryptionPassphrase TODO
*/
void removeRedirect(String hostname, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException;
void removeRedirect(String hostname, byte[] privateKeyEncryptionPassphrase) throws Exception;
void removeRedirect(Scope<ShardingKey> scope, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException;
void removeRedirect(Scope<ShardingKey> scope, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* {@link AwsLandscape#terminate(AwsInstance) Terminates} all {@link #getHosts() hosts} that form this reverse
@@ -1,6 +1,5 @@
package com.sap.sse.landscape.aws.impl;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Optional;
@@ -8,7 +7,6 @@ import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jcraft.jsch.JSchException;
import com.sap.sse.common.Duration;
import com.sap.sse.landscape.Host;
import com.sap.sse.landscape.RotatingFileBasedLog;
@@ -82,7 +80,7 @@ implements com.sap.sse.landscape.Process<RotatingFileBasedLog, MetricsT> {
private void setRedirect(String configFileNameForHostname, String macroName, String hostname,
byte[] privateKeyEncryptionPassphrase, String... macroArguments)
throws InterruptedException, JSchException, IOException {
throws Exception {
final String command = "echo \"Use " + macroName + " " + hostname + " " + String.join(" ", macroArguments)
+ "\" >" + getConfigFilePath(configFileNameForHostname) + "; service httpd reload";
logger.info("Standard output from setting up the re-direct for " + hostname
@@ -93,7 +91,7 @@ implements com.sap.sse.landscape.Process<RotatingFileBasedLog, MetricsT> {
Level.INFO, privateKeyEncryptionPassphrase));
}
private String runCommandAndReturnStdoutAndStderr(String command, String stderrLogPrefix, Level stderrLogLevel, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException {
private String runCommandAndReturnStdoutAndStderr(String command, String stderrLogPrefix, Level stderrLogLevel, byte[] privateKeyEncryptionPassphrase) throws Exception {
final SshCommandChannel sshChannel = getHost().createRootSshChannel(TIMEOUT, privateKeyEncryptionPassphrase);
final String stdout = sshChannel.runCommandAndReturnStdoutAndLogStderr(command, stderrLogPrefix, stderrLogLevel);
return stdout;
@@ -109,21 +107,21 @@ implements com.sap.sse.landscape.Process<RotatingFileBasedLog, MetricsT> {
}
@Override
public void setPlainRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
public void setPlainRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws Exception {
final String host = applicationProcess.getHost().getPrivateAddress().getHostAddress();
final int port = applicationProcess.getPort();
setRedirect(getConfigFileNameForHostname(hostname), PLAIN_REDIRECT_MACRO, hostname, privateKeyEncryptionPassphrase, host, ""+port);
}
@Override
public void setHomeRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
public void setHomeRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws Exception {
final String host = applicationProcess.getHost().getPrivateAddress().getHostAddress();
final int port = applicationProcess.getPort();
setRedirect(getConfigFileNameForHostname(hostname), HOME_REDIRECT_MACRO, hostname, privateKeyEncryptionPassphrase, host, ""+port);
}
@Override
public void setEventRedirect(String hostname, ProcessT applicationProcess, UUID eventId, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
public void setEventRedirect(String hostname, ProcessT applicationProcess, UUID eventId, byte[] privateKeyEncryptionPassphrase) throws Exception {
final String host = applicationProcess.getHost().getPrivateAddress().getHostAddress();
final int port = applicationProcess.getPort();
setRedirect(getConfigFileNameForHostname(hostname), EVENT_REDIRECT_MACRO, hostname, privateKeyEncryptionPassphrase, eventId.toString(), host, ""+port);
@@ -131,31 +129,31 @@ implements com.sap.sse.landscape.Process<RotatingFileBasedLog, MetricsT> {
@Override
public void setEventSeriesRedirect(String hostname, ProcessT applicationProcess,
UUID leaderboardGroupId, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
UUID leaderboardGroupId, byte[] privateKeyEncryptionPassphrase) throws Exception {
final String host = applicationProcess.getHost().getPrivateAddress().getHostAddress();
final int port = applicationProcess.getPort();
setRedirect(getConfigFileNameForHostname(hostname), SERIES_REDIRECT_MACRO, hostname, privateKeyEncryptionPassphrase, leaderboardGroupId.toString(), host, ""+port);
}
@Override
public void createInternalStatusRedirect(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
public void createInternalStatusRedirect(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception {
setRedirect(CONFIG_FILE_FOR_INTERNALS, STATUS, getHost().getPublicAddress(optionalTimeout).getCanonicalHostName(), privateKeyEncryptionPassphrase, INTERNAL_SERVER_STATUS);
}
@Override
public void removeRedirect(Scope<ShardingKey> scope, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException {
public void removeRedirect(Scope<ShardingKey> scope, byte[] privateKeyEncryptionPassphrase) throws Exception {
final String configFilePath = getConfigFilePath(getConfigFileNameForScope(scope));
removeRedirect(configFilePath, scope.toString(), privateKeyEncryptionPassphrase);
}
@Override
public void removeRedirect(String hostname, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException {
public void removeRedirect(String hostname, byte[] privateKeyEncryptionPassphrase) throws Exception {
final String configFilePath = getConfigFilePath(getConfigFileNameForHostname(hostname));
removeRedirect(configFilePath, hostname, privateKeyEncryptionPassphrase);
}
private void removeRedirect(String configFilePath, String redirectNameForLogOutput,
byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException {
byte[] privateKeyEncryptionPassphrase) throws Exception {
final String command = "rm " + configFilePath + "; service httpd reload";
logger.info("Standard output from removing the re-direct for " + redirectNameForLogOutput
+ " and reloading the Apache httpd server: "
@@ -1,13 +1,11 @@
package com.sap.sse.landscape.aws.impl;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import com.jcraft.jsch.JSchException;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.landscape.Log;
@@ -90,14 +88,14 @@ implements ReverseProxyCluster<ShardingKey, MetricsT, ProcessT, RotatingFileBase
}
@Override
public void setPlainRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
public void setPlainRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws Exception {
for (final ApacheReverseProxy<ShardingKey, MetricsT, ProcessT> proxy : getReverseProxies()) {
proxy.setPlainRedirect(hostname, applicationProcess, privateKeyEncryptionPassphrase);
}
}
@Override
public void setHomeRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
public void setHomeRedirect(String hostname, ProcessT applicationProcess, byte[] privateKeyEncryptionPassphrase) throws Exception {
for (final ApacheReverseProxy<ShardingKey, MetricsT, ProcessT> proxy : getReverseProxies()) {
proxy.setHomeRedirect(hostname, applicationProcess, privateKeyEncryptionPassphrase);
}
@@ -105,7 +103,7 @@ implements ReverseProxyCluster<ShardingKey, MetricsT, ProcessT, RotatingFileBase
@Override
public void setEventRedirect(String hostname, ProcessT applicationProcess,
UUID eventId, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
UUID eventId, byte[] privateKeyEncryptionPassphrase) throws Exception {
for (final ApacheReverseProxy<ShardingKey, MetricsT, ProcessT> proxy : getReverseProxies()) {
proxy.setEventRedirect(hostname, applicationProcess, eventId, privateKeyEncryptionPassphrase);
}
@@ -113,7 +111,7 @@ implements ReverseProxyCluster<ShardingKey, MetricsT, ProcessT, RotatingFileBase
@Override
public void setEventSeriesRedirect(String hostname, ProcessT applicationProcess,
UUID leaderboardGroupId, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
UUID leaderboardGroupId, byte[] privateKeyEncryptionPassphrase) throws Exception {
for (final ApacheReverseProxy<ShardingKey, MetricsT, ProcessT> proxy : getReverseProxies()) {
proxy.setEventSeriesRedirect(hostname, applicationProcess, leaderboardGroupId, privateKeyEncryptionPassphrase);
}
@@ -127,21 +125,21 @@ implements ReverseProxyCluster<ShardingKey, MetricsT, ProcessT, RotatingFileBase
}
@Override
public void createInternalStatusRedirect(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException {
public void createInternalStatusRedirect(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception {
for (final ApacheReverseProxy<ShardingKey, MetricsT, ProcessT> proxy : getReverseProxies()) {
proxy.createInternalStatusRedirect(optionalTimeout, privateKeyEncryptionPassphrase);
}
}
@Override
public void removeRedirect(String hostname, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException {
public void removeRedirect(String hostname, byte[] privateKeyEncryptionPassphrase) throws Exception {
for (final ApacheReverseProxy<ShardingKey, MetricsT, ProcessT> proxy : getReverseProxies()) {
proxy.removeRedirect(hostname, privateKeyEncryptionPassphrase);
}
}
@Override
public void removeRedirect(Scope<ShardingKey> scope, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException {
public void removeRedirect(Scope<ShardingKey> scope, byte[] privateKeyEncryptionPassphrase) throws Exception {
for (final ApacheReverseProxy<ShardingKey, MetricsT, ProcessT> proxy : getReverseProxies()) {
proxy.removeRedirect(scope, privateKeyEncryptionPassphrase);
}
@@ -1,6 +1,5 @@
package com.sap.sse.landscape.aws.impl;
import java.io.IOException;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
@@ -11,8 +10,6 @@ import java.util.logging.Logger;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.sap.sse.common.Duration;
import com.sap.sse.landscape.Host;
import com.sap.sse.landscape.RotatingFileBasedLog;
@@ -60,7 +57,7 @@ implements ApplicationProcessHost<ShardingKey, MetricsT, ProcessT> {
@Override
public Iterable<ProcessT> getApplicationProcesses(Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase)
throws SftpException, JSchException, IOException, InterruptedException {
throws Exception {
final Set<ProcessT> result = new HashSet<>();
final ChannelSftp sftpChannel = createRootSftpChannel(optionalTimeout, privateKeyEncryptionPassphrase);
if (optionalTimeout.isPresent()) {
@@ -1,14 +1,15 @@
package com.sap.sse.landscape.aws.impl;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Optional;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jcraft.jsch.Channel;
@@ -157,7 +158,7 @@ public class AwsInstanceImpl<ShardingKey, MetricsT extends ApplicationProcessMet
*/
@Override
public SshCommandChannel createRootSshChannel(Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException {
byte[] privateKeyEncryptionPassphrase) throws Exception {
return createSshChannel(ROOT_USER_NAME, optionalTimeout, privateKeyEncryptionPassphrase);
}
@@ -174,54 +175,52 @@ public class AwsInstanceImpl<ShardingKey, MetricsT extends ApplicationProcessMet
*/
@Override
public SshCommandChannel createSshChannel(String sshUserName, Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException {
byte[] privateKeyEncryptionPassphrase) throws Exception {
return new SshCommandChannelImpl((ChannelExec) createSshChannelInternal(sshUserName, "exec", optionalTimeout, privateKeyEncryptionPassphrase));
}
private Channel createSshChannelInternal(String sshUserName, String channelType, Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException {
final TimePoint start = TimePoint.now();
byte[] privateKeyEncryptionPassphrase) throws Exception {
logger.info(
"Creating SSH "+channelType+" channel for SSH user "+sshUserName+
" to instance with ID "+getInstanceId());
Channel channel = null;
while (channel == null && (!optionalTimeout.isPresent() || start.until(TimePoint.now()).compareTo(optionalTimeout.get()) < 0)) {
Session session = null;
try {
session = createSshSession(sshUserName, privateKeyEncryptionPassphrase);
session.setUserInfo(new YesUserInfo());
session.connect(optionalTimeout.map(d->d.asMillis()).orElse(0l).intValue());
channel = session.openChannel(channelType);
} catch (JSchException | IllegalStateException e) {
if (session != null) {
session.disconnect();
}
logger.info(e.getMessage()
+ " while trying to connect. Probably timeout trying early SSH connection.");
Thread.sleep(5000); // wait a bit for the service to become available
}
if (channel == null) {
if (optionalTimeout.isPresent()) {
logger.info("Retrying until "+start.plus(optionalTimeout.get()));
} else {
logger.info("Retrying forever");
}
}
Channel result;
try {
result = Util.wait(()->{
Session session = null;
try {
session = createSshSession(sshUserName, privateKeyEncryptionPassphrase);
session.setUserInfo(new YesUserInfo());
session.connect(optionalTimeout.map(d->d.asMillis()).orElse(0l).intValue());
return session.openChannel(channelType);
} catch (JSchException | IllegalStateException e) {
if (session != null) {
session.disconnect();
}
throw e;
}
},
channel->channel != null,
/* retryOnException */ true, optionalTimeout,
Duration.ONE_SECOND.times(5), Level.INFO,
"Trying to connect to " + getInstanceId() + " with user " + sshUserName + " using SSH");
} catch (TimeoutException timeout) {
result = null;
}
return channel;
return result;
}
@Override
public ChannelSftp createSftpChannel(String sshUserName, Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException {
byte[] privateKeyEncryptionPassphrase) throws Exception {
return (ChannelSftp) createSshChannelInternal(sshUserName, "sftp", optionalTimeout,
privateKeyEncryptionPassphrase);
}
@Override
public ChannelSftp createRootSftpChannel(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase)
throws JSchException, IOException, InterruptedException {
throws Exception {
return createSftpChannel(ROOT_USER_NAME, optionalTimeout, privateKeyEncryptionPassphrase);
}
@@ -1,6 +1,5 @@
package com.sap.sse.landscape.aws.orchestration;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
@@ -12,7 +11,6 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jcraft.jsch.JSchException;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.landscape.AvailabilityZone;
@@ -382,7 +380,7 @@ extends StartHost<ShardingKey, MetricsT, ProcessT, HostT> {
}
protected void copyRootAuthorizedKeysToOtherUser(String username, Optional<Duration> optionalTimeout)
throws JSchException, IOException, InterruptedException {
throws Exception {
final SshCommandChannel sshChannel = getHost().createRootSshChannel(optionalTimeout, getPrivateKeyEncryptionPassphrase());
final String sailingUserSsh = "/home/" + username + "/.ssh";
final String sailingUserAuthorizedKeys = sailingUserSsh + "/authorized_keys";
@@ -3,8 +3,11 @@ package com.sap.sse.landscape.aws.orchestration;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Optional;
import java.util.logging.Level;
import com.jcraft.jsch.JSchException;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.landscape.Host;
import com.sap.sse.landscape.ProcessConfigurationVariable;
@@ -21,6 +24,7 @@ import com.sap.sse.landscape.mongodb.impl.MongoProcessImpl;
import com.sap.sse.landscape.mongodb.impl.MongoProcessInReplicaSetImpl;
import com.sap.sse.landscape.orchestration.StartHost;
import software.amazon.awssdk.services.ec2.model.InstanceStateName;
import software.amazon.awssdk.services.ec2.model.InstanceType;
/**
@@ -57,6 +61,8 @@ extends StartAwsHost<ShardingKey, MetricsT, ProcessT, AwsInstance<ShardingKey, M
private MongoProcess mongoProcess;
private final String replicaSetName;
private final Optional<Duration> optionalTimeout;
/**
* In order to launch a standalone instance, call {@link #setReplicaSetName(String)} with {@code null} as a
@@ -220,6 +226,14 @@ extends StartAwsHost<ShardingKey, MetricsT, ProcessT, AwsInstance<ShardingKey, M
}
return new StartMongoDBServer<>(this);
}
/**
* Re-expose the method declared protected in a different package to the local procedure
*/
@Override
protected Optional<Duration> getOptionalTimeout() {
return super.getOptionalTimeout();
}
}
public static <BuilderT extends Builder<BuilderT, ShardingKey, MetricsT, ProcessT>,ShardingKey, MetricsT extends ApplicationProcessMetrics,
@@ -239,6 +253,7 @@ extends StartAwsHost<ShardingKey, MetricsT, ProcessT, AwsInstance<ShardingKey, M
}
addUserData(MongoDBReplicaSetUserData.REPLICA_SET_PRIORITY, Integer.toString(builder.getReplicaSetPriority()));
addUserData(MongoDBReplicaSetUserData.REPLICA_SET_VOTES, Integer.toString(builder.getReplicaSetVotes()));
this.optionalTimeout = builder.getOptionalTimeout();
}
/**
@@ -254,6 +269,12 @@ extends StartAwsHost<ShardingKey, MetricsT, ProcessT, AwsInstance<ShardingKey, M
if (replicaSetName == null) {
mongoProcess = new MongoProcessImpl(getHost());
} else {
// the host may not yet be in state RUNNING; we'd like to wait for this:
boolean running = Util.wait(()->getLandscape().getInstance(getHost().getInstanceId(), getHost().getRegion()).state().name() == InstanceStateName.RUNNING,
optionalTimeout, Duration.ONE_SECOND.times(5), Level.INFO, "Waiting for host "+getHost().getInstanceId()+" to be in state RUNNING");
if (!running) {
throw new IllegalStateException("The host launched did not reach state RUNNING"+optionalTimeout.map(d->" within timeout "+d).orElse(""));
}
final MongoReplicaSet replicaSet = getLandscape().getDatabaseConfigurationForReplicaSet(getHost().getRegion(), replicaSetName);
final Host instance = Util.stream(replicaSet.getInstances()).filter(replica->replica.getHost().equals(getHost())).map(replica->replica.getHost()).findAny().get();
mongoProcess = new MongoProcessInReplicaSetImpl(replicaSet, MongoProcess.DEFAULT_PORT, instance);
@@ -1,7 +1,6 @@
package com.sap.sse.landscape;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.InetAddress;
@@ -9,7 +8,6 @@ import java.util.Optional;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.sap.sse.common.Duration;
import com.sap.sse.landscape.ssh.SshCommandChannel;
@@ -60,7 +58,7 @@ public interface Host {
* @param privateKeyEncryptionPassphrase
* the pass phrase for the private key that belongs to the instance's public key used for start-up
*/
SshCommandChannel createSshChannel(String sshUserName, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException;
SshCommandChannel createSshChannel(String sshUserName, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Connects to an SSH session for the "root" user with a "shell" channel
@@ -70,19 +68,19 @@ public interface Host {
*
* @see #createSshChannel(String, Optional, byte[])
*/
SshCommandChannel createRootSshChannel(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException;
SshCommandChannel createRootSshChannel(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* @param privateKeyEncryptionPassphrase
* the pass phrase for the private key that belongs to the instance's public key used for start-up
*/
ChannelSftp createSftpChannel(String sshUserName, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException;
ChannelSftp createSftpChannel(String sshUserName, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* @param privateKeyEncryptionPassphrase
* the pass phrase for the private key that belongs to the instance's public key used for start-up
*/
ChannelSftp createRootSftpChannel(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException;
ChannelSftp createRootSftpChannel(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Tells where in the cloud this host runs; the availability zone {@link AvailabilityZone#getRegion() implies} the
@@ -8,8 +8,6 @@ import java.util.Optional;
import java.util.logging.Logger;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.landscape.Process;
@@ -29,10 +27,9 @@ extends Process<RotatingFileBasedLog, MetricsT> {
* @param releaseRepository
* mandatory parameter required to enable resolving the release and enabling the download of its
* artifacts, including its release notes
* @param privateKeyEncryptionPassphrase TODO
* @return the release that this process is currently running
*/
Release getRelease(ReleaseRepository releaseRepository, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException;
Release getRelease(ReleaseRepository releaseRepository, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* Tries to shut down an OSGi application server process cleanly by sending the "shutdown" OSGi command to this
@@ -49,7 +46,7 @@ extends Process<RotatingFileBasedLog, MetricsT> {
*/
boolean tryCleanShutdown(Duration timeout, boolean forceAfterTimeout);
int getTelnetPortToOSGiConsole(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws NumberFormatException, JSchException, IOException, SftpException, InterruptedException;
int getTelnetPortToOSGiConsole(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* @return the directory as an absolute path that can be used, e.g., in a {@link ChannelSftp} to change directory to
@@ -63,11 +60,10 @@ extends Process<RotatingFileBasedLog, MetricsT> {
* as the base name of the {@link #getServerDirectory() server's directory}. Often, it is also used as the name of
* the {@link Database}, at least when this is a master node, and the name of the RabbitMQ fan-out exchange used
* for replication.
* @param privateKeyEncryptionPassphrase TODO
*/
String getServerName(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
String getEnvSh(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException;
String getEnvSh(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception;
/**
* The URL path (everything following the hostname and starting with "/" but without any fragment) that can be
@@ -82,18 +78,17 @@ extends Process<RotatingFileBasedLog, MetricsT> {
/**
* Obtains the last definition of the process configuration variable specified, or {@code null} if that variable cannot be found
* in the evaluated {@code env.sh} file.
* @param privateKeyEncryptionPassphrase TODO
* @throws Exception
*/
String getEnvShValueFor(ProcessConfigurationVariable variable, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase)
throws JSchException, IOException, InterruptedException;
throws Exception;
/**
* Obtains the last definition of the process configuration variable specified, or {@code null} if that variable isn't set
* by evaluating the {@code env.sh} file on the {@link #getHost() host}.
* @param privateKeyEncryptionPassphrase TODO
*/
String getEnvShValueFor(String variableName, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase)
throws JSchException, IOException, InterruptedException;
throws Exception;
/**
* Tells whether this process is ready to accept requests. Use this for a health check in a target group
@@ -19,8 +19,6 @@ import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.landscape.DefaultProcessConfigurationVariables;
@@ -56,7 +54,7 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
* @param privateKeyEncryptionPassphrase
* the pass phrase for the private key that belongs to the instance's public key used for start-up
*/
public ApplicationProcessImpl(Host host, String serverDirectory, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws NumberFormatException, JSchException, IOException, InterruptedException {
public ApplicationProcessImpl(Host host, String serverDirectory, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception {
this(readPortFromDirectory(host, serverDirectory, optionalTimeout, privateKeyEncryptionPassphrase), host, serverDirectory);
}
@@ -67,7 +65,7 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
private static int readPortFromDirectory(Host host, String serverDirectory, Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase)
throws NumberFormatException, JSchException, IOException, InterruptedException {
throws Exception {
return Integer.parseInt(
getEnvShValueFor(host, serverDirectory, DefaultProcessConfigurationVariables.SERVER_PORT.name(),
optionalTimeout, privateKeyEncryptionPassphrase));
@@ -76,7 +74,7 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
@Override
public Release getRelease(ReleaseRepository releaseRepository, Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase)
throws JSchException, IOException, SftpException, InterruptedException {
throws Exception {
final Pattern pattern = Pattern.compile("^[^-]*-([^ ]*) System:");
final Matcher matcher = pattern.matcher(getVersionTxt(optionalTimeout, privateKeyEncryptionPassphrase));
final Release result;
@@ -99,7 +97,7 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
* @param privateKeyEncryptionPassphrase
* the pass phrase for the private key that belongs to the instance's public key used for start-up
*/
private String getVersionTxt(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException {
private String getVersionTxt(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception {
return getFileContents(getServerDirectory()+"/"+VERSION_TXT, optionalTimeout, privateKeyEncryptionPassphrase);
}
@@ -111,7 +109,7 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
@Override
public int getTelnetPortToOSGiConsole(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase)
throws NumberFormatException, JSchException, IOException, SftpException, InterruptedException {
throws Exception {
return Integer.parseInt(getEnvShValueFor(DefaultProcessConfigurationVariables.TELNET_PORT, optionalTimeout,
privateKeyEncryptionPassphrase));
}
@@ -122,13 +120,13 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
*/
@Override
public String getEnvShValueFor(String variableName, Optional<Duration> optionalTimeout,
byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException {
byte[] privateKeyEncryptionPassphrase) throws Exception {
return getEnvShValueFor(getHost(), getServerDirectory(), variableName, optionalTimeout, privateKeyEncryptionPassphrase);
}
protected static String getEnvShValueFor(Host host, String serverDirectory, String variableName,
Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase)
throws JSchException, IOException, InterruptedException {
throws Exception {
final SshCommandChannel sshChannel = host.createRootSshChannel(optionalTimeout, privateKeyEncryptionPassphrase);
final String variableValue = sshChannel.runCommandAndReturnStdoutAndLogStderr(". "+getEnvShPath(serverDirectory)+">/dev/null 2>/dev/null; "+
"echo \"${"+variableName+"}\"", /* stderr prefix */ null, /* stderr log level */ null);
@@ -140,7 +138,7 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
* in the evaluated {@code env.sh} file.
*/
@Override
public String getEnvShValueFor(ProcessConfigurationVariable variable, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException {
public String getEnvShValueFor(ProcessConfigurationVariable variable, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception {
return getEnvShValueFor(variable.name(), optionalTimeout, privateKeyEncryptionPassphrase);
}
@@ -163,12 +161,12 @@ implements ApplicationProcess<ShardingKey, MetricsT, ProcessT> {
}
@Override
public String getEnvSh(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException {
public String getEnvSh(Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception {
return getFileContents(getEnvShPath(), optionalTimeout, privateKeyEncryptionPassphrase);
}
protected String getFileContents(String path, Optional<Duration> optionalTimeout, byte[] privateKeyEncryptionPassphrase)
throws JSchException, IOException, SftpException, InterruptedException {
throws Exception {
final ChannelSftp sftpChannel = getHost().createRootSftpChannel(optionalTimeout, privateKeyEncryptionPassphrase);
final ByteArrayOutputStream bos = new ByteArrayOutputStream();
sftpChannel.connect((int) optionalTimeout.orElse(Duration.NULL).asMillis());