|
|
|
@@ -62,6 +62,8 @@ import com.sap.sse.common.Duration;
|
|
|
|
|
import com.sap.sse.common.TimePoint;
|
|
|
|
|
import com.sap.sse.common.Util;
|
|
|
|
|
import com.sap.sse.common.Util.Pair;
|
|
|
|
|
import com.sap.sse.common.mail.MailException;
|
|
|
|
|
import com.sap.sse.i18n.impl.ResourceBundleStringMessagesImpl;
|
|
|
|
|
import com.sap.sse.landscape.DefaultProcessConfigurationVariables;
|
|
|
|
|
import com.sap.sse.landscape.InboundReplicationConfiguration;
|
|
|
|
|
import com.sap.sse.landscape.Landscape;
|
|
|
|
@@ -101,9 +103,12 @@ import com.sap.sse.replication.FullyInitializedReplicableTracker;
|
|
|
|
|
import com.sap.sse.security.SecurityService;
|
|
|
|
|
import com.sap.sse.security.SessionUtils;
|
|
|
|
|
import com.sap.sse.security.shared.HasPermissions.DefaultActions;
|
|
|
|
|
import com.sap.sse.security.shared.OwnershipAnnotation;
|
|
|
|
|
import com.sap.sse.security.shared.QualifiedObjectIdentifier;
|
|
|
|
|
import com.sap.sse.security.shared.TypeRelativeObjectIdentifier;
|
|
|
|
|
import com.sap.sse.security.shared.WildcardPermission;
|
|
|
|
|
import com.sap.sse.security.shared.impl.SecuredSecurityTypes;
|
|
|
|
|
import com.sap.sse.security.shared.impl.User;
|
|
|
|
|
import com.sap.sse.security.util.RemoteServerUtil;
|
|
|
|
|
import com.sap.sse.shared.util.Wait;
|
|
|
|
|
import com.sap.sse.util.JvmUtils;
|
|
|
|
@@ -121,6 +126,8 @@ import software.amazon.awssdk.services.sts.model.Credentials;
|
|
|
|
|
|
|
|
|
|
public class LandscapeServiceImpl implements LandscapeService {
|
|
|
|
|
private static final Logger logger = Logger.getLogger(LandscapeServiceImpl.class.getName());
|
|
|
|
|
|
|
|
|
|
private static final String STRING_MESSAGES_BASE_NAME = "stringmessages/SailingLandscape_StringMessages";
|
|
|
|
|
|
|
|
|
|
private static final String TEMPORARY_UPGRADE_REPLICA_NAME_SUFFIX = " (Upgrade Replica)";
|
|
|
|
|
|
|
|
|
@@ -746,6 +753,10 @@ public class LandscapeServiceImpl implements LandscapeService {
|
|
|
|
|
Integer optionalMemoryTotalSizeFactorOrNull, final AwsRegion region, final Release release) {
|
|
|
|
|
final AppConfigBuilderT masterConfigurationBuilder = SailingAnalyticsMasterConfiguration.masterBuilder();
|
|
|
|
|
final String bearerTokenUsedByMaster = getEffectiveBearerToken(optionalMasterReplicationBearerTokenOrNull);
|
|
|
|
|
final User currentUser = getSecurityService().getCurrentUser();
|
|
|
|
|
if (currentUser != null && currentUser.isEmailValidated() && currentUser.getEmail() != null) {
|
|
|
|
|
masterConfigurationBuilder.setCommaSeparatedEmailAddressesToNotifyOfStartup(currentUser.getEmail());
|
|
|
|
|
}
|
|
|
|
|
masterConfigurationBuilder
|
|
|
|
|
.setLandscape(getLandscape())
|
|
|
|
|
.setServerName(replicaSetName)
|
|
|
|
@@ -768,6 +779,10 @@ public class LandscapeServiceImpl implements LandscapeService {
|
|
|
|
|
String replicaSetName, final int masterPort, final Release release,
|
|
|
|
|
final String bearerTokenUsedByReplicas, final String masterHostname) {
|
|
|
|
|
final AppConfigBuilderT replicaConfigurationBuilder = SailingAnalyticsReplicaConfiguration.replicaBuilder();
|
|
|
|
|
final User currentUser = getSecurityService().getCurrentUser();
|
|
|
|
|
if (currentUser != null && currentUser.isEmailValidated() && currentUser.getEmail() != null) {
|
|
|
|
|
replicaConfigurationBuilder.setCommaSeparatedEmailAddressesToNotifyOfStartup(currentUser.getEmail());
|
|
|
|
|
}
|
|
|
|
|
// no specific memory configuration is made here; replicas are mostly launched on a dedicated host and hence can
|
|
|
|
|
// grab as much memory as they can get on that host
|
|
|
|
|
replicaConfigurationBuilder
|
|
|
|
@@ -1412,6 +1427,7 @@ public class LandscapeServiceImpl implements LandscapeService {
|
|
|
|
|
optionalPreferredInstanceToDeployTo).getInstanceToDeployTo(replicaSet);
|
|
|
|
|
}
|
|
|
|
|
logger.info("Stopping master "+replicaSet.getMaster());
|
|
|
|
|
sendMailAboutMasterUnavailable(replicaSet);
|
|
|
|
|
replicaSet.getMaster().stopAndTerminateIfLast(Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase);
|
|
|
|
|
final AppConfigBuilderT masterConfigurationBuilder = createMasterConfigurationBuilder(replicaSet.getName(),
|
|
|
|
|
optionalMasterReplicationBearerTokenOrNull, optionalMemoryInMegabytesOrNull, optionalMemoryTotalSizeFactorOrNull,
|
|
|
|
@@ -1444,6 +1460,7 @@ public class LandscapeServiceImpl implements LandscapeService {
|
|
|
|
|
logger.info("Adding new master "+newMaster+" to target groups");
|
|
|
|
|
replicaSet.getPublicTargetGroup().addTarget(hostToDeployTo);
|
|
|
|
|
replicaSet.getMasterTargetGroup().addTarget(hostToDeployTo);
|
|
|
|
|
sendMailAboutMasterAvailable(replicaSet);
|
|
|
|
|
if (newTemporaryReplica != null) {
|
|
|
|
|
newTemporaryReplica.stopAndTerminateIfLast(Landscape.WAIT_FOR_HOST_TIMEOUT, Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase);
|
|
|
|
|
}
|
|
|
|
@@ -1451,6 +1468,38 @@ public class LandscapeServiceImpl implements LandscapeService {
|
|
|
|
|
return getLandscape().getApplicationReplicaSet(region, replicaSet.getServerName(), newMaster, replicaSet.getReplicas());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void sendMailAboutMasterAvailable(
|
|
|
|
|
AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet) throws MailException {
|
|
|
|
|
sendMailToReplicaSetOwner(replicaSet, "MasterUnavailableMailSubject", "MasterUnavailableMailBody");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void sendMailAboutMasterUnavailable(
|
|
|
|
|
AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet) throws MailException {
|
|
|
|
|
sendMailToReplicaSetOwner(replicaSet, "MasterAvailableMailSubject", "MasterAvailableMailBody");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param subjectMessageKey must have a single placeholder argument representing the name of the replica set
|
|
|
|
|
* @param bodyMessageKey must have a single placeholder argument representing the name of the replica set
|
|
|
|
|
*/
|
|
|
|
|
private void sendMailToReplicaSetOwner(
|
|
|
|
|
AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet,
|
|
|
|
|
final String subjectMessageKey, final String bodyMessageKey) throws MailException {
|
|
|
|
|
final OwnershipAnnotation serverOwnership = getSecurityService().getOwnership(getReplicaSetQualifiedObjectIdentifier(replicaSet));
|
|
|
|
|
final User serverOwner;
|
|
|
|
|
final ResourceBundleStringMessagesImpl stringMessages = new ResourceBundleStringMessagesImpl(STRING_MESSAGES_BASE_NAME, getClass().getClassLoader());
|
|
|
|
|
if (serverOwnership != null && serverOwnership.getAnnotation() != null && (serverOwner = serverOwnership.getAnnotation().getUserOwner()) != null) {
|
|
|
|
|
getSecurityService().sendMail(serverOwner.getName(),
|
|
|
|
|
stringMessages.get(serverOwner.getLocaleOrDefault(), subjectMessageKey, replicaSet.getServerName()),
|
|
|
|
|
stringMessages.get(serverOwner.getLocaleOrDefault(), bodyMessageKey, replicaSet.getServerName()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private QualifiedObjectIdentifier getReplicaSetQualifiedObjectIdentifier(
|
|
|
|
|
AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet) {
|
|
|
|
|
return SecuredSecurityTypes.SERVER.getQualifiedObjectIdentifier(new TypeRelativeObjectIdentifier(replicaSet.getServerName()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If a non-{@code null}, non-{@link String#isEmpty() empty} bearer token is provided by the
|
|
|
|
|
* {@code optionalBearerTokenOnNull} parameter, it is returned unchanged; otherwise, the bearer token as obtained
|
|
|
|
|