java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/AbstractApplicationReplicaSetDialog.java
... ...
@@ -1,15 +1,8 @@
1 1
package com.sap.sailing.landscape.ui.client;
2 2
3
-import java.util.Collections;
4
-import java.util.Comparator;
5
-import java.util.LinkedList;
6
-import java.util.List;
7
-
8
-import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
9 3
import com.google.gwt.user.client.ui.SuggestBox;
10 4
import com.google.gwt.user.client.ui.TextBox;
11 5
import com.sap.sailing.landscape.ui.client.i18n.StringMessages;
12
-import com.sap.sse.common.Util;
13 6
import com.sap.sse.gwt.client.ErrorReporter;
14 7
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
15 8
... ...
@@ -45,16 +38,7 @@ public abstract class AbstractApplicationReplicaSetDialog<I extends AbstractAppl
45 38
Iterable<String> releaseNames, StringMessages stringMessages, ErrorReporter errorReporter, Validator<I> validator, DialogCallback<I> callback) {
46 39
super(title, /* message */ null, stringMessages.ok(), stringMessages.cancel(), validator, callback);
47 40
this.stringMessages = stringMessages;
48
- final List<String> releaseNamesAndLatestMaster = new LinkedList<>();
49
- Util.addAll(releaseNames, releaseNamesAndLatestMaster);
50
- final Comparator<String> newestFirstComaprator = (r1, r2)->r2.compareTo(r1);
51
- Collections.sort(releaseNamesAndLatestMaster, newestFirstComaprator);
52
- releaseNamesAndLatestMaster.add(0, stringMessages.latestMasterRelease());
53
- releaseNameBox = createSuggestBox(releaseNamesAndLatestMaster);
54
- if (releaseNameBox.getSuggestOracle() instanceof MultiWordSuggestOracle) {
55
- ((MultiWordSuggestOracle) releaseNameBox.getSuggestOracle()).setComparator(newestFirstComaprator);
56
- }
57
- releaseNameBox.setValue(stringMessages.latestMasterRelease());
41
+ releaseNameBox = LandscapeDialogUtil.createReleaseNameBox(stringMessages, releaseNames, this);
58 42
masterReplicationBearerTokenBox = createTextBox("", 40);
59 43
replicaReplicationBearerTokenBox = createTextBox("", 40);
60 44
}
... ...
@@ -67,11 +51,6 @@ public abstract class AbstractApplicationReplicaSetDialog<I extends AbstractAppl
67 51
return releaseNameBox;
68 52
}
69 53
70
- protected String getReleaseNameBoxValue() {
71
- return (!Util.hasLength(releaseNameBox.getValue()) || Util.equalsWithNull(releaseNameBox.getValue(), stringMessages.latestMasterRelease()))
72
- ? null : releaseNameBox.getValue();
73
- }
74
-
75 54
protected TextBox getMasterReplicationBearerTokenBox() {
76 55
return masterReplicationBearerTokenBox;
77 56
}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/AbstractNewProcessDialog.java
... ...
@@ -0,0 +1,120 @@
1
+package com.sap.sailing.landscape.ui.client;
2
+
3
+import com.google.gwt.user.client.ui.Grid;
4
+import com.google.gwt.user.client.ui.Label;
5
+import com.google.gwt.user.client.ui.ListBox;
6
+import com.google.gwt.user.client.ui.TextBox;
7
+import com.sap.sailing.landscape.common.SharedLandscapeConstants;
8
+import com.sap.sailing.landscape.ui.client.i18n.StringMessages;
9
+import com.sap.sse.gwt.client.ErrorReporter;
10
+import com.sap.sse.gwt.client.controls.IntegerBox;
11
+import com.sap.sse.gwt.client.dialog.DataEntryDialog;
12
+
13
+/**
14
+ * Allows the user to specify the parameters required for moving a replica set's master process to a different
15
+ * instance.
16
+ * <p>
17
+ *
18
+ * @author Axel Uhl (d043530)
19
+ *
20
+ */
21
+public abstract class AbstractNewProcessDialog<T> extends DataEntryDialog<T> {
22
+ public static class NewProcessInstructions {
23
+ private final String instanceTypeOrNull;
24
+ private final Integer optionalMemoryInMegabytesOrNull;
25
+ private final Integer optionalMemoryTotalSizeFactorOrNull;
26
+ private final String masterReplicationBearerToken;
27
+ private final String replicaReplicationBearerToken;
28
+
29
+ public NewProcessInstructions(String instanceTypeOrNull,
30
+ String masterReplicationBearerToken, String replicaReplicationBearerToken, Integer optionalMemoryInMegabytesOrNull,
31
+ Integer optionalMemoryTotalSizeFactorOrNull) {
32
+ this.instanceTypeOrNull = instanceTypeOrNull;
33
+ this.optionalMemoryInMegabytesOrNull = optionalMemoryInMegabytesOrNull;
34
+ this.optionalMemoryTotalSizeFactorOrNull = optionalMemoryTotalSizeFactorOrNull;
35
+ this.masterReplicationBearerToken = masterReplicationBearerToken;
36
+ this.replicaReplicationBearerToken = replicaReplicationBearerToken;
37
+ }
38
+ public String getDedicatedInstanceType() {
39
+ return instanceTypeOrNull;
40
+ }
41
+ public Integer getOptionalMemoryInMegabytesOrNull() {
42
+ return optionalMemoryInMegabytesOrNull;
43
+ }
44
+ public Integer getOptionalMemoryTotalSizeFactorOrNull() {
45
+ return optionalMemoryTotalSizeFactorOrNull;
46
+ }
47
+ public String getInstanceTypeOrNull() {
48
+ return instanceTypeOrNull;
49
+ }
50
+ public String getMasterReplicationBearerToken() {
51
+ return masterReplicationBearerToken;
52
+ }
53
+ public String getReplicaReplicationBearerToken() {
54
+ return replicaReplicationBearerToken;
55
+ }
56
+ }
57
+
58
+ protected final StringMessages stringMessages;
59
+ private final ListBox instanceTypeListBox;
60
+ private final Label instanceTypeLabel;
61
+ private final TextBox masterReplicationBearerTokenBox;
62
+ private final TextBox replicaReplicationBearerTokenBox;
63
+ private final IntegerBox memoryInMegabytesBox;
64
+ private final IntegerBox memoryTotalSizeFactorBox;
65
+
66
+ public AbstractNewProcessDialog(String title, LandscapeManagementWriteServiceAsync landscapeManagementService,
67
+ StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback<T> callback) {
68
+ super(title, /* message */ null, stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback);
69
+ this.stringMessages = stringMessages;
70
+ instanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
71
+ stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
72
+ instanceTypeLabel = new Label();
73
+ masterReplicationBearerTokenBox = createTextBox("", 40);
74
+ replicaReplicationBearerTokenBox = createTextBox("", 40);
75
+ memoryInMegabytesBox = createIntegerBox(null, 7);
76
+ memoryTotalSizeFactorBox = createIntegerBox(null, 2);
77
+ getMemoryInMegabytesBox().addValueChangeHandler(e->getMemoryTotalSizeFactorBox().setEnabled(e.getValue() == null));
78
+ }
79
+
80
+ @Override
81
+ protected Grid getAdditionalWidget() {
82
+ final Grid result = new Grid(5, 2);
83
+ int row=0;
84
+ result.setWidget(row, 0, getInstanceTypeLabel());
85
+ result.setWidget(row++, 1, getInstanceTypeListBox());
86
+ result.setWidget(row, 0, new Label(stringMessages.bearerTokenForSecurityReplication()));
87
+ result.setWidget(row++, 1, getMasterReplicationBearerTokenBox());
88
+ result.setWidget(row, 0, new Label(stringMessages.replicaReplicationBearerToken()));
89
+ result.setWidget(row++, 1, getReplicaReplicationBearerTokenBox());
90
+ result.setWidget(row, 0, new Label(stringMessages.memoryInMegabytes()));
91
+ result.setWidget(row++, 1, getMemoryInMegabytesBox());
92
+ result.setWidget(row, 0, new Label(stringMessages.memoryTotalSizeFactor()));
93
+ result.setWidget(row++, 1, getMemoryTotalSizeFactorBox());
94
+ return result;
95
+ }
96
+
97
+ protected IntegerBox getMemoryTotalSizeFactorBox() {
98
+ return memoryTotalSizeFactorBox;
99
+ }
100
+
101
+ protected IntegerBox getMemoryInMegabytesBox() {
102
+ return memoryInMegabytesBox;
103
+ }
104
+
105
+ protected TextBox getReplicaReplicationBearerTokenBox() {
106
+ return replicaReplicationBearerTokenBox;
107
+ }
108
+
109
+ protected TextBox getMasterReplicationBearerTokenBox() {
110
+ return masterReplicationBearerTokenBox;
111
+ }
112
+
113
+ protected Label getInstanceTypeLabel() {
114
+ return instanceTypeLabel;
115
+ }
116
+
117
+ protected ListBox getInstanceTypeListBox() {
118
+ return instanceTypeListBox;
119
+ }
120
+}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/CreateApplicationReplicaSetDialog.java
... ...
@@ -319,7 +319,7 @@ public class CreateApplicationReplicaSetDialog extends AbstractApplicationReplic
319 319
return new CreateApplicationReplicaSetInstructions(nameBox.getValue(), sharedMasterInstanceBox.getValue(),
320 320
getDedicatedInstanceTypeListBox().getSelectedValue(),
321 321
getSharedInstanceTypeListBox().getSelectedValue(),
322
- getReleaseNameBoxValue(), dynamicLoadBalancerCheckBox==null?false:dynamicLoadBalancerCheckBox.getValue(),
322
+ LandscapeDialogUtil.getReleaseNameBoxValue(getReleaseNameBox(), stringMessages), dynamicLoadBalancerCheckBox==null?false:dynamicLoadBalancerCheckBox.getValue(),
323 323
getMasterReplicationBearerTokenBox().getValue(), getReplicaReplicationBearerTokenBox().getValue(),
324 324
domainNameBox.getValue(), memoryInMegabytesBox.getValue(), memoryTotalSizeFactorBox.getValue(),
325 325
igtimiRiotPortBox.getValue(), startWithReplicaOnSharedInstanceBox.getValue());
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeDialogUtil.java
... ...
@@ -2,10 +2,16 @@ package com.sap.sailing.landscape.ui.client;
2 2
3 3
import java.util.ArrayList;
4 4
import java.util.Collections;
5
+import java.util.Comparator;
6
+import java.util.LinkedList;
7
+import java.util.List;
5 8
6 9
import com.google.gwt.user.client.rpc.AsyncCallback;
7 10
import com.google.gwt.user.client.ui.ListBox;
11
+import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
12
+import com.google.gwt.user.client.ui.SuggestBox;
8 13
import com.sap.sailing.landscape.ui.client.i18n.StringMessages;
14
+import com.sap.sse.common.Util;
9 15
import com.sap.sse.common.util.NaturalComparator;
10 16
import com.sap.sse.gwt.client.ErrorReporter;
11 17
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
... ...
@@ -67,4 +73,23 @@ public class LandscapeDialogUtil {
67 73
}
68 74
}
69 75
}
76
+
77
+ public static SuggestBox createReleaseNameBox(StringMessages stringMessages, Iterable<String> releaseNames, DataEntryDialog<?> dialog) {
78
+ final List<String> releaseNamesAndLatestMaster = new LinkedList<>();
79
+ Util.addAll(releaseNames, releaseNamesAndLatestMaster);
80
+ final Comparator<String> newestFirstComaprator = (r1, r2)->r2.compareTo(r1);
81
+ Collections.sort(releaseNamesAndLatestMaster, newestFirstComaprator);
82
+ releaseNamesAndLatestMaster.add(0, stringMessages.latestMasterRelease());
83
+ SuggestBox releaseNameBox = dialog.createSuggestBox(releaseNamesAndLatestMaster);
84
+ if (releaseNameBox.getSuggestOracle() instanceof MultiWordSuggestOracle) {
85
+ ((MultiWordSuggestOracle) releaseNameBox.getSuggestOracle()).setComparator(newestFirstComaprator);
86
+ }
87
+ releaseNameBox.setValue(stringMessages.latestMasterRelease());
88
+ return releaseNameBox;
89
+ }
90
+
91
+ public static String getReleaseNameBoxValue(SuggestBox releaseNameBox, StringMessages stringMessages) {
92
+ return (!Util.hasLength(releaseNameBox.getValue()) || Util.equalsWithNull(releaseNameBox.getValue(), stringMessages.latestMasterRelease()))
93
+ ? null : releaseNameBox.getValue();
94
+ }
70 95
}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementPanel.java
... ...
@@ -1466,33 +1466,28 @@ public class LandscapeManagementPanel extends SimplePanel {
1466 1466
}
1467 1467
1468 1468
@Override
1469
- public void onSuccess(ArrayList<ReleaseDTO> result) {
1470
- new UpgradeArchiveServerDialog(landscapeManagementService, result.stream().map(r->r.getName())::iterator,
1469
+ public void onSuccess(ArrayList<ReleaseDTO> releases) {
1470
+ new UpgradeArchiveServerDialog(landscapeManagementService, releases.stream().map(r->r.getName())::iterator,
1471 1471
stringMessages, errorReporter, new DialogCallback<UpgradeArchiveServerDialog.UpgradeArchiveServerInstructions>() {
1472 1472
@Override
1473 1473
public void ok(UpgradeArchiveServerInstructions upgradeInstructions) {
1474
- landscapeManagementService.createArchiveReplicaSet(regionId, replicaSet, upgradeInstructions.getOptionalInstanceType(),
1474
+ landscapeManagementService.createArchiveReplicaSet(regionId, replicaSet, upgradeInstructions.getInstanceTypeOrNull(),
1475 1475
upgradeInstructions.getReleaseNameOrNullForLatestMaster(), sshKeyManagementPanel.getSelectedKeyPair()==null?null:sshKeyManagementPanel.getSelectedKeyPair().getName(),
1476 1476
sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption() != null
1477 1477
? sshKeyManagementPanel.getPassphraseForPrivateKeyDecryption().getBytes() : null,
1478 1478
upgradeInstructions.getMasterReplicationBearerToken(), upgradeInstructions.getReplicaReplicationBearerToken(),
1479
- new AsyncCallback<SailingApplicationReplicaSetDTO<String>>() {
1479
+ upgradeInstructions.getOptionalMemoryInMegabytesOrNull(), upgradeInstructions.getOptionalMemoryTotalSizeFactorOrNull(),
1480
+ new AsyncCallback<Void>() {
1480 1481
@Override
1481 1482
public void onFailure(Throwable caught) {
1482 1483
errorReporter.reportError(caught.getMessage());
1483 1484
}
1484 1485
1485 1486
@Override
1486
- public void onSuccess(SailingApplicationReplicaSetDTO<String> result) {
1487
- if (result != null) {
1488
- Notification.notify(stringMessages.successfullyUpgradedApplicationReplicaSet(
1489
- result.getName(), result.getVersion()), NotificationType.SUCCESS);
1490
- applicationReplicaSetsTable.replaceBasedOnEntityIdentityComparator(result);
1491
- applicationReplicaSetsTable.refresh();
1492
- } else {
1493
- Notification.notify(stringMessages.upgradingApplicationReplicaSetFailed(replicaSet.getName()),
1494
- NotificationType.ERROR);
1495
- }
1487
+ public void onSuccess(Void result) {
1488
+ Notification.notify(stringMessages.successfullyLaunchedNewArchiveCandidate(
1489
+ replicaSet.getName(), upgradeInstructions.getReleaseNameOrNullForLatestMaster()),
1490
+ NotificationType.SUCCESS);
1496 1491
}
1497 1492
});
1498 1493
}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementWriteService.java
... ...
@@ -166,9 +166,10 @@ public interface LandscapeManagementWriteService extends RemoteService {
166 166
SailingApplicationReplicaSetDTO<String> replicaSet, String instanceTypeName,
167 167
String optionalKeyName, byte[] privateKeyEncryptionPassphrase) throws Exception;
168 168
169
- SailingApplicationReplicaSetDTO<String> createArchiveReplicaSet(
169
+ void createArchiveReplicaSet(
170 170
String regionId, SailingApplicationReplicaSetDTO<String> applicationReplicaSetToUpgrade, String optionalSharedInstanceType, String releaseOrNullForLatestMaster,
171
- String optionalKeyName, byte[] privateKeyEncryptionPassphrase, String securityReplicationBearerToken, String replicaReplicationBearerToken) throws Exception;
171
+ String optionalKeyName, byte[] privateKeyEncryptionPassphrase, String securityReplicationBearerToken, String replicaReplicationBearerToken,
172
+ Integer optionalMemoryInMegabytesOrNull, Integer optionalMemoryTotalSizeFactorOrNull) throws Exception;
172 173
173 174
ArrayList<LeaderboardNameDTO> getLeaderboardNames(SailingApplicationReplicaSetDTO<String> replicaSet, String bearerToken) throws Exception;
174 175
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/LandscapeManagementWriteServiceAsync.java
... ...
@@ -192,7 +192,8 @@ public interface LandscapeManagementWriteServiceAsync {
192 192
193 193
void createArchiveReplicaSet(String regionId, SailingApplicationReplicaSetDTO<String> applicationReplicaSetToUpgrade,
194 194
String optionalSharedInstanceType, String releaseOrNullForLatestMaster, String optionalKeyName,
195
- byte[] privateKeyEncryptionPassphrase, String securityReplicationBearerToken, String replicaReplicationBearerToken, AsyncCallback<SailingApplicationReplicaSetDTO<String>> callback);
195
+ byte[] privateKeyEncryptionPassphrase, String securityReplicationBearerToken, String replicaReplicationBearerToken,
196
+ Integer optionalMemoryInMegabytesOrNull, Integer optionalMemoryTotalSizeFactorOrNull, AsyncCallback<Void> callback);
196 197
197 198
/**
198 199
* For the given replica set ensures there is at least one healthy replica, then stops replicating on all replicas and
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/MoveMasterProcessDialog.java
... ...
@@ -3,14 +3,9 @@ package com.sap.sailing.landscape.ui.client;
3 3
import com.google.gwt.user.client.ui.CheckBox;
4 4
import com.google.gwt.user.client.ui.Grid;
5 5
import com.google.gwt.user.client.ui.Label;
6
-import com.google.gwt.user.client.ui.ListBox;
7
-import com.google.gwt.user.client.ui.TextBox;
8
-import com.google.gwt.user.client.ui.Widget;
9 6
import com.sap.sailing.landscape.common.SharedLandscapeConstants;
10 7
import com.sap.sailing.landscape.ui.client.i18n.StringMessages;
11 8
import com.sap.sse.gwt.client.ErrorReporter;
12
-import com.sap.sse.gwt.client.controls.IntegerBox;
13
-import com.sap.sse.gwt.client.dialog.DataEntryDialog;
14 9
15 10
/**
16 11
* Allows the user to specify the parameters required for moving a replica set's master process to a different
... ...
@@ -20,115 +15,63 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog;
20 15
* @author Axel Uhl (d043530)
21 16
*
22 17
*/
23
-public class MoveMasterProcessDialog extends DataEntryDialog<MoveMasterProcessDialog.MoveMasterToOtherInstanceInstructions> {
18
+public class MoveMasterProcessDialog extends AbstractNewProcessDialog<MoveMasterProcessDialog.MoveMasterToOtherInstanceInstructions> {
24 19
25
- public static class MoveMasterToOtherInstanceInstructions {
20
+ public static class MoveMasterToOtherInstanceInstructions extends AbstractNewProcessDialog.NewProcessInstructions {
26 21
private final boolean sharedMasterInstance;
27
- private final String instanceTypeOrNull;
28
- private final Integer optionalMemoryInMegabytesOrNull;
29
- private final Integer optionalMemoryTotalSizeFactorOrNull;
30
- private final String masterReplicationBearerToken;
31
- private final String replicaReplicationBearerToken;
32 22
33 23
public MoveMasterToOtherInstanceInstructions(boolean sharedMasterInstance,
34 24
String instanceTypeOrNull,
35 25
String masterReplicationBearerToken, String replicaReplicationBearerToken, Integer optionalMemoryInMegabytesOrNull,
36 26
Integer optionalMemoryTotalSizeFactorOrNull) {
27
+ super(instanceTypeOrNull, masterReplicationBearerToken, replicaReplicationBearerToken, optionalMemoryInMegabytesOrNull, optionalMemoryTotalSizeFactorOrNull);
37 28
this.sharedMasterInstance = sharedMasterInstance;
38
- this.instanceTypeOrNull = instanceTypeOrNull;
39
- this.optionalMemoryInMegabytesOrNull = optionalMemoryInMegabytesOrNull;
40
- this.optionalMemoryTotalSizeFactorOrNull = optionalMemoryTotalSizeFactorOrNull;
41
- this.masterReplicationBearerToken = masterReplicationBearerToken;
42
- this.replicaReplicationBearerToken = replicaReplicationBearerToken;
43 29
}
44 30
public boolean isSharedMasterInstance() {
45 31
return sharedMasterInstance;
46 32
}
47
- public String getDedicatedInstanceType() {
48
- return instanceTypeOrNull;
49
- }
50
- public Integer getOptionalMemoryInMegabytesOrNull() {
51
- return optionalMemoryInMegabytesOrNull;
52
- }
53
- public Integer getOptionalMemoryTotalSizeFactorOrNull() {
54
- return optionalMemoryTotalSizeFactorOrNull;
55
- }
56
- public String getInstanceTypeOrNull() {
57
- return instanceTypeOrNull;
58
- }
59
- public String getMasterReplicationBearerToken() {
60
- return masterReplicationBearerToken;
61
- }
62
- public String getReplicaReplicationBearerToken() {
63
- return replicaReplicationBearerToken;
64
- }
65 33
}
66 34
67
- private final StringMessages stringMessages;
68 35
private final CheckBox sharedMasterInstanceBox;
69
- private final ListBox instanceTypeListBox;
70
- private final Label instanceTypeLabel;
71
- private final TextBox masterReplicationBearerTokenBox;
72
- private final TextBox replicaReplicationBearerTokenBox;
73
- private final IntegerBox memoryInMegabytesBox;
74
- private final IntegerBox memoryTotalSizeFactorBox;
75 36
private boolean memoryAsFactorToTotalMemoryAdjusted;
76 37
77 38
public MoveMasterProcessDialog(LandscapeManagementWriteServiceAsync landscapeManagementService,
78 39
StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback<MoveMasterToOtherInstanceInstructions> callback) {
79
- super(stringMessages.moveMasterToOtherInstance(), /* message */ null, stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback);
80
- this.stringMessages = stringMessages;
81
- instanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
82
- stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
83
- instanceTypeLabel = new Label();
84
- masterReplicationBearerTokenBox = createTextBox("", 40);
85
- replicaReplicationBearerTokenBox = createTextBox("", 40);
86
- memoryInMegabytesBox = createIntegerBox(null, 7);
87
- memoryTotalSizeFactorBox = createIntegerBox(null, 2);
88
- memoryTotalSizeFactorBox.addValueChangeHandler(e->memoryAsFactorToTotalMemoryAdjusted=true);
89
- memoryInMegabytesBox.addValueChangeHandler(e->memoryTotalSizeFactorBox.setEnabled(e.getValue() == null));
40
+ super(stringMessages.moveMasterToOtherInstance(), landscapeManagementService, stringMessages, errorReporter, callback);
41
+ getMemoryTotalSizeFactorBox().addValueChangeHandler(e->memoryAsFactorToTotalMemoryAdjusted=true);
90 42
sharedMasterInstanceBox = createCheckbox(stringMessages.sharedMasterInstance());
91 43
sharedMasterInstanceBox.addValueChangeHandler(e->updateInstanceTypeBasedOnSharedMasterInstanceBox());
92 44
updateInstanceTypeBasedOnSharedMasterInstanceBox();
93 45
}
94 46
95 47
private void updateInstanceTypeBasedOnSharedMasterInstanceBox() {
96
- instanceTypeLabel.setText(sharedMasterInstanceBox.getValue() ? stringMessages.sharedMasterInstanceType() : stringMessages.dedicatedInstanceType());
97
- LandscapeDialogUtil.selectInstanceType(instanceTypeListBox,
48
+ getInstanceTypeLabel().setText(sharedMasterInstanceBox.getValue() ? stringMessages.sharedMasterInstanceType() : stringMessages.dedicatedInstanceType());
49
+ LandscapeDialogUtil.selectInstanceType(getInstanceTypeListBox(),
98 50
sharedMasterInstanceBox.getValue() ? SharedLandscapeConstants.DEFAULT_SHARED_INSTANCE_TYPE_NAME : SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME);
99 51
if (!memoryAsFactorToTotalMemoryAdjusted) {
100 52
if (sharedMasterInstanceBox.getValue()) {
101
- memoryTotalSizeFactorBox.setValue(SharedLandscapeConstants.DEFAULT_NUMBER_OF_PROCESSES_IN_MEMORY);
53
+ getMemoryTotalSizeFactorBox().setValue(SharedLandscapeConstants.DEFAULT_NUMBER_OF_PROCESSES_IN_MEMORY);
102 54
} else {
103
- memoryTotalSizeFactorBox.setText("");
55
+ getMemoryTotalSizeFactorBox().setText("");
104 56
}
105 57
}
106 58
}
107 59
108 60
@Override
109
- protected Widget getAdditionalWidget() {
110
- final Grid result = new Grid(6, 2);
61
+ protected Grid getAdditionalWidget() {
62
+ final Grid result = super.getAdditionalWidget();
111 63
int row=0;
64
+ result.insertRow(row);
112 65
result.setWidget(row, 0, new Label(stringMessages.sharedMasterInstance()));
113 66
result.setWidget(row++, 1, sharedMasterInstanceBox);
114
- result.setWidget(row, 0, instanceTypeLabel);
115
- result.setWidget(row++, 1, instanceTypeListBox);
116
- result.setWidget(row, 0, new Label(stringMessages.bearerTokenForSecurityReplication()));
117
- result.setWidget(row++, 1, masterReplicationBearerTokenBox);
118
- result.setWidget(row, 0, new Label(stringMessages.replicaReplicationBearerToken()));
119
- result.setWidget(row++, 1, replicaReplicationBearerTokenBox);
120
- result.setWidget(row, 0, new Label(stringMessages.memoryInMegabytes()));
121
- result.setWidget(row++, 1, memoryInMegabytesBox);
122
- result.setWidget(row, 0, new Label(stringMessages.memoryTotalSizeFactor()));
123
- result.setWidget(row++, 1, memoryTotalSizeFactorBox);
124 67
return result;
125 68
}
126 69
127 70
@Override
128 71
protected MoveMasterToOtherInstanceInstructions getResult() {
129 72
return new MoveMasterToOtherInstanceInstructions(sharedMasterInstanceBox.getValue(),
130
- instanceTypeListBox.getSelectedValue(),
131
- masterReplicationBearerTokenBox.getValue(), replicaReplicationBearerTokenBox.getValue(),
132
- memoryInMegabytesBox.getValue(), memoryTotalSizeFactorBox.getValue());
73
+ getInstanceTypeListBox().getSelectedValue(),
74
+ getMasterReplicationBearerTokenBox().getValue(), getReplicaReplicationBearerTokenBox().getValue(),
75
+ getMemoryInMegabytesBox().getValue(), getMemoryTotalSizeFactorBox().getValue());
133 76
}
134 77
}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/UpgradeApplicationReplicaSetDialog.java
... ...
@@ -40,6 +40,8 @@ public class UpgradeApplicationReplicaSetDialog extends AbstractApplicationRepli
40 40
41 41
@Override
42 42
protected UpgradeApplicationReplicaSetInstructions getResult() {
43
- return new UpgradeApplicationReplicaSetInstructions(getReleaseNameBoxValue(), getMasterReplicationBearerTokenBox().getValue(), getReplicaReplicationBearerTokenBox().getValue());
43
+ return new UpgradeApplicationReplicaSetInstructions(
44
+ LandscapeDialogUtil.getReleaseNameBoxValue(getReleaseNameBox(), stringMessages),
45
+ getMasterReplicationBearerTokenBox().getValue(), getReplicaReplicationBearerTokenBox().getValue());
44 46
}
45 47
}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/UpgradeArchiveServerDialog.java
... ...
@@ -3,64 +3,54 @@ package com.sap.sailing.landscape.ui.client;
3 3
import com.google.gwt.user.client.ui.FocusWidget;
4 4
import com.google.gwt.user.client.ui.Grid;
5 5
import com.google.gwt.user.client.ui.Label;
6
-import com.google.gwt.user.client.ui.ListBox;
7
-import com.google.gwt.user.client.ui.Widget;
8
-import com.sap.sailing.landscape.common.SharedLandscapeConstants;
6
+import com.google.gwt.user.client.ui.SuggestBox;
9 7
import com.sap.sailing.landscape.ui.client.i18n.StringMessages;
10 8
import com.sap.sse.gwt.client.ErrorReporter;
11 9
12
-public class UpgradeArchiveServerDialog extends AbstractApplicationReplicaSetDialog<UpgradeArchiveServerDialog.UpgradeArchiveServerInstructions> {
10
+public class UpgradeArchiveServerDialog extends AbstractNewProcessDialog<UpgradeArchiveServerDialog.UpgradeArchiveServerInstructions> {
13 11
14
- public static class UpgradeArchiveServerInstructions extends AbstractApplicationReplicaSetDialog.AbstractApplicationReplicaSetInstructions {
15
- private final String optionalInstanceType;
16
- public UpgradeArchiveServerInstructions(String releaseNameOrNullForLatestMaster, String masterReplicationBearerToken, String replicaReplicationBearerToken, String optionalInstanceType) {
17
- super(releaseNameOrNullForLatestMaster, masterReplicationBearerToken, replicaReplicationBearerToken);
18
- this.optionalInstanceType = optionalInstanceType;
12
+ public static class UpgradeArchiveServerInstructions extends AbstractNewProcessDialog.NewProcessInstructions {
13
+ private final String releaseNameOrNullForLatestMaster;
14
+
15
+ public UpgradeArchiveServerInstructions(String releaseNameOrNullForLatestMaster,
16
+ String masterReplicationBearerToken, String replicaReplicationBearerToken, String optionalInstanceType,
17
+ Integer optionalMemoryInMegabytesOrNull, Integer optionalMemoryTotalSizeFactorOrNull) {
18
+ super(optionalInstanceType, masterReplicationBearerToken, replicaReplicationBearerToken, optionalMemoryInMegabytesOrNull, optionalMemoryTotalSizeFactorOrNull);
19
+ this.releaseNameOrNullForLatestMaster = releaseNameOrNullForLatestMaster;
19 20
}
20
- public String getOptionalInstanceType() {
21
- return optionalInstanceType;
21
+
22
+ public String getReleaseNameOrNullForLatestMaster() {
23
+ return releaseNameOrNullForLatestMaster;
22 24
}
23 25
}
24 26
25
- private final StringMessages stringMessages;
26
- private final ListBox sharedInstanceTypeListBox;
27
+ private final SuggestBox releaseNameBox;
27 28
28 29
public UpgradeArchiveServerDialog(LandscapeManagementWriteServiceAsync landscapeManagementService, Iterable<String> releaseNames,
29 30
StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback<UpgradeArchiveServerInstructions> callback) {
30
- super(stringMessages.upgradeArchiveServer(), landscapeManagementService, releaseNames, stringMessages, errorReporter, /* validator */ null, callback);
31
- this.stringMessages = stringMessages;
32
- sharedInstanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
33
- stringMessages, SharedLandscapeConstants.DEFAULT_SHARED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
34
-
35
- }
36
-
37
- protected ListBox getSharedInstanceTypeListBox() {
38
- return sharedInstanceTypeListBox;
31
+ super(stringMessages.upgradeArchiveServer(), landscapeManagementService, stringMessages, errorReporter, callback);
32
+ releaseNameBox = LandscapeDialogUtil.createReleaseNameBox(stringMessages, releaseNames, this);
39 33
}
40 34
41 35
@Override
42
- protected Widget getAdditionalWidget() {
43
- final Grid result = new Grid(4, 2);
36
+ protected Grid getAdditionalWidget() {
37
+ final Grid result = super.getAdditionalWidget();
44 38
int row=0;
39
+ result.insertRow(row);
45 40
result.setWidget(row, 0, new Label(stringMessages.release()));
46
- result.setWidget(row++, 1, getReleaseNameBox());
47
- result.setWidget(row, 0, new Label(stringMessages.instanceType()));
48
- result.setWidget(row++, 1, getSharedInstanceTypeListBox());
49
- result.setWidget(row, 0, new Label(stringMessages.bearerTokenForSecurityReplication()));
50
- result.setWidget(row++, 1, getMasterReplicationBearerTokenBox());
51
- result.setWidget(row, 0, new Label(stringMessages.bearerTokenOrNullForArchive()));
52
- result.setWidget(row++, 1, getReplicaReplicationBearerTokenBox());
41
+ result.setWidget(row++, 1, releaseNameBox);
53 42
return result;
54 43
}
55 44
56 45
@Override
57 46
public FocusWidget getInitialFocusWidget() {
58
- return getReleaseNameBox().getValueBox();
47
+ return releaseNameBox.getValueBox();
59 48
}
60 49
61 50
@Override
62 51
protected UpgradeArchiveServerInstructions getResult() {
63
- return new UpgradeArchiveServerInstructions(getReleaseNameBoxValue(), getMasterReplicationBearerTokenBox().getValue(),
64
- getReplicaReplicationBearerTokenBox().getValue(), getSharedInstanceTypeListBox().getSelectedValue());
52
+ return new UpgradeArchiveServerInstructions(LandscapeDialogUtil.getReleaseNameBoxValue(releaseNameBox, stringMessages), getMasterReplicationBearerTokenBox().getValue(),
53
+ getReplicaReplicationBearerTokenBox().getValue(), getInstanceTypeListBox().getSelectedValue(),
54
+ getMemoryInMegabytesBox().getValue(), getMemoryTotalSizeFactorBox().getValue());
65 55
}
66 56
}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/i18n/StringMessages.java
... ...
@@ -180,4 +180,5 @@ com.sap.sse.gwt.adminconsole.StringMessages {
180 180
String privateIp();
181 181
String igtimiRiotPort();
182 182
String examplePort(int examplePort);
183
+ String successfullyLaunchedNewArchiveCandidate(String replicaSetName, String releaseName);
183 184
}
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/i18n/StringMessages.properties
... ...
@@ -168,4 +168,5 @@ runOnExisting=Run on an existing, running instance
168 168
publicIp=Public IP address
169 169
privateIp=Private IP address
170 170
igtimiRiotPort=Igtimi Riot Port
171
-examplePort=e.g., {0}
... ...
\ No newline at end of file
0
+examplePort=e.g., {0}
1
+successfullyLaunchedNewArchiveCandidate=Successfully launched new {0} candidate with release {1}. You will receive an e-mail when the candidate is ready for spot checks and rotation to production. This can take several hours, depending on the number of events to load.
... ...
\ No newline at end of file
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/client/i18n/StringMessages_de.properties
... ...
@@ -167,4 +167,5 @@ runOnExisting=Auf anderem laufenden Server ausführen
167 167
publicIp=Öffentlich IP-Adresse
168 168
privateIP=Private IP-Adresse
169 169
igtimiRiotPort=Igtimi Riot Port
170
-examplePort=z.B. {0}
... ...
\ No newline at end of file
0
+examplePort=z.B. {0}
1
+successfullyLaunchedNewArchiveCandidate=Neuen Kandidaten für {0} mit Version {1} gestartet. Es erfolgt eine Benachrichtigung per e-Mail. Das kann, je nach Umfang der zu ladenden Daten, etliche Stunden dauern.
... ...
\ No newline at end of file
java/com.sap.sailing.landscape.ui/src/com/sap/sailing/landscape/ui/server/LandscapeManagementWriteServiceImpl.java
... ...
@@ -679,17 +679,18 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
679 679
}
680 680
681 681
@Override
682
- public SailingApplicationReplicaSetDTO<String> createArchiveReplicaSet(String regionId, SailingApplicationReplicaSetDTO<String> archiveReplicaSetToUpgrade,
682
+ public void createArchiveReplicaSet(String regionId, SailingApplicationReplicaSetDTO<String> archiveReplicaSetToUpgrade,
683 683
String instanceType, String releaseNameOrNullForLatestMaster, String optionalKeyName,
684 684
byte[] privateKeyEncryptionPassphrase, String securityReplicationBearerToken,
685
- String replicaReplicationBearerToken) throws Exception {
685
+ String replicaReplicationBearerToken, Integer optionalMemoryInMegabytesOrNull, Integer optionalMemoryTotalSizeFactorOrNull) throws Exception {
686
+ // TODO bug6203: we also should provide a possibility to specify memory size; if not provided, we should clone the current archive's settings
686 687
checkLandscapeManageAwsPermission();
687 688
final String userSetOrArchiveServerSecurityReplicationBearerToken;
688 689
final AwsRegion region = new AwsRegion(regionId, getLandscape());
689 690
final AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> awsReplicaSet =
690 691
convertFromApplicationReplicaSetDTO(region, archiveReplicaSetToUpgrade, optionalKeyName, privateKeyEncryptionPassphrase);
691 692
final SailingAnalyticsProcess<String> master = awsReplicaSet.getMaster();
692
- if(Util.hasLength(securityReplicationBearerToken)) {
693
+ if (Util.hasLength(securityReplicationBearerToken)) {
693 694
userSetOrArchiveServerSecurityReplicationBearerToken = securityReplicationBearerToken;
694 695
} else {
695 696
userSetOrArchiveServerSecurityReplicationBearerToken = master.getEnvShValueFor(
... ...
@@ -697,24 +698,16 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
697 698
Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.of(optionalKeyName), privateKeyEncryptionPassphrase);
698 699
}
699 700
final String replicaSetName = SharedLandscapeConstants.ARCHIVE_SERVER_APPLICATION_REPLICA_SET_NAME;
700
- final String archiveCandidateSubDomain = SharedLandscapeConstants.ARCHIVE_CANDIDATE_SUBDOMAIN;
701 701
final String domainName = AwsLandscape.getHostedZoneName(archiveReplicaSetToUpgrade.getHostname());
702
- final Release release = getLandscapeService().getRelease(releaseNameOrNullForLatestMaster);
703 702
final Database databaseConfiguration = master.getDatabaseConfiguration(region,
704 703
Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.ofNullable(optionalKeyName),
705 704
privateKeyEncryptionPassphrase);
706
- final AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> result = getLandscapeService()
705
+ getLandscapeService()
707 706
.createArchiveReplicaSet(regionId, replicaSetName, instanceType, releaseNameOrNullForLatestMaster,
708 707
databaseConfiguration, optionalKeyName, privateKeyEncryptionPassphrase,
709 708
userSetOrArchiveServerSecurityReplicationBearerToken, replicaReplicationBearerToken, domainName,
710
- /* optionalMemoryInMegabytesOrNull */ null, /* optionalMemoryTotalSizeFactorOrNull */ null,
709
+ /* optionalMemoryInMegabytesOrNull TODO bug6203 */ null, /* optionalMemoryTotalSizeFactorOrNull TODO bug6203 */ null,
711 710
/* optionalIgtimiRiotPort */ null);
712
- return new SailingApplicationReplicaSetDTO<String>(result.getName(),
713
- convertToSailingAnalyticsProcessDTO(result
714
- .getMaster(), Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase), /* replicas */ Collections.emptySet(),
715
- release.getName(), release.getReleaseNotesURL().toString(),
716
- getLandscapeService().getFullyQualifiedHostname(archiveCandidateSubDomain, Optional.ofNullable(domainName)),
717
- /* redirect rule */ null, /* autoScalingGroup */ null);
718 711
}
719 712
720 713
/**
java/com.sap.sailing.landscape/resources/stringmessages/SailingLandscape_StringMessages.properties
... ...
@@ -13,4 +13,6 @@ StartingToArchiveReplicaSetBody=Starting to archive a replica set {0}.\nWhile th
13 13
FinishedToArchiveReplicaSetIntoSubject=Archiving a replica set to {0} finished
14 14
FinishedToArchiveReplicaSetIntoBody=Archiving a replica set to {0} has finished.\nYou can now archive other content to {0} if you want.\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.
15 15
FinishedToArchiveReplicaSetSubject=Archiving replica set {0} finished
16
-FinishedToArchiveReplicaSetBody=Archiving replica set {0} has finished.\nIf you requested so, the original replica set has been removed.\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.
... ...
\ No newline at end of file
0
+FinishedToArchiveReplicaSetBody=Archiving replica set {0} has finished.\nIf you requested so, the original replica set has been removed.\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.
1
+NewArchiveCandidateReadyForSpotChecksAndRotationSubject=The new {0} candidate is ready for spot checks
2
+NewArchiveCandidateReadyForSpotChecksAndRotationBody=We''ve run the following checks:\n{3}.\nThe new {0} candidate is ready for spot checks and, if OK, rotation to become the new production {0}.\nRun your spot checks at https://{1}/gwt/Home.html#EventsPlace: and compare to https://{2}/gwt/Home.html#EventsPlace:.\nStart the rotation to the new production server at https://security-service.sapsailing.com/sailingserver/api/v1/TODO after successful checks.
... ...
\ No newline at end of file
java/com.sap.sailing.landscape/resources/stringmessages/SailingLandscape_StringMessages_de.properties
... ...
@@ -13,4 +13,6 @@ StartingToArchiveReplicaSetBody=Das Anwendungs-Cluster {0} wird jetzt archiviert
13 13
FinishedToArchiveReplicaSetIntoSubject=Archivierung des Anwendungs-Clusters nach {0} beendet
14 14
FinishedToArchiveReplicaSetIntoBody=Die Archivierung des Anwendungs-Clusters nach {0} ist beendet.\nAb jetzt sind bei Bedarf weitere Archivierungen nach {0} möglich.\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.
15 15
FinishedToArchiveReplicaSetSubject=Archivierung des Anwendungs-Clusters {0} beendet
16
-FinishedToArchiveReplicaSetBody=Die Archivierung des Anwendungs-Clusters {0} ist beendet.\nFalls angefragt, wurde das Original Anwendungs-Cluster entfernt.\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.
... ...
\ No newline at end of file
0
+FinishedToArchiveReplicaSetBody=Die Archivierung des Anwendungs-Clusters {0} ist beendet.\nFalls angefragt, wurde das Original Anwendungs-Cluster entfernt.\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.
1
+NewArchiveCandidateReadyForSpotChecksAndRotationSubject=Der neue {0} Kandidat ist bereit für einen stichprobenartigen Vergleich
2
+NewArchiveCandidateReadyForSpotChecksAndRotationBody=Es wurden die folgenden Prüfungen durchgeführt:\n{3}.\nDer neue {0} Kandidat ist bereit für einen stichprobenartigen Vergleich\nund, falls OK, Rotation zum neuen Produktiv-Server für {0}.\nStichprobenartiger Vergleich unter https://{1}/gwt/Home.html#EventsPlace: und https://{2}/gwt/Home.html#EventsPlace:.\nRotation nach erfolgreichen Prüfungen unter https://security-service.sapsailing.com/sailingserver/api/v1/TODO starten.
... ...
\ No newline at end of file
java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/LandscapeService.java
... ...
@@ -157,7 +157,7 @@ public interface LandscapeService {
157 157
Integer optionalIgtimiRiotPort, Optional<Integer> minimumAutoScalingGroupSize, Optional<Integer> maximumAutoScalingGroupSize)
158 158
throws Exception;
159 159
160
- AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> createArchiveReplicaSet(
160
+ void createArchiveReplicaSet(
161 161
String regionId, String name, String instanceType, String releaseNameOrNullForLatestMaster, Database databaseConfiguration,
162 162
String optionalKeyName, byte[] privateKeyEncryptionPassphrase, String securityServiceReplicationBearerToken,
163 163
String replicaReplicationBearerToken, String optionalDomainName, Integer optionalMemoryInMegabytesOrNull,
java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/ArchiveCandidateMonitoringBackgroundTask.java
... ...
@@ -4,6 +4,7 @@ import java.net.URL;
4 4
import java.util.Arrays;
5 5
import java.util.Iterator;
6 6
import java.util.Optional;
7
+import java.util.concurrent.ExecutionException;
7 8
import java.util.concurrent.ScheduledExecutorService;
8 9
import java.util.concurrent.TimeUnit;
9 10
import java.util.logging.Logger;
... ...
@@ -16,12 +17,11 @@ import com.sap.sailing.server.gateway.interfaces.SailingServer;
16 17
import com.sap.sse.common.Duration;
17 18
import com.sap.sse.common.Named;
18 19
import com.sap.sse.common.TimePoint;
20
+import com.sap.sse.common.Util;
19 21
import com.sap.sse.common.impl.NamedImpl;
20 22
import com.sap.sse.common.mail.MailException;
21 23
import com.sap.sse.landscape.Landscape;
22
-import com.sap.sse.landscape.RotatingFileBasedLog;
23 24
import com.sap.sse.landscape.aws.AwsApplicationReplicaSet;
24
-import com.sap.sse.landscape.aws.ReverseProxy;
25 25
import com.sap.sse.security.shared.impl.User;
26 26
27 27
/**
... ...
@@ -113,9 +113,6 @@ public class ArchiveCandidateMonitoringBackgroundTask implements Runnable {
113 113
private final String candidateHostname;
114 114
private final LandscapeService landscapeService;
115 115
private final AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet;
116
- private final ReverseProxy<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>, RotatingFileBasedLog> reverseProxyCluster;
117
- private final String optionalKeyName;
118
- private final byte[] privateKeyEncryptionPassphrase;
119 116
private final ScheduledExecutorService executor;
120 117
121 118
/**
... ...
@@ -133,16 +130,12 @@ public class ArchiveCandidateMonitoringBackgroundTask implements Runnable {
133 130
public ArchiveCandidateMonitoringBackgroundTask(User currentUser, LandscapeService landscapeService,
134 131
AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet,
135 132
String candidateHostname,
136
- ReverseProxy<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>, RotatingFileBasedLog> reverseProxyCluster,
137
- String optionalKeyName,
138
- byte[] privateKeyEncryptionPassphrase, ScheduledExecutorService executor, String effectiveBearerToken) {
133
+ ScheduledExecutorService executor,
134
+ String effectiveBearerToken) {
139 135
this.currentUser = currentUser;
140 136
this.landscapeService = landscapeService;
141 137
this.replicaSet = replicaSet;
142 138
this.candidateHostname = candidateHostname;
143
- this.reverseProxyCluster = reverseProxyCluster;
144
- this.optionalKeyName = optionalKeyName;
145
- this.privateKeyEncryptionPassphrase = privateKeyEncryptionPassphrase;
146 139
this.executor = executor;
147 140
this.effectiveBearerToken = effectiveBearerToken;
148 141
this.checks = Arrays.asList(
... ...
@@ -169,7 +162,7 @@ public class ArchiveCandidateMonitoringBackgroundTask implements Runnable {
169 162
} else {
170 163
// all checks passed; candidate is ready for production; nothing more to do here
171 164
logger.info("Done with all checks; candidate is ready for production.");
172
- notifyProcessOwnerCandidateIsReadyForProduction(); // this ends the re-scheduling loop
165
+ notifyProcessOwnerCandidateIsReadyForSpotChecksAndRotation(); // this ends the re-scheduling loop
173 166
}
174 167
} else {
175 168
rescheduleCurrentCheckAfterFailureOrTimeout();
... ...
@@ -281,7 +274,10 @@ public class ArchiveCandidateMonitoringBackgroundTask implements Runnable {
281 274
"Candidate server does not match production server according to REST API comparison."
282 275
+ "\nDifferences on candidate side: " + comparisonResult.getADiffs()
283 276
+ "\nDifferences on production side: " + comparisonResult.getBDiffs()
284
- + "\nNot proceeding further. You need to resolve the issues manually."); // TODO add link to running REST API comparison in browser
277
+ + "\nNot proceeding further. You need to resolve the issues manually."
278
+ + "\nCheck https://"+candidateHostname+"/sailingserver/v1/compareservers?server2="+replicaSet.getHostname()
279
+ + "\nafter you have tried to resolve the differences."
280
+ + "\nThen, run your smoke checks and trigger the rotation if everything looks good.");
285 281
}
286 282
return !comparisonResult.hasDiffs();
287 283
}
... ...
@@ -293,12 +289,9 @@ public class ArchiveCandidateMonitoringBackgroundTask implements Runnable {
293 289
currentCheck.getLastFailureMessage());
294 290
}
295 291
296
- private void notifyProcessOwnerCandidateIsReadyForProduction() throws MailException {
297
- // TODO send a mail to the process owner that the candidate is ready for production, comparisons were OK, remaining is an optional spot-checke (human in the loop). Include links for spot-checking and triggering the rotation
298
- }
299
-
300
- private void sendMailAboutNewArchiveCandidate() throws MailException {
301
- landscapeService.sendMailToUser(currentUser, "StartingNewArchiveCandidateSubject", "StartingNewArchiveCandidateBody", replicaSet.getServerName());
302
- landscapeService.sendMailToReplicaSetOwner(replicaSet, "RefrainFromArchivingSubject", "RefrainFromArchivingBody", Optional.empty());
292
+ private void notifyProcessOwnerCandidateIsReadyForSpotChecksAndRotation() throws MailException, InterruptedException, ExecutionException {
293
+ landscapeService.sendMailToUser(currentUser, "NewArchiveCandidateReadyForSpotChecksAndRotationSubject",
294
+ "NewArchiveCandidateReadyForSpotChecksAndRotationBody", replicaSet.getName(), candidateHostname,
295
+ replicaSet.getHostname(), Util.joinStrings("\n", Util.map(checks, Check::getName)));
303 296
}
304 297
}
java/com.sap.sailing.landscape/src/com/sap/sailing/landscape/impl/LandscapeServiceImpl.java
... ...
@@ -84,6 +84,7 @@ import com.sap.sse.landscape.aws.AwsLandscape;
84 84
import com.sap.sse.landscape.aws.AwsShard;
85 85
import com.sap.sse.landscape.aws.HostSupplier;
86 86
import com.sap.sse.landscape.aws.ReverseProxy;
87
+import com.sap.sse.landscape.aws.ReverseProxyCluster;
87 88
import com.sap.sse.landscape.aws.Tags;
88 89
import com.sap.sse.landscape.aws.TargetGroup;
89 90
import com.sap.sse.landscape.aws.common.shared.RedirectDTO;
... ...
@@ -125,6 +126,7 @@ import software.amazon.awssdk.services.ec2.model.LaunchTemplate;
125 126
import software.amazon.awssdk.services.ec2.model.LaunchTemplateVersion;
126 127
import software.amazon.awssdk.services.elasticloadbalancingv2.model.Listener;
127 128
import software.amazon.awssdk.services.elasticloadbalancingv2.model.Rule;
129
+import software.amazon.awssdk.services.elasticloadbalancingv2.model.TagDescription;
128 130
import software.amazon.awssdk.services.elasticloadbalancingv2.model.TargetHealthDescription;
129 131
import software.amazon.awssdk.services.route53.model.RRType;
130 132
import software.amazon.awssdk.services.route53.model.ResourceRecordSet;
... ...
@@ -237,7 +239,7 @@ public class LandscapeServiceImpl implements LandscapeService {
237 239
}
238 240
239 241
@Override
240
- public AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> createArchiveReplicaSet(
242
+ public void createArchiveReplicaSet(
241 243
String regionId, String replicaSetName, String instanceType, String releaseNameOrNullForLatestMaster, Database databaseConfiguration,
242 244
String optionalKeyName, byte[] privateKeyEncryptionPassphrase, String securityServiceReplicationBearerToken, String replicaReplicationBearerToken,
243 245
String optionalDomainName, Integer optionalMemoryInMegabytesOrNull,
... ...
@@ -259,8 +261,11 @@ public class LandscapeServiceImpl implements LandscapeService {
259 261
final InboundReplicationConfiguration inboundMasterReplicationConfiguration = masterConfigurationBuilder.getInboundReplicationConfiguration().get();
260 262
establishServerAndServerGroupAndTryToMakeCurrentUserItsOwnerAndMember(replicaSetName, bearerTokenUsedByReplicas,
261 263
inboundMasterReplicationConfiguration.getMasterHostname(), inboundMasterReplicationConfiguration.getMasterHttpPort());
264
+ final ReverseProxyCluster<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>, RotatingFileBasedLog> reverseProxyCluster =
265
+ getLandscape().getCentralReverseProxy(region);
262 266
final com.sap.sailing.landscape.procedures.StartSailingAnalyticsMasterHost.Builder<?, String> masterHostBuilder = StartSailingAnalyticsMasterHost.masterHostBuilder(masterConfigurationBuilder);
263
- 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)
267
+ masterHostBuilder
268
+ .setAvailabilityZone(getBestAvailabilityZoneForArchiveCandidate(region, landscape, reverseProxyCluster))
264 269
.setInstanceName(SharedLandscapeConstants.ARCHIVE_SERVER_NEW_CANDIDATE_INSTANCE_NAME)
265 270
.setInstanceType(InstanceType.valueOf(instanceType))
266 271
.setOptionalTimeout(Landscape.WAIT_FOR_HOST_TIMEOUT)
... ...
@@ -273,23 +278,48 @@ public class LandscapeServiceImpl implements LandscapeService {
273 278
final StartSailingAnalyticsMasterHost<String> masterHostStartProcedure = masterHostBuilder.build();
274 279
masterHostStartProcedure.run();
275 280
final SailingAnalyticsProcess<String> master = masterHostStartProcedure.getSailingAnalyticsProcess();
276
- logger.info("Waiting for archive new candidate "+master+" to get ready with new release "+release.getName());
277
- master.waitUntilReady(Optional.of(Duration.ONE_DAY.times(2))); // wait a little longer since archive candidate may need to load many races
278 281
final AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> replicaSet =
279
- landscape.getApplicationReplicaSet(region, replicaSetName, master, Collections.emptySet(),
282
+ landscape.getApplicationReplicaSet(region, replicaSetName, master, /* replicas */ Collections.emptySet(),
280 283
Landscape.WAIT_FOR_PROCESS_TIMEOUT, Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase);
281
- final ReverseProxy<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>, RotatingFileBasedLog> reverseProxyCluster =
282
- getLandscape().getCentralReverseProxy(region);
283 284
final String privateIpAdress = master.getHost().getPrivateAddress().getHostAddress();
284 285
logger.info("Adding reverse proxy rule for archive candidate with hostname "+ candidateHostname + " and private ip address " + privateIpAdress);
285 286
reverseProxyCluster.setPlainRedirect(candidateHostname, master, Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase);
286 287
sendMailAboutNewArchiveCandidate(replicaSet);
287 288
final ScheduledExecutorService monitorTaskExecutor = ThreadPoolUtil.INSTANCE.getDefaultBackgroundTaskThreadPoolExecutor();
288 289
final ArchiveCandidateMonitoringBackgroundTask monitoringTask = new ArchiveCandidateMonitoringBackgroundTask(
289
- getSecurityService().getCurrentUser(), this, replicaSet, candidateHostname, reverseProxyCluster, optionalKeyName,
290
- privateKeyEncryptionPassphrase, monitorTaskExecutor, bearerTokenUsedByReplicas);
290
+ getSecurityService().getCurrentUser(), this, replicaSet, candidateHostname, monitorTaskExecutor, bearerTokenUsedByReplicas);
291 291
monitorTaskExecutor.execute(monitoringTask);
292
- return replicaSet;
292
+ }
293
+
294
+ private AwsAvailabilityZone getBestAvailabilityZoneForArchiveCandidate(AwsRegion region, AwsLandscape<String> landscape,
295
+ ReverseProxyCluster<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>, RotatingFileBasedLog> reverseProxyCluster) {
296
+ for (final AwsInstance<String> reverseProxyHost : reverseProxyCluster.getHosts()) {
297
+ final AwsAvailabilityZone az = reverseProxyHost.getAvailabilityZone();
298
+ }
299
+ // 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)
300
+ return null;
301
+ }
302
+
303
+ @Override
304
+ public void makeCandidateArchiveServerGoLive(String regionId, String optionalKeyName, byte[] privateKeyEncryptionPassphrase, String optionalDomainName) throws Exception {
305
+ final AwsLandscape<String> landscape = getLandscape();
306
+ final AwsRegion region = new AwsRegion(regionId, landscape);
307
+ final String candidateHostname = getHostname(SharedLandscapeConstants.ARCHIVE_CANDIDATE_SUBDOMAIN, optionalDomainName);
308
+ final AwsApplicationReplicaSet<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>> archiveReplicaSet = getApplicationReplicaSet(
309
+ region, SharedLandscapeConstants.ARCHIVE_SERVER_APPLICATION_REPLICA_SET_NAME,
310
+ Landscape.WAIT_FOR_PROCESS_TIMEOUT.map(Duration::asMillis).orElse(null),
311
+ optionalKeyName, privateKeyEncryptionPassphrase);
312
+ if (archiveReplicaSet == null) {
313
+ throw new IllegalArgumentException("Couldn't find candidate replica set with name "+replicaSetName+" in region "+regionId);
314
+ }
315
+ final ReverseProxy<String, SailingAnalyticsMetrics, SailingAnalyticsProcess<String>, RotatingFileBasedLog> reverseProxyCluster =
316
+ getLandscape().getCentralReverseProxy(region);
317
+ final String candidateHostname = archiveReplicaSet.getHostname();
318
+ logger.info("Removing reverse proxy rule for archive candidate with hostname "+ candidateHostname);
319
+ reverseProxyCluster.removePlainRedirect(candidateHostname);
320
+ final String archiveHostname = getHostname(SharedLandscapeConstants.ARCHIVE_SUBDOMAIN, Optional.empty());
321
+ logger.info("Adding reverse proxy rule for new archive server with hostname "+ archiveHostname);
322
+ reverseProxyCluster.setPlainRedirect(archiveHostname, archiveReplicaSet.getMaster(), Optional.ofNullable(optionalKeyName), privateKeyEncryptionPassphrase);
293 323
}
294 324
295 325
@Override
java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompareServersResource.java
... ...
@@ -51,8 +51,8 @@ public class CompareServersResource extends AbstractSailingServerResource {
51 51
52 52
public static final Logger logger = Logger.getLogger(CompareServersResource.class.getName());
53 53
54
- private static final String LEADERBOARDGROUPSPATH = "/sailingserver/api/v1/leaderboardgroups";
55
- private static final String LEADERBOARDGROUPSIDENTIFIABLEPATH = LEADERBOARDGROUPSPATH+"/identifiable";
54
+ private static final String LEADERBOARDGROUPSPATH = "/sailingserver/api"+LeaderboardGroupsResource.V1_LEADERBOARDGROUPS;
55
+ private static final String LEADERBOARDGROUPSIDENTIFIABLEPATH = LEADERBOARDGROUPSPATH+LeaderboardGroupsResource.IDENTIFIABLE;
56 56
public static final String SERVER1_FORM_PARAM = "server1";
57 57
public static final String SERVER2_FORM_PARAM = "server2";
58 58
public static final String USER1_FORM_PARAM = "user1";
java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/dialog/DataEntryDialog.java
... ...
@@ -281,7 +281,7 @@ public abstract class DataEntryDialog<T> {
281 281
*
282 282
* @see #createSuggestBox(SuggestOracle)
283 283
*/
284
- protected SuggestBox createSuggestBox(Iterable<String> suggestValues) {
284
+ public SuggestBox createSuggestBox(Iterable<String> suggestValues) {
285 285
List<String> suggestValuesAsCollection = new ArrayList<>();
286 286
Util.addAll(suggestValues, suggestValuesAsCollection);
287 287
final MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
... ...
@@ -299,7 +299,7 @@ public abstract class DataEntryDialog<T> {
299 299
*
300 300
* @see SuggestBox#SuggestBox(SuggestOracle)
301 301
*/
302
- protected SuggestBox createSuggestBox(SuggestOracle suggestOracle) {
302
+ public SuggestBox createSuggestBox(SuggestOracle suggestOracle) {
303 303
final SuggestBox result = new SuggestBox(suggestOracle);
304 304
ensureHasValueIsValidated(result.getValueBox());
305 305
ensureChangeableIsValidated(result.getValueBox());