java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/server/StatusServlet.java
... ...
@@ -2,6 +2,8 @@ package com.sap.sailing.gwt.ui.server;
2 2
3 3
import java.io.IOException;
4 4
import java.io.OutputStreamWriter;
5
+import java.util.concurrent.ScheduledExecutorService;
6
+import java.util.concurrent.ThreadPoolExecutor;
5 7
6 8
import javax.servlet.ServletContext;
7 9
import javax.servlet.ServletException;
... ...
@@ -23,6 +25,7 @@ import com.sap.sse.ServerInfo;
23 25
import com.sap.sse.mongodb.MongoDBService;
24 26
import com.sap.sse.replication.ReplicationService;
25 27
import com.sap.sse.replication.ReplicationStatus;
28
+import com.sap.sse.util.ThreadPoolUtil;
26 29
27 30
public class StatusServlet extends HttpServlet {
28 31
private static final String WAIT_UNTIL_RACES_LOADED = "waitUntilRacesLoaded";
... ...
@@ -58,6 +61,16 @@ public class StatusServlet extends HttpServlet {
58 61
try {
59 62
final JSONObject versionAsJson = ServerInfo.getBuildVersionJson();
60 63
result.putAll(versionAsJson);
64
+ final ScheduledExecutorService defaultBackgroundTaskThreadPoolExecutor = ThreadPoolUtil.INSTANCE.getDefaultBackgroundTaskThreadPoolExecutor();
65
+ if (defaultBackgroundTaskThreadPoolExecutor instanceof ThreadPoolExecutor) {
66
+ final long queueLengthDefaultBackgroundThreadPoolExecutor = ((ThreadPoolExecutor) defaultBackgroundTaskThreadPoolExecutor).getQueue().size();
67
+ result.put("defaultbackgroundthreadpoolexecutorqueuelength", queueLengthDefaultBackgroundThreadPoolExecutor);
68
+ }
69
+ final ScheduledExecutorService defaultForegroundTaskThreadPoolExecutor = ThreadPoolUtil.INSTANCE.getDefaultForegroundTaskThreadPoolExecutor();
70
+ if (defaultForegroundTaskThreadPoolExecutor instanceof ThreadPoolExecutor) {
71
+ final long queueLengthDefaultForegroundThreadPoolExecutor = ((ThreadPoolExecutor) defaultForegroundTaskThreadPoolExecutor).getQueue().size();
72
+ result.put("defaultforegroundthreadpoolexecutorqueuelength", queueLengthDefaultForegroundThreadPoolExecutor);
73
+ }
61 74
final long numberOfTrackedRacesToRestore = service.getNumberOfTrackedRacesToRestore();
62 75
result.put("numberofracestorestore", numberOfTrackedRacesToRestore);
63 76
final int numberOfTrackedRacesRestored = service.getNumberOfTrackedRacesRestored();
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/server/LandscapeManagementWriteServiceImpl.java
... ...
@@ -692,7 +692,9 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
692 692
if(Util.hasLength(securityReplicationBearerToken)) {
693 693
userSetOrArchiveServerSecurityReplicationBearerToken = securityReplicationBearerToken;
694 694
} else {
695
- userSetOrArchiveServerSecurityReplicationBearerToken = master.getEnvShValueFor(DefaultProcessConfigurationVariables.REPLICATE_MASTER_BEARER_TOKEN, Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.of(optionalKeyName), privateKeyEncryptionPassphrase);
695
+ userSetOrArchiveServerSecurityReplicationBearerToken = master.getEnvShValueFor(
696
+ DefaultProcessConfigurationVariables.REPLICATE_MASTER_BEARER_TOKEN,
697
+ Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.of(optionalKeyName), privateKeyEncryptionPassphrase);
696 698
}
697 699
final String replicaSetName = SharedLandscapeConstants.ARCHIVE_SERVER_APPLICATION_REPLICA_SET_NAME;
698 700
final String archiveCandidateSubDomain = SharedLandscapeConstants.ARCHIVE_CANDIDATE_SUBDOMAIN;
... ...
@@ -701,10 +703,14 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
701 703
final Database databaseConfiguration = master.getDatabaseConfiguration(region,
702 704
Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.ofNullable(optionalKeyName),
703 705
privateKeyEncryptionPassphrase);
704
- final AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> result = getLandscapeService().createArchiveReplicaSet(regionId, replicaSetName,
705
- instanceType, releaseNameOrNullForLatestMaster, databaseConfiguration, optionalKeyName, privateKeyEncryptionPassphrase, userSetOrArchiveServerSecurityReplicationBearerToken, replicaReplicationBearerToken, domainName,
706
- /* optionalMemoryInMegabytesOrNull */ null, /* optionalMemoryTotalSizeFactorOrNull */ null, /* optionalIgtimiRiotPort */ null);
707
- return new SailingApplicationReplicaSetDTO<String>(result.getName(), convertToSailingAnalyticsProcessDTO(result
706
+ final AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> result = getLandscapeService()
707
+ .createArchiveReplicaSet(regionId, replicaSetName, instanceType, releaseNameOrNullForLatestMaster,
708
+ databaseConfiguration, optionalKeyName, privateKeyEncryptionPassphrase,
709
+ userSetOrArchiveServerSecurityReplicationBearerToken, replicaReplicationBearerToken, domainName,
710
+ /* optionalMemoryInMegabytesOrNull */ null, /* optionalMemoryTotalSizeFactorOrNull */ null,
711
+ /* optionalIgtimiRiotPort */ null);
712
+ return new SailingApplicationReplicaSetDTO<String>(result.getName(),
713
+ convertToSailingAnalyticsProcessDTO(result
708 714
.getMaster(), Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase), /* replicas */ Collections.emptySet(),
709 715
release.getName(), release.getReleaseNotesURL().toString(),
710 716
getLandscapeService().getFullyQualifiedHostname(archiveCandidateSubDomain, Optional.ofNullable(domainName)),
java/com.sap.sailing.landscape/resources/stringmessages/SailingLandscape_StringMessages.properties
... ...
@@ -2,8 +2,10 @@ MasterUnavailableMailSubject=Primary server of replica set {0} temporarily unava
2 2
MasterUnavailableMailBody=The primary server of replica set {0} is temporarily unavailable.\nModifying access will be suspended.\nModifications incurred by a replica will be queued and will be applied when the primary is available again.\n\nYou are receiving this mail because you have administrative permissions for {0}.\nRemove those permissions at https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace: if you do not like to receive these messages anymore.
3 3
MasterAvailableMailSubject=Primary server of replica set {0} available again
4 4
MasterAvailableMailBody=The primary server of replica set {0} is available again.\nModifying access is possible again.\nQueued modifications will now process.\n\nYou are receiving this mail because you have administrative permissions for {0}.\nRemove those permissions at https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace: if you do not like to receive these messages anymore.
5
-StartingNewArchiveCandidateSubject=Starting new archive candidate
6
-StartingNewArchiveCandidateBody=Starting new archive candidate.\nFirst archived content is loaded from the MongoDB and afterwards wind estimations are calculated.\nThe whole process can take up to two days.\nCheck the status of the candidate at https://archive-canidate.sapsailing.com/gwt/status
5
+StartingNewArchiveCandidateSubject=Starting new {0} candidate
6
+StartingNewArchiveCandidateBody=Starting new {0} candidate.\nFirst, archived content is loaded from the MongoDB; afterwards wind estimations and mark passings are calculated.\nThe whole process can take up to two days.\nYou will receive another e-mail when this phase has finished.\nAlso check the status of the candidate at https://archive-canidate.sapsailing.com/gwt/status
7
+NewArchiveServerLiveSubject=New {0} server is live
8
+NewArchiveServerLiveBody=New {0} server is live.\nYou can now archive content to {0}.\n\nYou are receiving this mail because you have administrative permissions for {0}.\nRemove those permissions at https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace: if you do not like to receive these messages anymore.
7 9
StartingToArchiveReplicaSetIntoSubject=Starting to archive a replica set to {0}
8 10
StartingToArchiveReplicaSetIntoBody=Starting to archive a replica set to {0}.\nWhile this is going on, refrain from archiving another replica set into the same archive {0}.\nAfter the content has been imported it will be compared to the original.\nYou should receive another e-mail when this has completed.\n\nYou are receiving this mail because you have administrative permissions for {0}.\nRemove those permissions at https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace: if you do not like to receive these messages anymore.
9 11
StartingToArchiveReplicaSetSubject=Starting to archive replica set {0}
java/com.sap.sailing.landscape/resources/stringmessages/SailingLandscape_StringMessages_de.properties
... ...
@@ -2,8 +2,10 @@ MasterUnavailableMailSubject=Primär-Server des Anwendungs-Clusters {0} vorüber
2 2
MasterUnavailableMailBody=Der Primär-Server des Anwendungs-Clusters {0} ist vorübergehend nicht verfügbar.\nVerändernde Zugriffe sind derzeit nicht möglich.\nModifikationen, die durch eine Replika ausgeüfhrt werden, werden gepuffert und werden angewandt, wenn der primäre Server wieder verfügbar ist.\n\nDiese Nachricht wurde versandt, weil Du über administrative Rechte für {0} verfügst.\nUm das zu ändern, besuche https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace:, um diese Rechte für Dein Benutzerkonto zu entfernen.
3 3
MasterAvailableMailSubject=Primär-Server des Anwendungs-Clusters {0} wieder verfügbar
4 4
MasterAvailableMailBody=Der Primär-Server des Anwendungs-Clusters {0} ist wieder verfügbar.\nVerändernde Zugriffe sind jetzt wieder möglich.\nGepufferte Modifikationen werden jetzt abgearbeitet.\n\nDiese Nachricht wurde versandt, weil Du über administrative Rechte für {0} verfügst.\nUm das zu ändern, besuche https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace:, um diese Rechte für Dein Benutzerkonto zu entfernen.
5
-StartingNewArchiveCandidateSubject=Neuer Archivserver-Kandidat wird gestartet
6
-StartingNewArchiveCandidateBody=Neuer Archivserver-Kandidat wird gestartet.\nZuerst werden dabei die archivierten Veranstaltungen von der Datenbank geladen. Danach werden Manöver, Windschätzungen und Zwischenzeiten berechnet.\nDieser Prozess kann bis zu zwei vollen Tagen dauern.\nUnter https://archive-canidate.sapsailing.com/gwt/status kann der Status des Kandidaten verfolgt werden.
5
+StartingNewArchiveCandidateSubject=Neuer {0}-Kandidat wird gestartet
6
+StartingNewArchiveCandidateBody=Neuer {0}-Kandidat wird gestartet.\nZuerst werden dabei die archivierten Veranstaltungen von der Datenbank geladen. Danach werden Manöver, Windschätzungen und Zwischenzeiten berechnet.\nDieser Prozess kann bis zu zwei vollen Tagen dauern.\nEine weitere e-Mail benachrichtigt über den Abschluss dieser Phase.\nUnter https://archive-canidate.sapsailing.com/gwt/status kann der Status des Kandidaten verfolgt werden.
7
+NewArchiveServerLiveSubject=Neuer {0}-Server ist live
8
+NewArchiveServerLiveBody=Neuer {0}-Server ist live.\nAb jetzt dürfen wieder Anwendungs-Cluster nach {0} archiviert werden.\n\nDiese Nachricht wurde versandt, weil Du über administrative Rechte für {0} verfügst.\nUm das zu ändern, besuche https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace:, um diese Rechte für Dein Benutzerkonto zu entfernen.
7 9
StartingToArchiveReplicaSetIntoSubject=Anwendungs-Cluster wird nach {0} archiviert
8 10
StartingToArchiveReplicaSetIntoBody=Ein Anwendungs-Cluster wird nach {0} archiviert.\nWährend dieser Vorgang läuft, dürfen keine weitere Anwendungs-Cluster nach {0} archiviert werden.\nNach der Archivierung werden die Inhalte verglichen.\nEine e-Mail folgt, wenn der Vorgang abgeschlossen ist.\n\nDiese Nachricht wurde versandt, weil Du über administrative Rechte für {0} verfügst.\nUm das zu ändern, besuche https://sapsailing.com/gwt/AdminConsole.html#UserManagementPlace:, um diese Rechte für Dein Benutzerkonto zu entfernen.
9 11
StartingToArchiveReplicaSetSubject=Anwendungs-Cluster {0} wird archiviert
java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/LandscapeServiceImpl.java
... ...
@@ -252,13 +252,13 @@ public class LandscapeServiceImpl implements LandscapeService {
252 252
final Release release = getRelease(releaseNameOrNullForLatestMaster);
253 253
final com.sap.sailing.landscape.procedures.SailingAnalyticsMasterConfiguration.Builder<?, String> masterConfigurationBuilder =
254 254
createArchiveConfigurationBuilder(replicaSetName, databaseConfiguration, securityServiceReplicationBearerToken, optionalMemoryInMegabytesOrNull,
255
- null, optionalIgtimiRiotPort, region, release);
255
+ optionalMemoryTotalSizeFactorOrNull, optionalIgtimiRiotPort, region, release);
256 256
final String bearerTokenUsedByReplicas = getEffectiveBearerToken(replicaReplicationBearerToken);
257 257
final InboundReplicationConfiguration inboundMasterReplicationConfiguration = masterConfigurationBuilder.getInboundReplicationConfiguration().get();
258 258
establishServerAndServerGroupAndTryToMakeCurrentUserItsOwnerAndMember(replicaSetName, bearerTokenUsedByReplicas,
259 259
inboundMasterReplicationConfiguration.getMasterHostname(), inboundMasterReplicationConfiguration.getMasterHttpPort());
260 260
final com.sap.sailing.landscape.procedures.StartSailingAnalyticsMasterHost.Builder<?, String> masterHostBuilder = StartSailingAnalyticsMasterHost.masterHostBuilder(masterConfigurationBuilder);
261
- masterHostBuilder
261
+ masterHostBuilder // TODO bug6203: choose AZ such that ideally we have a reverse proxy in that AZ and the AZ differs from the current production ARCHIVE's AZ (which will become the failover later)
262 262
.setInstanceName(SharedLandscapeConstants.ARCHIVE_SERVER_NEW_CANDIDATE_INSTANCE_NAME)
263 263
.setInstanceType(InstanceType.valueOf(instanceType))
264 264
.setOptionalTimeout(Landscape.WAIT_FOR_HOST_TIMEOUT)
... ...
@@ -278,11 +278,9 @@ public class LandscapeServiceImpl implements LandscapeService {
278 278
Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase);
279 279
final ReverseProxy<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>, RotatingFileBasedLog> reverseProxyCluster =
280 280
getLandscape().getCentralReverseProxy(region);
281
- // TODO bug5311: when refactoring this for general scope migration, moving to a dedicated replica set will not require this
282
- // TODO bug5311: when refactoring this for general scope migration, moving into a cold storage server other than ARCHIVE will require ALBToReverseProxyRedirectMapper instead
283 281
final String privateIpAdress = master.getHost().getPrivateAddress().getHostAddress();
284 282
logger.info("Adding reverse proxy rule for archive candidate with hostname "+ hostname + " and private ip address " + privateIpAdress);
285
- reverseProxyCluster.setPlainRedirect(hostname, master, Optional.of(optionalKeyName), privateKeyEncryptionPassphrase);
283
+ reverseProxyCluster.setPlainRedirect(hostname, master, Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase);
286 284
sendMailAboutNewArchiveCandidate(replicaSet);
287 285
return replicaSet;
288 286
}
... ...
@@ -972,7 +970,6 @@ public class LandscapeServiceImpl implements LandscapeService {
972 970
.setServerName(replicaSetName)
973 971
.setRelease(release)
974 972
.setRegion(region)
975
- // TODO bug5684: probably this is the place to add the REPLICATE_MASTER_SERVLET_HOST/REPLICATE_MASTER_EXCHANGE_NAME variables to point to a default security service?
976 973
.setInboundReplicationConfiguration(InboundReplicationConfiguration.builder().setCredentials(new BearerTokenReplicationCredentials(bearerTokenUsedByMaster)).build());
977 974
if (optionalIgtimiRiotPort != null) {
978 975
masterConfigurationBuilder.setIgtimiRiotPort(optionalIgtimiRiotPort);
... ...
@@ -1736,7 +1733,22 @@ public class LandscapeServiceImpl implements LandscapeService {
1736 1733
1737 1734
private void sendMailAboutNewArchiveCandidate(
1738 1735
AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet) throws MailException {
1739
- sendMailToReplicaSetOwner(replicaSet, "StartingNewArchiveCandidateSubject", "StartingNewArchiveCandidateBody", Optional.empty());
1736
+ final ResourceBundleStringMessages stringMessages = ResourceBundleStringMessages.create(STRING_MESSAGES_BASE_NAME, getClass().getClassLoader(), StandardCharsets.UTF_8.name());
1737
+ final User currentUser = getSecurityService().getCurrentUser();
1738
+ if (currentUser != null && currentUser.isEmailValidated()) {
1739
+ final String subject = stringMessages.get(currentUser.getLocaleOrDefault(), "StartingNewArchiveCandidateSubject", replicaSet.getServerName());
1740
+ final String body = stringMessages.get(currentUser.getLocaleOrDefault(), "StartingNewArchiveCandidateBody", replicaSet.getServerName());
1741
+ getSecurityService().sendMail(currentUser.getName(), subject, body);
1742
+ } else {
1743
+ logger.warning("Not sending e-mail about new archive candidate to current user because no user is logged in or email address of logged in user "+
1744
+ (currentUser == null ? "" : currentUser.getName()+" ")+"is not validated");
1745
+ }
1746
+ sendMailToReplicaSetOwner(replicaSet, "RefrainFromArchivingSubject", "RefrainFromArchivingBody", Optional.empty());
1747
+ }
1748
+
1749
+ private void sendMailAboutNewArchiveServerLive(
1750
+ AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet) throws MailException {
1751
+ sendMailToReplicaSetOwner(replicaSet, "NewArchiveServerLiveSubject", "NewArchiveServerLiveBody", Optional.empty());
1740 1752
}
1741 1753
1742 1754
private void sendMailAboutMasterUnavailable(