diff --git a/java/com.sap.sailing.landscape.test/src/com/sap/sailing/landscape/test/TestProcedures.java b/java/com.sap.sailing.landscape.test/src/com/sap/sailing/landscape/test/TestProcedures.java index df3f7608df6..56e51d79a65 100755 --- a/java/com.sap.sailing.landscape.test/src/com/sap/sailing/landscape/test/TestProcedures.java +++ b/java/com.sap.sailing.landscape.test/src/com/sap/sailing/landscape/test/TestProcedures.java @@ -164,7 +164,7 @@ public class TestProcedures { landscape.getApplicationReplicaSetsByTag(region, sailingAnalyticsServerTag, (theHost, dir)->{ try { return new SailingAnalyticsProcessImpl(theHost, dir, optionalTimeout, privateKeyEncryptionPassphrase); - } catch (NumberFormatException | JSchException | IOException | InterruptedException e) { + } catch (Exception e) { throw new RuntimeException(e); } }, optionalTimeout, privateKeyEncryptionPassphrase); diff --git a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/SailingAnalyticsProcess.java b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/SailingAnalyticsProcess.java index c537ae7791a..8d4f8a471ce 100755 --- a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/SailingAnalyticsProcess.java +++ b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/SailingAnalyticsProcess.java @@ -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 extends ApplicationProcess static String HEALTH_CHECK_PATH = "/gwt/status"; default int getExpeditionUdpPort(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) - throws NumberFormatException, JSchException, IOException, InterruptedException, SftpException { + throws Exception { return Integer.parseInt(getEnvShValueFor(SailingAnalyticsProcessConfigurationVariable.EXPEDITION_PORT.name(), optionalTimeout, privateKeyEncryptionPassphrase)); } diff --git a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/SailingAnalyticsProcessImpl.java b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/SailingAnalyticsProcessImpl.java index 960cf8ebf18..6739dcfbc0b 100755 --- a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/SailingAnalyticsProcessImpl.java +++ b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/SailingAnalyticsProcessImpl.java @@ -34,7 +34,7 @@ implements SailingAnalyticsProcess { */ public SailingAnalyticsProcessImpl(Host host, String serverDirectory, Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) - throws NumberFormatException, JSchException, IOException, InterruptedException { + throws Exception { super(host, serverDirectory, optionalTimeout, privateKeyEncryptionPassphrase); } diff --git a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/DeployProcessOnMultiServer.java b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/DeployProcessOnMultiServer.java index 4952af4dafa..8111c06519a 100755 --- a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/DeployProcessOnMultiServer.java +++ b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/DeployProcessOnMultiServer.java @@ -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{ 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{ 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>(instanceId, az, landscape, (host, serverDirectory)->{ try { return new SailingAnalyticsProcessImpl(host, serverDirectory, getOptionalTimeout(), getPrivateKeyEncryptionPassphrase()); - } catch (NumberFormatException | JSchException | IOException | InterruptedException e) { + } catch (Exception e) { throw new RuntimeException(e); } }); diff --git a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/StartSailingAnalyticsHost.java b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/StartSailingAnalyticsHost.java index bf65e408d19..ae6ca35ce8a 100755 --- a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/StartSailingAnalyticsHost.java +++ b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/StartSailingAnalyticsHost.java @@ -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{ try { return new SailingAnalyticsProcessImpl(host, serverDirectory, getOptionalTimeout(), getPrivateKeyEncryptionPassphrase()); - } catch (NumberFormatException | JSchException | IOException | InterruptedException e) { + } catch (Exception e) { throw new RuntimeException(e); } }); diff --git a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/UpgradeAmi.java b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/UpgradeAmi.java index daed83d634d..0511782b73f 100755 --- a/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/UpgradeAmi.java +++ b/java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/procedures/UpgradeAmi.java @@ -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{ try { return new SailingAnalyticsProcessImpl(host, serverDirectory, getOptionalTimeout(), getPrivateKeyEncryptionPassphrase()); - } catch (NumberFormatException | JSchException | IOException | InterruptedException e) { + } catch (Exception e) { throw new RuntimeException(e); } }); diff --git a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java index c871b2c94d5..c11c4e63f39 100755 --- a/java/com.sap.sse.common/src/com/sap/sse/common/Util.java +++ b/java/com.sap.sse.common/src/com/sap/sse/common/Util.java @@ -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 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 condition, Optional 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}.

+ * + * Any exception thrown during the evaluation of {@code condition} will pass the exception on to the caller.

+ * + * 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 condition, Optional 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}. + *

+ * + * 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. + *

+ * + * 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 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 wait(Callable callable, Predicate successPredicate, boolean retryOnException, + Optional 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; + } } \ No newline at end of file diff --git a/java/com.sap.sse.landscape.aws.test/src/com/sap/sse/landscape/aws/ConnectivityTest.java b/java/com.sap.sse.landscape.aws.test/src/com/sap/sse/landscape/aws/ConnectivityTest.java index 24d4ee68d0a..9e4bbf63235 100755 --- a/java/com.sap.sse.landscape.aws.test/src/com/sap/sse/landscape/aws/ConnectivityTest.java +++ b/java/com.sap.sse.landscape.aws.test/src/com/sap/sse/landscape/aws/ConnectivityTest.java @@ -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 proxy = landscape.getCentralReverseProxy(region); final String hostname = "kw2021.sapsailing.com"; final AwsInstance proxyHost = proxy.getHosts().iterator().next(); @@ -315,21 +314,21 @@ public class ConnectivityTest host = landscape.launchHost(getLatestSailingImage(), InstanceType.T3_SMALL, landscape.getAvailabilityZoneByName(region, "eu-west-2b"), keyName, Collections.singleton(()->"sg-0b2afd48960251280"), /* tags */ Optional.empty()); try { diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ApplicationProcessHost.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ApplicationProcessHost.java index 64717710fae..c6a656e3a29 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ApplicationProcessHost.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ApplicationProcessHost.java @@ -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 { /** * Obtains the Sailing Analytics processes running on this host. Can be zero or more. - * @param optionalTimeout TODO - * @param privateKeyEncryptionPassphrase TODO */ - Iterable getApplicationProcesses(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws SftpException, JSchException, IOException, InterruptedException; + Iterable getApplicationProcesses(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception; AwsLandscape getLandscape(); } diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ReverseProxy.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ReverseProxy.java index f9048cbd7bc..41713b9e166 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ReverseProxy.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/ReverseProxy.java @@ -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 scope, ProcessT applicationProcess) throws InterruptedException, JSchException, IOException; + void setScopeRedirect(Scope 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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException; + void createInternalStatusRedirect(Optional 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 scope, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException; + void removeRedirect(Scope scope, byte[] privateKeyEncryptionPassphrase) throws Exception; /** * {@link AwsLandscape#terminate(AwsInstance) Terminates} all {@link #getHosts() hosts} that form this reverse diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxy.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxy.java index 3568a842686..5e6b6aa0fa1 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxy.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxy.java @@ -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 { 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 { 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 { } @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 { @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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException { + public void createInternalStatusRedirect(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception { setRedirect(CONFIG_FILE_FOR_INTERNALS, STATUS, getHost().getPublicAddress(optionalTimeout).getCanonicalHostName(), privateKeyEncryptionPassphrase, INTERNAL_SERVER_STATUS); } @Override - public void removeRedirect(Scope scope, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException { + public void removeRedirect(Scope 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: " diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxyCluster.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxyCluster.java index 3d2c71c4d6d..fdc04714ca2 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxyCluster.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxyCluster.java @@ -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 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 proxy : getReverseProxies()) { proxy.setHomeRedirect(hostname, applicationProcess, privateKeyEncryptionPassphrase); } @@ -105,7 +103,7 @@ implements ReverseProxyCluster proxy : getReverseProxies()) { proxy.setEventRedirect(hostname, applicationProcess, eventId, privateKeyEncryptionPassphrase); } @@ -113,7 +111,7 @@ implements ReverseProxyCluster proxy : getReverseProxies()) { proxy.setEventSeriesRedirect(hostname, applicationProcess, leaderboardGroupId, privateKeyEncryptionPassphrase); } @@ -127,21 +125,21 @@ implements ReverseProxyCluster optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws InterruptedException, JSchException, IOException { + public void createInternalStatusRedirect(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception { for (final ApacheReverseProxy 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 proxy : getReverseProxies()) { proxy.removeRedirect(hostname, privateKeyEncryptionPassphrase); } } @Override - public void removeRedirect(Scope scope, byte[] privateKeyEncryptionPassphrase) throws IOException, InterruptedException, JSchException { + public void removeRedirect(Scope scope, byte[] privateKeyEncryptionPassphrase) throws Exception { for (final ApacheReverseProxy proxy : getReverseProxies()) { proxy.removeRedirect(scope, privateKeyEncryptionPassphrase); } diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApplicationProcessHostImpl.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApplicationProcessHostImpl.java index 973d04955bd..423b6e849a0 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApplicationProcessHostImpl.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApplicationProcessHostImpl.java @@ -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 { @Override public Iterable getApplicationProcesses(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) - throws SftpException, JSchException, IOException, InterruptedException { + throws Exception { final Set result = new HashSet<>(); final ChannelSftp sftpChannel = createRootSftpChannel(optionalTimeout, privateKeyEncryptionPassphrase); if (optionalTimeout.isPresent()) { diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsInstanceImpl.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsInstanceImpl.java index 5cebde8603a..fbd83af22e5 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsInstanceImpl.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsInstanceImpl.java @@ -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 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 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 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 optionalTimeout, - byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException { + byte[] privateKeyEncryptionPassphrase) throws Exception { return (ChannelSftp) createSshChannelInternal(sshUserName, "sftp", optionalTimeout, privateKeyEncryptionPassphrase); } @Override public ChannelSftp createRootSftpChannel(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) - throws JSchException, IOException, InterruptedException { + throws Exception { return createSftpChannel(ROOT_USER_NAME, optionalTimeout, privateKeyEncryptionPassphrase); } diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartAwsHost.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartAwsHost.java index b390df2508c..4db19a1cfc5 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartAwsHost.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartAwsHost.java @@ -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 { } protected void copyRootAuthorizedKeysToOtherUser(String username, Optional 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"; diff --git a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartMongoDBServer.java b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartMongoDBServer.java index d431d1d1643..183b9ada14e 100755 --- a/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartMongoDBServer.java +++ b/java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/StartMongoDBServer.java @@ -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 optionalTimeout; /** * In order to launch a standalone instance, call {@link #setReplicaSetName(String)} with {@code null} as a @@ -220,6 +226,14 @@ extends StartAwsHost(this); } + + /** + * Re-expose the method declared protected in a different package to the local procedure + */ + @Override + protected Optional getOptionalTimeout() { + return super.getOptionalTimeout(); + } } public static ,ShardingKey, MetricsT extends ApplicationProcessMetrics, @@ -239,6 +253,7 @@ extends StartAwsHostgetLandscape().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); diff --git a/java/com.sap.sse.landscape/src/com/sap/sse/landscape/Host.java b/java/com.sap.sse.landscape/src/com/sap/sse/landscape/Host.java index e96ccd953d7..5eda7af2856 100755 --- a/java/com.sap.sse.landscape/src/com/sap/sse/landscape/Host.java +++ b/java/com.sap.sse.landscape/src/com/sap/sse/landscape/Host.java @@ -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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException; + SshCommandChannel createSshChannel(String sshUserName, Optional 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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException; + SshCommandChannel createRootSshChannel(Optional 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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException; + ChannelSftp createSftpChannel(String sshUserName, Optional 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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException; + ChannelSftp createRootSftpChannel(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception; /** * Tells where in the cloud this host runs; the availability zone {@link AvailabilityZone#getRegion() implies} the diff --git a/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/ApplicationProcess.java b/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/ApplicationProcess.java index 520c41b206b..74d0e3001e2 100755 --- a/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/ApplicationProcess.java +++ b/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/ApplicationProcess.java @@ -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 { * @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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException; + Release getRelease(ReleaseRepository releaseRepository, Optional 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 { */ boolean tryCleanShutdown(Duration timeout, boolean forceAfterTimeout); - int getTelnetPortToOSGiConsole(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws NumberFormatException, JSchException, IOException, SftpException, InterruptedException; + int getTelnetPortToOSGiConsole(Optional 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 { * 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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception; - String getEnvSh(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException; + String getEnvSh(Optional 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 { /** * 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 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 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 diff --git a/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/impl/ApplicationProcessImpl.java b/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/impl/ApplicationProcessImpl.java index b2b0441c2c2..87132113e34 100755 --- a/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/impl/ApplicationProcessImpl.java +++ b/java/com.sap.sse.landscape/src/com/sap/sse/landscape/application/impl/ApplicationProcessImpl.java @@ -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 { * @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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws NumberFormatException, JSchException, IOException, InterruptedException { + public ApplicationProcessImpl(Host host, String serverDirectory, Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception { this(readPortFromDirectory(host, serverDirectory, optionalTimeout, privateKeyEncryptionPassphrase), host, serverDirectory); } @@ -67,7 +65,7 @@ implements ApplicationProcess { private static int readPortFromDirectory(Host host, String serverDirectory, Optional 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 { @Override public Release getRelease(ReleaseRepository releaseRepository, Optional 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 { * @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 optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException { + private String getVersionTxt(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception { return getFileContents(getServerDirectory()+"/"+VERSION_TXT, optionalTimeout, privateKeyEncryptionPassphrase); } @@ -111,7 +109,7 @@ implements ApplicationProcess { @Override public int getTelnetPortToOSGiConsole(Optional 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 { */ @Override public String getEnvShValueFor(String variableName, Optional 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 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 { * in the evaluated {@code env.sh} file. */ @Override - public String getEnvShValueFor(ProcessConfigurationVariable variable, Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, InterruptedException { + public String getEnvShValueFor(ProcessConfigurationVariable variable, Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception { return getEnvShValueFor(variable.name(), optionalTimeout, privateKeyEncryptionPassphrase); } @@ -163,12 +161,12 @@ implements ApplicationProcess { } @Override - public String getEnvSh(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws JSchException, IOException, SftpException, InterruptedException { + public String getEnvSh(Optional optionalTimeout, byte[] privateKeyEncryptionPassphrase) throws Exception { return getFileContents(getEnvShPath(), optionalTimeout, privateKeyEncryptionPassphrase); } protected String getFileContents(String path, Optional 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());