mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-15 06:49:56 +00:00
bug4811: implemented Util.wait in different variants and used in a few places
This commit is contained in:
1 parent
b8c9848a33
commit
ca1108b2d1
20 files changed
+219
-140
No files matched your search
+1
-1
@@ -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
-4
@@ -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));
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+3
-8
@@ -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
-3
@@ -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
-3
@@ -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
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
+5
-6
@@ -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
-6
@@ -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
|
||||
|
||||
+10
-12
@@ -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: "
|
||||
|
||||
+7
-9
@@ -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
-4
@@ -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()) {
|
||||
|
||||
+30
-31
@@ -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
-3
@@ -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";
|
||||
|
||||
+21
@@ -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
|
||||
|
||||
+6
-11
@@ -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
|
||||
|
||||
+10
-12
@@ -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());
|
||||
|
||||
Reference in new issue
Block a user