mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-13 14:12:11 +00:00
bug4811: interims commit, started with StartMongoDBServer procedure and refined UpgradeAmi procedure
This commit is contained in:
1 parent
920020b6a3
commit
1be2ee9215
16 files changed
+327
-35
No files matched your search
@@ -7,4 +7,5 @@ Bundle-Vendor: SAP
|
||||
Fragment-Host: com.sap.sailing.landscape
|
||||
Automatic-Module-Name: com.sap.sailing.landscape.test
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: org.junit
|
||||
Require-Bundle: org.junit,
|
||||
org.mongodb.mongo-java-driver
|
||||
+30
@@ -5,15 +5,19 @@ import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bson.Document;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.client.MongoDatabase;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsHost;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMaster;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
|
||||
@@ -23,11 +27,15 @@ import com.sap.sailing.landscape.procedures.StartSailingAnalyticsMaster;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.landscape.InboundReplicationConfiguration;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
import com.sap.sse.landscape.aws.orchestration.CreateDynamicLoadBalancerMapping;
|
||||
import com.sap.sse.landscape.aws.orchestration.StartMongoDBServer;
|
||||
import com.sap.sse.landscape.aws.orchestration.StartMongoDBServer.Builder;
|
||||
import com.sap.sse.landscape.mongodb.MongoEndpoint;
|
||||
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.ec2.model.Instance;
|
||||
@@ -59,6 +67,28 @@ public class TestProcedures {
|
||||
securityServiceReplicationBearerToken = System.getProperty(SECURITY_SERVICE_REPLICATION_BEARER_TOKEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMongoReplica() throws Exception {
|
||||
final Builder<String, ApplicationProcessMetrics, ?, ?> startMongoDBServerProcedureBuilder = StartMongoDBServer.builder();
|
||||
final StartMongoDBServer<String, ApplicationProcessMetrics, ?, ?> startMongoDBServerProcedure = startMongoDBServerProcedureBuilder.build();
|
||||
// by default this should add a replica to the only "live" server in the test landscape
|
||||
try {
|
||||
startMongoDBServerProcedure.run();
|
||||
final AwsInstance<String, ApplicationProcessMetrics> host = startMongoDBServerProcedure.getHost();
|
||||
final String internalDNSName = landscape.getInstance(host.getInstanceId(), region).privateDnsName();
|
||||
// now configure a MongoEndpoint against the replica just launched and try to connect (with a timeout)
|
||||
final MongoEndpoint mongoEndpoint = landscape.getDatabaseConfigurationForDefaultReplicaSet(region);
|
||||
final MongoClient mongoClient = mongoEndpoint.getClient();
|
||||
final MongoDatabase database = mongoClient.getDatabase("admin");
|
||||
final Document replicaSetStatus = database.runCommand(new Document("replSetGetStatus", 1));
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Document> members = (List<Document>) replicaSetStatus.get("members");
|
||||
assertTrue(members.stream().filter(member->member.get("name").equals(internalDNSName+":27017")).findAny().isPresent());
|
||||
} finally {
|
||||
startMongoDBServerProcedure.getHost().terminate();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectivity() throws Exception {
|
||||
final String serverName = "test"+new Random().nextInt();
|
||||
|
||||
+3
-1
@@ -36,6 +36,8 @@ implements Procedure<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
* <ul>
|
||||
* <li>If no {@link #getInstanceName() instance name} is set, the default instance name will be constructed as
|
||||
* {@code IMAGE_UPGRADE+" for "+machineImage.getId()}</li>
|
||||
* <li>The {@link #isNoShutdown()} defaults to {@code true} because "starting" a server is what the {@link StartEmptyServer}
|
||||
* procedure is meant to do. Specialized builders may change this default.</li>
|
||||
* <li>The user data are set to the string defined by {@link StartEmptyServer#IMAGE_UPGRADE_USER_DATA}, forcing the image to
|
||||
* boot without trying to launch a process instance.</li>
|
||||
* </ul>
|
||||
@@ -57,7 +59,7 @@ implements Procedure<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
HostT extends AwsInstance<ShardingKey, MetricsT>>
|
||||
extends StartAwsHost.BuilderImpl<StartEmptyServer<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>
|
||||
implements Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT> {
|
||||
private boolean noShutdown;
|
||||
private boolean noShutdown = true;
|
||||
|
||||
@Override
|
||||
public boolean isNoShutdown() {
|
||||
|
||||
+14
-13
@@ -12,8 +12,8 @@ import com.sap.sailing.landscape.SailingReleaseRepository;
|
||||
import com.sap.sailing.landscape.impl.SailingAnalyticsHostImpl;
|
||||
import com.sap.sse.landscape.ProcessConfigurationVariable;
|
||||
import com.sap.sse.landscape.Release;
|
||||
import com.sap.sse.landscape.aws.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.HostSupplier;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.orchestration.StartAwsHost;
|
||||
import com.sap.sse.landscape.orchestration.Procedure;
|
||||
|
||||
@@ -35,7 +35,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaste
|
||||
private final static String EXPEDITION_PORT_USER_DATA_NAME = "EXPEDITION_PORT";
|
||||
private final int DEFAULT_PORT = 8888;
|
||||
private final Integer port;
|
||||
private final String serverDirectory;
|
||||
private final String defaultServerDirectory;
|
||||
|
||||
/**
|
||||
* The following defaults, in addition to the defaults implemented by the more general {@link StartAwsHost.Builder},
|
||||
@@ -49,7 +49,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaste
|
||||
* <li>If no {@link Release} is explicitly {@link #setRelease set}, or that {@link Optional} is empty,
|
||||
* {@link SailingReleaseRepository#INSTANCE}{@link SailingReleaseRepository#getLatestMasterRelease()
|
||||
* getLatestMasterRelease()} will be used instead.</li>
|
||||
* <li>The {@link #getServerDirectory() server directory} defaults to {@link /home/sailing/servers/server}</li>
|
||||
* <li>The {@link #getDefaultServerDirectory() server directory} defaults to {@link /home/sailing/servers/server}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
@@ -68,9 +68,9 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaste
|
||||
|
||||
Builder<T, ShardingKey, ProcessT> setExpeditionPort(int expeditionPort);
|
||||
|
||||
String getServerDirectory();
|
||||
String getDefaultServerDirectory();
|
||||
|
||||
Builder<T, ShardingKey, ProcessT> setServerDirectory(String serverDirectory);
|
||||
Builder<T, ShardingKey, ProcessT> setDefaultServerDirectory(String serverDirectory);
|
||||
}
|
||||
|
||||
protected abstract static class BuilderImpl<T extends StartSailingAnalyticsHost<ShardingKey, ProcessT>, ShardingKey, ProcessT extends SailingAnalyticsProcess<ShardingKey>>
|
||||
@@ -79,7 +79,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaste
|
||||
private Integer port;
|
||||
private Integer telnetPort;
|
||||
private Integer expeditionPort;
|
||||
private String serverDirectory;
|
||||
private String defaultServerDirectory;
|
||||
|
||||
@Override
|
||||
public String getImageType() {
|
||||
@@ -134,14 +134,15 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaste
|
||||
return this;
|
||||
}
|
||||
|
||||
// TODO the host start-up should ideally be separated from the process installation/startup
|
||||
@Override
|
||||
public String getServerDirectory() {
|
||||
return serverDirectory == null ? "/home/sailing/servers/server" : serverDirectory;
|
||||
public String getDefaultServerDirectory() {
|
||||
return defaultServerDirectory == null ? "/home/sailing/servers/server" : defaultServerDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<T, ShardingKey, ProcessT> setServerDirectory(String serverDirectory) {
|
||||
this.serverDirectory = serverDirectory;
|
||||
public Builder<T, ShardingKey, ProcessT> setDefaultServerDirectory(String defaultServerDirectory) {
|
||||
this.defaultServerDirectory = defaultServerDirectory;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -150,7 +151,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaste
|
||||
super(builder);
|
||||
// remember the port we need in order to hand out the process
|
||||
this.port = builder.getPort();
|
||||
this.serverDirectory = builder.getServerDirectory();
|
||||
this.defaultServerDirectory = builder.getDefaultServerDirectory();
|
||||
if (builder.getPort() != null) {
|
||||
addUserData(ProcessConfigurationVariable.SERVER_PORT, builder.getPort().toString());
|
||||
}
|
||||
@@ -166,8 +167,8 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, SailingAnalyticsMaste
|
||||
return port == null ? DEFAULT_PORT : port;
|
||||
}
|
||||
|
||||
protected String getServerDirectory() {
|
||||
return serverDirectory;
|
||||
protected String getDefaultServerDirectory() {
|
||||
return defaultServerDirectory;
|
||||
}
|
||||
|
||||
public abstract ProcessT getSailingAnalyticsProcess();
|
||||
|
||||
+1
-1
@@ -53,6 +53,6 @@ public class StartSailingAnalyticsMaster<ShardingKey>
|
||||
|
||||
@Override
|
||||
public SailingAnalyticsMaster<ShardingKey> getSailingAnalyticsProcess() {
|
||||
return new SailingAnalyticsMasterImpl<>(getPort(), getHost(), getServerDirectory());
|
||||
return new SailingAnalyticsMasterImpl<>(getPort(), getHost(), getDefaultServerDirectory());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -54,6 +54,6 @@ public class StartSailingAnalyticsReplica<ShardingKey>
|
||||
|
||||
@Override
|
||||
public SailingAnalyticsReplica<ShardingKey> getSailingAnalyticsProcess() {
|
||||
return new SailingAnalyticsReplicaImpl<>(getPort(), getHost(), getServerDirectory());
|
||||
return new SailingAnalyticsReplicaImpl<>(getPort(), getHost(), getDefaultServerDirectory());
|
||||
}
|
||||
}
|
||||
+89
-4
@@ -1,10 +1,14 @@
|
||||
package com.sap.sailing.landscape.procedures;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sap.sailing.landscape.SailingAnalyticsHost;
|
||||
import com.sap.sailing.landscape.SailingAnalyticsMetrics;
|
||||
import com.sap.sailing.landscape.impl.SailingAnalyticsHostImpl;
|
||||
import com.sap.sailing.landscape.procedures.UpgradeAmi.Builder;
|
||||
import com.sap.sailing.landscape.procedures.UpgradeAmi.Builder.VersionPart;
|
||||
import com.sap.sse.landscape.MachineImage;
|
||||
import com.sap.sse.landscape.application.ApplicationMasterProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
@@ -16,7 +20,18 @@ import com.sap.sse.landscape.orchestration.Procedure;
|
||||
/**
|
||||
* Upgrades an existing Amazon Machine Image that is expected to be prepared for such an upgrade, by
|
||||
* invoking it with very specific user data that trigger the automatic upgrade. The resulting AMI can
|
||||
* be obtained after this procedure has completed by calling {@link #getUpgradedAmi()}.
|
||||
* be obtained after this procedure has completed by calling {@link #getUpgradedAmi()}.<p>
|
||||
*
|
||||
* The procedure uses a new name for the image and its snapshots. This name can either be explicitly
|
||||
* configured using the {@link Builder}, or it is inferred from the name of the image to upgrade by looking
|
||||
* for a version number in the form {@code [0-9]+\.[0-9]+(\.[0-9]+)}, so that major.minor and major.minor.micro
|
||||
* will all be considered matches. The {@link Builder} can be provided only with a new version string. By default,
|
||||
* it will increment the last version part matched (minor in case of major.minor and micro in case of
|
||||
* major.minor.micro) by one.<p>
|
||||
*
|
||||
* TODO generalize such that kernel upgrades / security patches can be applied to any CentOS/Amazon Linux-based
|
||||
* image; then one level more specialized clean httpd logs for anything that has a reverse proxy on it;
|
||||
* then for those that have a default server process / git on it cleaning that up and refreshing...
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
@@ -30,7 +45,9 @@ extends StartEmptyServer<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, R
|
||||
implements Procedure<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT> {
|
||||
private static final String IMAGE_UPGRADE_USER_DATA = "image-upgrade";
|
||||
private static final String NO_SHUTDOWN_USER_DATA = "no-shutdown";
|
||||
private static final Pattern imageNamePattern = Pattern.compile("^(.*) ([0-9]+)\\.([0-9]+)(\\.([0-9]+))?$");
|
||||
|
||||
private final String upgradedImageName;
|
||||
private MachineImage upgradedAmi;
|
||||
|
||||
/**
|
||||
@@ -41,13 +58,28 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, Repli
|
||||
* {@code IMAGE_UPGRADE+" for "+machineImage.getId()}</li>
|
||||
* <li>The user data are set to the string defined by {@link UpgradeAmi#IMAGE_UPGRADE_USER_DATA}, forcing the image to
|
||||
* boot without trying to launch a process instance.</li>
|
||||
* <li>The {@link #isNoShutdown()} property default is changed to {@code false} because when upgrading an image the
|
||||
* default is that after the upgrading activity the instance is shut down for image creation.</li>
|
||||
* <li>By default the last part of the version number found will be incremented.</li>
|
||||
* <li>If the {@link #setVersionPartToIncrement(VersionPart)} method is used to explicitly specify a part to increment
|
||||
* then if its {@link VersionPart#MICRO} and the {@link VersionPart#MICRO} part doesn't exist yet, it is added and set to 0.
|
||||
* If the part exists it is incremented and in case it's not the last part, tailing parts are all set to 0. With this,
|
||||
* the new image name defaults to the old image's base name plus a space plus the new version number.</li>
|
||||
* </ul>
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public static interface Builder<ShardingKey,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT>>
|
||||
extends StartEmptyServer.Builder<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT, SailingAnalyticsHost<ShardingKey>> {
|
||||
extends
|
||||
StartEmptyServer.Builder<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT, SailingAnalyticsHost<ShardingKey>> {
|
||||
enum VersionPart {
|
||||
MAJOR, MINOR, MICRO
|
||||
}
|
||||
|
||||
Builder<ShardingKey, MasterProcessT, ReplicaProcessT> setUpgradedImageName(String upgradedImageName);
|
||||
|
||||
Builder<ShardingKey, MasterProcessT, ReplicaProcessT> setVersionPartToIncrement(VersionPart versionPartToIncrement);
|
||||
}
|
||||
|
||||
protected static class BuilderImpl<ShardingKey,
|
||||
@@ -55,13 +87,64 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, Repli
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT>>
|
||||
extends StartEmptyServer.BuilderImpl<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT, SailingAnalyticsHost<ShardingKey>>
|
||||
implements Builder<ShardingKey, MasterProcessT, ReplicaProcessT> {
|
||||
private String upgradedImageName;
|
||||
private VersionPart versionPartToIncrement;
|
||||
|
||||
private BuilderImpl() {
|
||||
super();
|
||||
setNoShutdown(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ShardingKey, MasterProcessT, ReplicaProcessT> setVersionPartToIncrement(VersionPart versionPartToIncrement) {
|
||||
this.versionPartToIncrement = versionPartToIncrement;
|
||||
return this;
|
||||
}
|
||||
|
||||
private String increaseVersionNumber(String imageName) {
|
||||
final String result;
|
||||
final Matcher versionNumberMatcher = imageNamePattern.matcher(imageName);
|
||||
if (versionNumberMatcher.matches()) {
|
||||
final String imageBaseName = versionNumberMatcher.group(1);
|
||||
final String majorVersion = versionNumberMatcher.group(2);
|
||||
final String minorVersion = versionNumberMatcher.group(3);
|
||||
final String microVersion = versionNumberMatcher.group(5);
|
||||
final StringBuilder sb = new StringBuilder(imageBaseName);
|
||||
sb.append(' ');
|
||||
sb.append(majorVersion);
|
||||
sb.append('.');
|
||||
sb.append(minorVersion);
|
||||
if (microVersion != null || versionPartToIncrement == VersionPart.MICRO) {
|
||||
sb.append('.');
|
||||
sb.append(microVersion);
|
||||
}
|
||||
result = sb.toString();
|
||||
} else {
|
||||
result = imageName+" (1)";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ShardingKey, MasterProcessT, ReplicaProcessT> setUpgradedImageName(String upgradedImageName) {
|
||||
this.upgradedImageName = upgradedImageName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostSupplier<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT, SailingAnalyticsHost<ShardingKey>> getHostSupplier() {
|
||||
return SailingAnalyticsHostImpl::new;
|
||||
}
|
||||
|
||||
protected String getUpgradedImageName() {
|
||||
return upgradedImageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartEmptyServer<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, ReplicaProcessT, SailingAnalyticsHost<ShardingKey>> build() {
|
||||
public UpgradeAmi<ShardingKey, MasterProcessT, ReplicaProcessT> build() {
|
||||
if (upgradedImageName == null) {
|
||||
upgradedImageName = increaseVersionNumber(getMachineImage().getName());
|
||||
}
|
||||
return new UpgradeAmi<>(this);
|
||||
}
|
||||
}
|
||||
@@ -73,8 +156,9 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, Repli
|
||||
return new BuilderImpl<>();
|
||||
}
|
||||
|
||||
public UpgradeAmi(Builder<ShardingKey, MasterProcessT, ReplicaProcessT> builder) {
|
||||
protected UpgradeAmi(BuilderImpl<ShardingKey, MasterProcessT, ReplicaProcessT> builder) {
|
||||
super(builder);
|
||||
upgradedImageName = builder.getUpgradedImageName();
|
||||
addUserData(Collections.singleton(IMAGE_UPGRADE_USER_DATA));
|
||||
if (builder.isNoShutdown()) {
|
||||
addUserData(Collections.singleton(NO_SHUTDOWN_USER_DATA));
|
||||
@@ -84,6 +168,7 @@ implements Procedure<ShardingKey, SailingAnalyticsMetrics, MasterProcessT, Repli
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
super.run(); // launches the machine in upgrade mode and shuts it down again, preparing for AMI creation
|
||||
upgradedAmi = getLandscape().createImage(getHost(), upgradedImageName);
|
||||
// TODO now comes the waiting for the shutdown and initiating the creation of an AMI for the instance
|
||||
// TODO then comes the tagging of the volume snapshots created
|
||||
// TODO then tag the resulting AMI according to the original image's tags, except for the name where automatic version number increment should be implemented
|
||||
|
||||
-1
@@ -37,7 +37,6 @@ import com.sap.sse.landscape.application.ApplicationProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.application.impl.ApplicationProcessImpl;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
import com.sap.sse.landscape.aws.orchestration.CreateDNSBasedLoadBalancerMapping;
|
||||
import com.sap.sse.landscape.impl.ReleaseRepositoryImpl;
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.sap.sse.landscape.aws;
|
||||
|
||||
import com.sap.sse.landscape.MachineImage;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.BlockDeviceMapping;
|
||||
|
||||
public interface AmazonMachineImage<ShardingKey, MetricsT extends ApplicationProcessMetrics> extends MachineImage {
|
||||
Iterable<BlockDeviceMapping> getBlockDeviceMappings();
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import com.sap.sse.landscape.SecurityGroup;
|
||||
import com.sap.sse.landscape.application.ApplicationMasterProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.impl.AwsInstanceImpl;
|
||||
import com.sap.sse.landscape.aws.impl.AwsLandscapeImpl;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
@@ -119,6 +118,8 @@ extends Landscape<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
|
||||
AmazonMachineImage<ShardingKey, MetricsT> getImage(Region region, String imageId);
|
||||
|
||||
AmazonMachineImage<ShardingKey, MetricsT> createImage(AwsInstance<ShardingKey, MetricsT> instance, String imageName);
|
||||
|
||||
AmazonMachineImage<ShardingKey, MetricsT> getLatestImageWithTag(Region region, String tagName, String tagValue);
|
||||
|
||||
/**
|
||||
|
||||
+16
-5
@@ -7,17 +7,19 @@ import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.landscape.MachineImage;
|
||||
import com.sap.sse.landscape.Region;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.aws.AmazonMachineImage;
|
||||
|
||||
import software.amazon.awssdk.services.ec2.model.BlockDeviceMapping;
|
||||
import software.amazon.awssdk.services.ec2.model.Image;
|
||||
|
||||
public class AmazonMachineImage<ShardingKey, MetricsT extends ApplicationProcessMetrics> implements MachineImage {
|
||||
public class AmazonMachineImageImpl<ShardingKey, MetricsT extends ApplicationProcessMetrics> implements AmazonMachineImage<ShardingKey, MetricsT> {
|
||||
private static final long serialVersionUID = 1615200981492476022L;
|
||||
private final Image image;
|
||||
private final Region region;
|
||||
|
||||
public AmazonMachineImage(Image image, Region region) {
|
||||
public AmazonMachineImageImpl(Image image, Region region) {
|
||||
this.image = image;
|
||||
this.region = region;
|
||||
}
|
||||
@@ -27,6 +29,11 @@ public class AmazonMachineImage<ShardingKey, MetricsT extends ApplicationProcess
|
||||
return image.imageId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return image.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getRegion() {
|
||||
return region;
|
||||
@@ -54,7 +61,11 @@ public class AmazonMachineImage<ShardingKey, MetricsT extends ApplicationProcess
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
// TODO Implement MachineImage<AwsInstance>.delete(...)
|
||||
|
||||
// TODO implement AmazonMachineImageImpl.delete(); we probably want landscape here...
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<BlockDeviceMapping> getBlockDeviceMappings() {
|
||||
return image.blockDeviceMappings();
|
||||
}
|
||||
}
|
||||
+1
@@ -11,6 +11,7 @@ import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaSet;
|
||||
import com.sap.sse.landscape.application.Scope;
|
||||
import com.sap.sse.landscape.aws.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
|
||||
+13
-3
@@ -31,6 +31,7 @@ import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaSet;
|
||||
import com.sap.sse.landscape.application.Scope;
|
||||
import com.sap.sse.landscape.aws.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.ApplicationLoadBalancer;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
@@ -449,14 +450,23 @@ ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterP
|
||||
public AmazonMachineImage<ShardingKey, MetricsT> getImage(com.sap.sse.landscape.Region region, String imageId) {
|
||||
final DescribeImagesResponse response = getEc2Client(getRegion(region))
|
||||
.describeImages(DescribeImagesRequest.builder().imageIds(imageId).build());
|
||||
return new AmazonMachineImage<>(response.images().iterator().next(), region);
|
||||
return new AmazonMachineImageImpl<>(response.images().iterator().next(), region);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AmazonMachineImage<ShardingKey, MetricsT> createImage(AwsInstance<ShardingKey, MetricsT> instance, String imageName) {
|
||||
final Ec2Client client = getEc2Client(getRegion(instance.getRegion()));
|
||||
final String imageId = client.createImage(b->b
|
||||
.instanceId(instance.getInstanceId())
|
||||
.name(imageName)).imageId();
|
||||
return getImage(instance.getRegion(), imageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AmazonMachineImage<ShardingKey, MetricsT> getLatestImageWithTag(com.sap.sse.landscape.Region region, String tagName, String tagValue) {
|
||||
final DescribeImagesResponse response = getEc2Client(getRegion(region))
|
||||
.describeImages(DescribeImagesRequest.builder().filters(Filter.builder().name("tag:"+tagName).values(tagValue).build()).build());
|
||||
return new AmazonMachineImage<>(response.images().stream().max(getMachineImageCreationDateComparator()).get(), region);
|
||||
return new AmazonMachineImageImpl<>(response.images().stream().max(getMachineImageCreationDateComparator()).get(), region);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -781,7 +791,7 @@ ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterP
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MongoEndpoint getDatabaseConfigurationForDefaultReplicaSet(com.sap.sse.landscape.Region region) {
|
||||
return getDatabaseConfigurationForReplicaSet(region, MONGO_DEFAULT_REPLICA_SET_NAME);
|
||||
|
||||
+6
-2
@@ -23,12 +23,12 @@ import com.sap.sse.landscape.UserDataProvider;
|
||||
import com.sap.sse.landscape.application.ApplicationMasterProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.aws.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.AwsAvailabilityZone;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
import com.sap.sse.landscape.aws.AwsLandscape;
|
||||
import com.sap.sse.landscape.aws.HostSupplier;
|
||||
import com.sap.sse.landscape.aws.Tags;
|
||||
import com.sap.sse.landscape.aws.impl.AmazonMachineImage;
|
||||
import com.sap.sse.landscape.aws.impl.AwsRegion;
|
||||
import com.sap.sse.landscape.mongodb.Database;
|
||||
import com.sap.sse.landscape.orchestration.StartHost;
|
||||
@@ -613,7 +613,11 @@ extends StartHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, HostT>
|
||||
* will be escaped by preceding them with a {@code \} (backslash) character.
|
||||
*/
|
||||
protected void addUserData(ProcessConfigurationVariable userDataVariable, String value) {
|
||||
userData.add(userDataVariable.name()+"=\""+value.replaceAll("\"", "\\\"")+"\"");
|
||||
addUserData(userDataVariable.name(), value);
|
||||
}
|
||||
|
||||
protected void addUserData(String name, String value) {
|
||||
userData.add(name+"=\""+value.replaceAll("\"", "\\\"")+"\"");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
package com.sap.sse.landscape.aws.orchestration;
|
||||
|
||||
import com.sap.sse.landscape.application.ApplicationMasterProcess;
|
||||
import com.sap.sse.landscape.application.ApplicationProcessMetrics;
|
||||
import com.sap.sse.landscape.application.ApplicationReplicaProcess;
|
||||
import com.sap.sse.landscape.aws.AwsInstance;
|
||||
import com.sap.sse.landscape.aws.HostSupplier;
|
||||
import com.sap.sse.landscape.aws.impl.AwsInstanceImpl;
|
||||
|
||||
/**
|
||||
* Launches a MongoDB host with user data as follows:<pre>
|
||||
* REPLICA_SET_NAME={@link Builder#setReplicaSetName(String) replicaSetName}
|
||||
* REPLICA_SET_PRIMARY={@link Builder#setReplicaSetName(String) replicaSetPrimary}
|
||||
* REPLICA_SET_PRIORITY={@link Builder#setReplicaSetName(String) replicaSetVotes}
|
||||
* REPLICA_SET_VOTES={@link Builder#setReplicaSetName(String) replicaSetVotes}</pre>
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public class StartMongoDBServer<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>>
|
||||
extends StartAwsHost<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, AwsInstance<ShardingKey, MetricsT>> {
|
||||
private static enum MongoDBReplicaSetUserData {
|
||||
REPLICA_SET_NAME, REPLICA_SET_PRIMARY, REPLICA_SET_PRIORITY, REPLICA_SET_VOTES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defaults:
|
||||
* <ul>
|
||||
* <li>The image type defaults to the value of the constant {@link #MONGODB_SERVER_IMAGE_TYPE} ("mongodb-server").</li>
|
||||
* <li>The replica set name defaults to "live"</li>
|
||||
* <li>The replica set priority defaults to 1</li>
|
||||
* <li>The replica set votes defaults to 1</li>
|
||||
* </ul>
|
||||
* @author Axel Uhl (D043530)
|
||||
*/
|
||||
public static interface Builder<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>>
|
||||
extends StartAwsHost.Builder<StartMongoDBServer<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, AwsInstance<ShardingKey, MetricsT>> {
|
||||
/**
|
||||
* The default {@link #setImageType(String) image type} used for launching a MongoDB server.
|
||||
*/
|
||||
String MONGODB_SERVER_IMAGE_TYPE = "mongodb-server";
|
||||
|
||||
Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetName(String replicaSetName);
|
||||
|
||||
Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetPrimary(String replicaSetPrimary);
|
||||
|
||||
Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetPriority(int replicaSetPriority);
|
||||
|
||||
Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetVotes(int replicaSetVotes);
|
||||
|
||||
StartMongoDBServer<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> build();
|
||||
}
|
||||
|
||||
protected static class BuilderImpl<ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>>
|
||||
extends StartAwsHost.BuilderImpl<StartMongoDBServer<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>, ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, AwsInstance<ShardingKey, MetricsT>>
|
||||
implements Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> {
|
||||
private String replicaSetName = "live";
|
||||
private String replicaSetPrimary;
|
||||
private int replicaSetPriority = 1;
|
||||
private int replicaSetVotes = 1;
|
||||
|
||||
private BuilderImpl() {
|
||||
setImageType(MONGODB_SERVER_IMAGE_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HostSupplier<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT, AwsInstance<ShardingKey, MetricsT>> getHostSupplier() {
|
||||
return AwsInstanceImpl::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetName(String replicaSetName) {
|
||||
this.replicaSetName = replicaSetName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetPrimary(String replicaSetPrimary) {
|
||||
this.replicaSetPrimary = replicaSetPrimary;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetPriority(int replicaSetPriority) {
|
||||
this.replicaSetPriority = replicaSetPriority;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> setReplicaSetVotes(int replicaSetVotes) {
|
||||
this.replicaSetVotes = replicaSetVotes;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected String getReplicaSetName() {
|
||||
return replicaSetName;
|
||||
}
|
||||
|
||||
protected String getReplicaSetPrimary() {
|
||||
return replicaSetPrimary;
|
||||
}
|
||||
|
||||
protected int getReplicaSetPriority() {
|
||||
return replicaSetPriority;
|
||||
}
|
||||
|
||||
protected int getReplicaSetVotes() {
|
||||
return replicaSetVotes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartMongoDBServer<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> build() {
|
||||
return new StartMongoDBServer<>(this);
|
||||
}
|
||||
}
|
||||
|
||||
public static <ShardingKey, MetricsT extends ApplicationProcessMetrics,
|
||||
MasterProcessT extends ApplicationMasterProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>,
|
||||
ReplicaProcessT extends ApplicationReplicaProcess<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT>>
|
||||
Builder<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> builder() {
|
||||
return new BuilderImpl<>();
|
||||
}
|
||||
|
||||
protected StartMongoDBServer(BuilderImpl<ShardingKey, MetricsT, MasterProcessT, ReplicaProcessT> builder) {
|
||||
super(builder);
|
||||
addUserData(MongoDBReplicaSetUserData.REPLICA_SET_NAME.name(), builder.getReplicaSetName());
|
||||
addUserData(MongoDBReplicaSetUserData.REPLICA_SET_PRIMARY.name(), builder.getReplicaSetPrimary());
|
||||
addUserData(MongoDBReplicaSetUserData.REPLICA_SET_PRIORITY.name(), Integer.toString(builder.getReplicaSetPriority()));
|
||||
addUserData(MongoDBReplicaSetUserData.REPLICA_SET_VOTES.name(), Integer.toString(builder.getReplicaSetVotes()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.sap.sse.landscape;
|
||||
|
||||
import com.sap.sse.common.NamedWithID;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.WithID;
|
||||
|
||||
/**
|
||||
* An image (e.g., an AMI for AWS) that can be used to
|
||||
@@ -13,7 +13,7 @@ import com.sap.sse.common.WithID;
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
*/
|
||||
public interface MachineImage extends WithID {
|
||||
public interface MachineImage extends NamedWithID {
|
||||
/**
|
||||
* The image lives in a region; it can only be used for {@link Host} creation in that region.
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user