Merge branch 'master' into bug5978

This commit is contained in:
Thomas Stokes
2024-03-13 15:52:37 +01:00
36 changed files with 557 additions and 36 deletions
@@ -0,0 +1,25 @@
<VirtualHost *:80>
ServerName git.sapsailing.com
SetEnv GIT_PROJECT_ROOT /home/trac/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
ScriptAlias /hooks/ /var/www/cgi-bin/
<Location /git/ >
Options +ExecCGI
AuthType Basic
AuthName 'Git'
AuthUserFile '/etc/httpd/conf/passwd.git'
Require valid-user
</Location>
<Directory "/var/www/cgi-bin">
AllowOverride None
Options FollowSymLinks
Order allow,deny
Allow from all
</Directory>
SetEnvIf User-Agent ".*MSIE.*" \
downgrade-1.0 force-response-1.0
</VirtualHost>
@@ -0,0 +1,39 @@
<VirtualHost *:80>
ServerName docker.sapsailing.com
ProxyPreserveHost on
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
<Location />
Order deny,allow
Allow from all
AuthName "Docker Registry Authentication"
AuthType basic
AuthUserFile '/etc/httpd/conf/passwd.git'
Require valid-user
</Location>
# Use separate log files for the SSL virtual host; note that LogLevel
# is not inherited from httpd.conf.
ErrorLog logs/docker_error_log
TransferLog logs/docker_access_log
LogLevel warn
</VirtualHost>
<VirtualHost *:80>
ServerName docker-registry.sapsailing.com
ProxyPreserveHost on
ProxyPass /v2 http://127.0.0.1:5001/v2
ProxyPassReverse /v2 http://127.0.0.1:5001/v2
<Location />
Order deny,allow
Allow from all
AuthName "Docker Registry Authentication"
AuthType basic
AuthUserFile '/etc/httpd/conf/passwd.git'
Require valid-user
</Location>
# Use separate log files for the SSL virtual host; note that LogLevel
# is not inherited from httpd.conf.
ErrorLog logs/docker_error_log
TransferLog logs/docker_access_log
LogLevel warn
</VirtualHost>
@@ -0,0 +1,14 @@
# sail-insight.com
<VirtualHost *:80>
ServerName sail-insight.com
ServerAlias www.sail-insight.com
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
Alias / /home/trac/sail-insight-website/
<Directory /home/trac/sail-insight-website>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
@@ -0,0 +1,56 @@
#
# Content of this file, with correct values, can be automatically added to
# your Apache server by using the AWStats configure.pl tool.
#
# If using Windows and Perl ActiveStat, this is to enable Perl script as CGI.
#ScriptInterpreterSource registry
#
# Directives to add to your Apache conf file to allow use of AWStats as a CGI.
# Note that path "/usr/share/awstats/" must reflect your AWStats install path.
#
Alias /awstatsclasses "/usr/share/awstats/wwwroot/classes/"
Alias /awstatscss "/usr/share/awstats/wwwroot/css/"
Alias /awstatsicons "/usr/share/awstats/wwwroot/icon/"
ScriptAlias /awstats/ "/usr/share/awstats/wwwroot/cgi-bin/"
# Adding access to /var/log/old/cache/unique-ips-per-referrer/stats:
Alias /unique-visitors/ "/var/log/old/cache/unique-ips-per-referrer/stats/"
#
# This is to permit URL access to scripts/files in AWStats directory.
#
<VirtualHost *:80>
ServerName awstats.sapsailing.com
CustomLog logs/awstats_access_log combined
ErrorLog logs/awstats_error_log
<Directory "/usr/share/awstats/wwwroot">
Options None
# AllowOverride None
# Order allow,deny
# Allow from 127.0.0.1
AuthType Basic
AuthName 'awstats'
AuthUserFile /etc/httpd/conf/passwd.awstats
Require valid-user
</Directory>
<Directory "/var/log/old/cache/unique-ips-per-referrer/stats/">
Options Indexes
# AllowOverride None
# Order allow,deny
# Allow from 127.0.0.1
AuthType Basic
AuthName 'awstats'
AuthUserFile /etc/httpd/conf/passwd.awstats
Require valid-user
</Directory>
# Additional Perl modules
<IfModule mod_env.c>
SetEnv PERL5LIB /usr/share/awstats/lib:/usr/share/awstats/plugins:/root/perl5/lib/perl5
</IfModule>
</VirtualHost>
@@ -0,0 +1,78 @@
<VirtualHost *:80>
ServerName jobs.sapsailing.com
CustomLog logs/jobs_log combined env=!original_client_ip
CustomLog logs/jobs_log first_forwarded_for_ip env=original_client_ip
DocumentRoot /home/trac/static/jobs
<Directory /home/trac/static/jobs>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
</VirtualHost>
# P2 repository
<VirtualHost *:80>
ServerName p2.sapsailing.com
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
Alias /p2 /home/trac/p2-repositories
<Directory /home/trac/p2-repositories>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName bugzilla.sapsailing.com
RewriteEngine On
RewriteRule ^/?$ http://bugzilla.sapsailing.com/bugzilla [L]
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
Alias /bugzilla /usr/share/bugzilla
<Directory /usr/share/bugzilla>
AddHandler cgi-script .cgi
Options +Indexes +ExecCGI +FollowSymLinks
DirectoryIndex index.cgi
AllowOverride Limit Options FileInfo Indexes AuthConfig
</Directory>
# Additional Perl modules
<IfModule mod_env.c>
SetEnv PERL5LIB /root/perl5/lib/perl5:/root/perl5/lib/perl5/x86_64-linux-thread-multi
</IfModule>
</VirtualHost>
# Wiki -->
<VirtualHost *:80>
ServerName wiki.sapsailing.com
RewriteEngine on
RewriteRule ^/(.*) http://localhost:4567/$1 [P,L]
ProxyPassReverse / http://localhost:4567/
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
</VirtualHost>
<VirtualHost *:80>
ServerName releases.sapsailing.com
DocumentRoot /home/trac/releases
<Directory /home/trac/releases>
Options +Indexes +FollowSymLinks
</Directory>
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
</VirtualHost>
<VirtualHost *:80>
ServerName static.sapsailing.com
DocumentRoot /var/www/static
<Directory /var/www/static>
Order Deny,Allow
Allow from all
Options -Indexes +FollowSymLinks -ExecCGI
AllowOverride All
</Directory>
CustomLog logs/services_log combined env=!original_client_ip
CustomLog logs/services_log first_forwarded_for_ip env=original_client_ip
</VirtualHost>
@@ -0,0 +1 @@
LoadModule php7_module modules/libphp-7.1.so
@@ -0,0 +1,48 @@
#
# Mod_perl incorporates a Perl interpreter into the Apache web server,
# so that the Apache web server can directly execute Perl code.
# Mod_perl links the Perl runtime library into the Apache web server
# and provides an object-oriented Perl interface for Apache's C
# language API. The end result is a quicker CGI script turnaround
# process, since no external Perl interpreter has to be started.
#
# Uncomment this line to globally enable warnings, which will be
# written to the server's error log. Warnings should be enabled
# during the development process, but should be disabled on a
# production server as they affect performance.
#
#PerlSwitches -w
# Uncomment this line to enable taint checking globally. When Perl is
# running in taint mode various checks are performed to reduce the
# risk of insecure data being passed to a subshell or being used to
# modify the filesystem. Unfortunately many Perl modules are not
# taint-safe, so you should exercise care before enabling it on a
# production server.
#
#PerlSwitches -T
# This will allow execution of mod_perl to compile your scripts to
# subroutines which it will execute directly, avoiding the costly
# compile process for most requests.
#
#Alias /perl /var/www/perl
#<Directory /var/www/perl>
# SetHandler perl-script
# PerlResponseHandler ModPerl::Registry
# PerlOptions +ParseHeaders
# Options +ExecCGI
#</Directory>
# This will allow remote server configuration reports, with the URL of
# http://servername/perl-status
# Change the ".example.com" to match your domain to enable.
#
#<Location /perl-status>
# SetHandler perl-script
# PerlResponseHandler Apache2::Status
# Order deny,allow
# Deny from all
# Allow from .example.com
#</Location>
@@ -0,0 +1,57 @@
#
# The following lines prevent .user.ini files from being viewed by Web clients.
#
<Files ".user.ini">
Require all denied
</Files>
#
# Allow php to handle Multiviews
#
AddType text/html .php
#
# Add index.php to the list of files that will be served as directory
# indexes.
#
DirectoryIndex index.php
# mod_php options
<IfModule mod_php7.c>
#
# Cause the PHP interpreter to handle files with a .php extension.
#
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
#
# Uncomment the following lines to allow PHP to pretty-print .phps
# files as PHP source code:
#
#<FilesMatch \.phps$>
# SetHandler application/x-httpd-php-source
#</FilesMatch>
#
# Apache specific PHP configuration options
# those can be override in each configured vhost
#
php_value session.save_handler "files"
php_value session.save_path "/var/lib/php/7.1/session"
php_value soap.wsdl_cache_dir "/var/lib/php/7.1/wsdlcache"
#php_value opcache.file_cache "/var/lib/php/7.1/opcache"
</IfModule>
# Redirect to local php-fpm if mod_php is not available
<IfModule !mod_php5.c>
<IfModule !mod_php7.c>
# Enable http authorization headers
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"
</FilesMatch>
</IfModule>
</IfModule>
@@ -0,0 +1,57 @@
#
# The following lines prevent .user.ini files from being viewed by Web clients.
#
<Files ".user.ini">
Require all denied
</Files>
#
# Allow php to handle Multiviews
#
AddType text/html .php
#
# Add index.php to the list of files that will be served as directory
# indexes.
#
DirectoryIndex index.php
# mod_php options
<IfModule mod_php7.c>
#
# Cause the PHP interpreter to handle files with a .php extension.
#
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
#
# Uncomment the following lines to allow PHP to pretty-print .phps
# files as PHP source code:
#
#<FilesMatch \.phps$>
# SetHandler application/x-httpd-php-source
#</FilesMatch>
#
# Apache specific PHP configuration options
# those can be override in each configured vhost
#
php_value session.save_handler "files"
php_value session.save_path "/var/lib/php/7.1/session"
php_value soap.wsdl_cache_dir "/var/lib/php/7.1/wsdlcache"
#php_value opcache.file_cache "/var/lib/php/7.1/opcache"
</IfModule>
# Redirect to local php-fpm if mod_php is not available
<IfModule !mod_php5.c>
<IfModule !mod_php7.c>
# Enable http authorization headers
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"
</FilesMatch>
</IfModule>
</IfModule>
@@ -14,4 +14,7 @@ if ! git status; then
GIT_SSH_COMMAND="ssh -A -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" git fetch
git checkout main
fi
echo "Use Status ${SELF_IP} internal-server-status" > /etc/httpd/conf.d/${STATUS_DEFINITION_FILE}
echo "Use Status ${SELF_IP} internal-server-status" > /etc/httpd/conf.d/${STATUS_DEFINITION_FILE}
cd /etc/httpd
git config user.name "Disposable Reverse Proxy"
git config user.email "$(hostname)"
@@ -17,7 +17,8 @@ if [[ "$#" -eq 0 ]];then
fi
addSelfToNLB() {
if ! ec2-metadata --user-data | grep "^image-upgrade$" ; then
user_data=$(ec2-metadata --user-data | sed -e 's/^user-data: //')
if ! echo "$user_data" | grep "^image-upgrade$" && ! echo "$user_data" | grep "^no-startup-automation$" ; then
ec2-metadata --local-ipv4 | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\>" > /var/cache/local-ip
ec2-metadata --availability-zone | grep -o "[a-zA-Z]\+-[a-zA-Z]\+-[0-9a-z]\+\>" > /var/cache/availability-zone
aws elbv2 register-targets --target-group-arn "${targetGroupArn}" --targets Id="${selfIp}",Port=80,AvailabilityZone="${availabilityZone}"
+1 -1
View File
@@ -1,4 +1,4 @@
FROM docker.sapsailing.com/sapjvm8:8.1.096
FROM docker.sapsailing.com/sapjvm8:8.1.097
ARG RELEASE
LABEL maintainer=axel.uhl@sap.com
# Download and extract the release
+1 -1
View File
@@ -1,5 +1,5 @@
FROM buildpack-deps:bullseye
ARG SAPJVM_VERSION=8.1.096
ARG SAPJVM_VERSION=8.1.097
LABEL maintainer=axel.uhl@sap.com
# Download and extract the SAP JVM 8
ENV PATH=${PATH}:/opt/sapjvm_8/bin
+1 -1
View File
@@ -1,4 +1,4 @@
ARG SAPJVM_VERSION=8.1.096
ARG SAPJVM_VERSION=8.1.097
FROM docker.sapsailing.com/sapjvm8:${SAPJVM_VERSION}
LABEL maintainer=axel.uhl@sap.com
# Download and extract the release
@@ -10,13 +10,17 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import com.mongodb.connection.ClusterDescription;
import com.mongodb.connection.ServerDescription;
import com.sap.sailing.server.interfaces.RacingEventService;
import com.sap.sse.ServerInfo;
import com.sap.sse.mongodb.MongoDBService;
import com.sap.sse.replication.ReplicationService;
import com.sap.sse.replication.ReplicationStatus;
@@ -62,6 +66,7 @@ public class StatusServlet extends HttpServlet {
result.put("numberofracesrestoreddoneloading", numberOfTrackedRacesRestoredDoneLoading);
final int numberOfTrackedRacesStillLoading = service.getNumberOfTrackedRacesStillLoading();
result.put("numberofracesstillloading", numberOfTrackedRacesStillLoading);
result.put("mongoDbConfiguration", getMongoDBReplicaSetNodes());
final ReplicationService replicationService = getReplicationService(servletContext);
final ReplicationStatus replicationStatus = replicationService == null ? null : replicationService.getStatus();
if (replicationStatus != null) {
@@ -82,4 +87,22 @@ public class StatusServlet extends HttpServlet {
throw new RuntimeException(e);
}
}
private JSONObject getMongoDBReplicaSetNodes() {
final JSONObject result = new JSONObject();
final ClusterDescription clusterDescription = MongoDBService.INSTANCE.getMongoClient().getClusterDescription();
result.put("connectionMode", clusterDescription.getConnectionMode().name());
result.put("replicaSet", clusterDescription.getClusterSettings().getRequiredReplicaSetName());
result.put("database", MongoDBService.INSTANCE.getMongoClientURI().getDatabase());
final JSONArray servers = new JSONArray();
for (final ServerDescription serverDescription : clusterDescription.getServerDescriptions()) {
final JSONObject serverHostAndPort = new JSONObject();
serverHostAndPort.put("host", serverDescription.getAddress().getHost());
serverHostAndPort.put("port", serverDescription.getAddress().getPort());
serverHostAndPort.put("type", serverDescription.getType().name());
servers.add(serverHostAndPort);
}
result.put("servers", servers);
return result;
}
}
@@ -24,7 +24,7 @@ public class ChangeAutoScalingReplicaInstanceTypeDialog extends DataEntryDialog<
super(stringMessages.moveMasterToOtherInstance(), /* message */ null, stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback);
this.stringMessages = stringMessages;
instanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter);
stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
}
@Override
@@ -193,10 +193,10 @@ public class CreateApplicationReplicaSetDialog extends AbstractApplicationReplic
dynamicLoadBalancerCheckBox = mayUseDynamicLoadBalancer ? createCheckbox(stringMessages.useDynamicLoadBalancer()) : null;
domainNameBox = createTextBox(SharedLandscapeConstants.DEFAULT_DOMAIN_NAME, 40);
dedicatedInstanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter);
stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
dedicatedInstanceTypeLabel = new Label();
sharedInstanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
stringMessages, SharedLandscapeConstants.DEFAULT_SHARED_INSTANCE_TYPE_NAME, errorReporter);
stringMessages, SharedLandscapeConstants.DEFAULT_SHARED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
sharedInstanceTypeLabel = new Label();
memoryInMegabytesBox = createIntegerBox(null, 7);
memoryTotalSizeFactorBox = createIntegerBox(null, 2);
@@ -128,7 +128,7 @@ public class CreateReverseProxyInClusterDialog
existingReverseProxies);
proxyName = createTextBox("", 20);
dedicatedInstanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
stringMessages, SharedLandscapeConstants.DEFAULT_REVERSE_PROXY_INSTANCE_TYPE, errorReporter);
stringMessages, SharedLandscapeConstants.DEFAULT_REVERSE_PROXY_INSTANCE_TYPE, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ true);
// setup labels
nameLabel = new Label(stringMessages.instanceName());
instanceTypeLabel = new Label(stringMessages.instanceType());
@@ -13,10 +13,10 @@ import com.sap.sse.gwt.client.dialog.DataEntryDialog;
public class LandscapeDialogUtil {
public static ListBox createInstanceTypeListBox(DataEntryDialog<?> dialog,
LandscapeManagementWriteServiceAsync landscapeManagementService, StringMessages stringMessages,
String defaultInstanceTypeName, ErrorReporter errorReporter) {
String defaultInstanceTypeName, ErrorReporter errorReporter, boolean canBeDeployedInNlbInstanceBasedTargetGroup) {
return createInstanceTypeListBoxWithAdditionalDefaultEntry(dialog, /* additionalItem */ null,
/* additionalValue */ null, landscapeManagementService, stringMessages, defaultInstanceTypeName,
errorReporter);
errorReporter, canBeDeployedInNlbInstanceBasedTargetGroup);
}
/**
@@ -24,17 +24,20 @@ public class LandscapeDialogUtil {
* if not {@code null}, an item with this name is created, and then {@code additionalValue} must not be
* {@code null} because it is then used as that item's value. The item will then be set as the one
* selected.
* @param canBeDeployedInNlbInstanceBasedTargetGroup A boolean indicating whether the instance list should filter out those
* which cannot be added to NLB, instance-based target groups. True indicates that it needs to be deployable
* to this type of target group, so the resulting listbox should not contain the banned instance types.
*/
public static ListBox createInstanceTypeListBoxWithAdditionalDefaultEntry(DataEntryDialog<?> dialog,
String additionalItem, String additionalValue,
LandscapeManagementWriteServiceAsync landscapeManagementService, StringMessages stringMessages,
String defaultInstanceTypeName, ErrorReporter errorReporter) {
String defaultInstanceTypeName, ErrorReporter errorReporter, boolean canBeDeployedInNlbInstanceBasedTargetGroup) {
final ListBox instanceTypeBox = dialog.createListBox(/* isMultipleSelect */false);
if (additionalItem != null) {
instanceTypeBox.addItem(additionalItem, additionalValue);
instanceTypeBox.setSelectedIndex(0);
}
landscapeManagementService.getInstanceTypeNames(new AsyncCallback<ArrayList<String>>() {
landscapeManagementService.getInstanceTypeNames(canBeDeployedInNlbInstanceBasedTargetGroup, new AsyncCallback<ArrayList<String>>() {
@Override
public void onFailure(Throwable caught) {
errorReporter.reportError(caught.getMessage());
@@ -26,7 +26,7 @@ import com.sap.sse.landscape.aws.common.shared.RedirectDTO;
public interface LandscapeManagementWriteService extends RemoteService {
ArrayList<String> getRegions();
ArrayList<String> getInstanceTypeNames();
ArrayList<String> getInstanceTypeNames(boolean canBeDeployedInNlbInstanceBasedTargetGroup);
ArrayList<MongoEndpointDTO> getMongoEndpoints(String region) throws Exception;
@@ -28,7 +28,12 @@ import com.sap.sse.landscape.aws.common.shared.RedirectDTO;
public interface LandscapeManagementWriteServiceAsync {
void getRegions(AsyncCallback<ArrayList<String>> callback);
void getInstanceTypeNames(AsyncCallback<ArrayList<String>> callback);
/**
* @param canBeDeployedInNlbInstanceBasedTargetGroup
* A boolean indicating, if true, that the list of available instance types should not contain those,
* which cannot be added to an instance-based Network Load Balancer.
*/
void getInstanceTypeNames(boolean canBeDeployedInNlbInstanceBasedTargetGroup, AsyncCallback<ArrayList<String>> callback);
void getMongoEndpoints(String regionId, AsyncCallback<ArrayList<MongoEndpointDTO>> callback);
@@ -106,7 +106,7 @@ public class MongoScalingDialog extends DataEntryDialog<MongoScalingInstructions
voteBox = createIntegerBox(0, /* visibleLength */ 2);
grid.setWidget(row++, 1, voteBox);
grid.setWidget(row, 0, new Label(stringMessages.instanceType()));
instanceTypeBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService, stringMessages, DEFAULT_INSTANCE_TYPE, errorReporter);
instanceTypeBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService, stringMessages, DEFAULT_INSTANCE_TYPE, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
grid.setWidget(row++, 1, instanceTypeBox);
launchPanel.add(grid);
panel.add(launchPanel);
@@ -38,7 +38,7 @@ public class MoveAllAwayFromHostDialog extends DataEntryDialog<String> {
stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback);
instanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBoxWithAdditionalDefaultEntry(this,
stringMessages.sameAsExistingHost(), SAME_AS_MASTER, landscapeManagementService, stringMessages, /* default */ stringMessages.sameAsExistingHost(),
errorReporter);
errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
instanceTypeLabel = new Label();
}
@@ -79,7 +79,7 @@ public class MoveMasterProcessDialog extends DataEntryDialog<MoveMasterProcessDi
super(stringMessages.moveMasterToOtherInstance(), /* message */ null, stringMessages.ok(), stringMessages.cancel(), /* validator */ null, callback);
this.stringMessages = stringMessages;
instanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBox(this, landscapeManagementService,
stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter);
stringMessages, SharedLandscapeConstants.DEFAULT_DEDICATED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
instanceTypeLabel = new Label();
masterReplicationBearerTokenBox = createTextBox("", 40);
replicaReplicationBearerTokenBox = createTextBox("", 40);
@@ -57,7 +57,7 @@ public class SwitchToReplicaOnSharedInstanceDialog extends DataEntryDialog<Switc
sharedInstanceTypeListBox = LandscapeDialogUtil.createInstanceTypeListBoxWithAdditionalDefaultEntry(this,
stringMessages.sameAsMaster(), DEFAULT_INSTANCE_TYPE,
landscapeManagementService,
stringMessages, SharedLandscapeConstants.DEFAULT_SHARED_INSTANCE_TYPE_NAME, errorReporter);
stringMessages, SharedLandscapeConstants.DEFAULT_SHARED_INSTANCE_TYPE_NAME, errorReporter, /* canBeDeployedInNlbInstanceBasedTargetGroup */ false);
replicaReplicationBearerTokenBox = createTextBox("", 40);
memoryInMegabytesBox = createIntegerBox(null, 7);
memoryTotalSizeFactorBox = createIntegerBox(SharedLandscapeConstants.DEFAULT_NUMBER_OF_PROCESSES_IN_MEMORY, 2);
@@ -208,11 +208,21 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
Util.addAll(Util.map(AwsLandscape.obtain(RemoteServiceMappingConstants.pathPrefixForShardingKey).getRegions(), r->r.getId()), result);
return result;
}
private static final Set<InstanceType> INSTANCE_TYPES_BANNED_FROM_INSTANCE_BASE_NLB_TARGET_GROUPS_AS_SET =
new HashSet<>(Arrays.asList(LandscapeConstants.INSTANCE_TYPES_BANNED_FROM_INSTANCE_BASED_NLB_TARGET_GROUPS));
@Override
public ArrayList<String> getInstanceTypeNames() {
public ArrayList<String> getInstanceTypeNames(boolean canBeDeployedInNlbInstanceBasedTargetGroup) {
final ArrayList<String> result = new ArrayList<>();
Util.addAll(Util.map(Arrays.asList(InstanceType.values()), instanceType->instanceType.name()), result);
Util.addAll(
Util.map(
// if deployment to NLB instance-based target group is to be possible, remove those
// instance types that are banned from those sorts of target groups
Util.filter(Arrays.asList(InstanceType.values()), instanceType->
!canBeDeployedInNlbInstanceBasedTargetGroup ||
!INSTANCE_TYPES_BANNED_FROM_INSTANCE_BASE_NLB_TARGET_GROUPS_AS_SET.contains(instanceType)),
instanceType->instanceType.name()), result);
return result;
}
@@ -241,8 +251,11 @@ public class LandscapeManagementWriteServiceImpl extends ResultCachingProxiedRem
@Override
public ArrayList<AvailabilityZoneDTO> describeAvailabilityZones(String region) {
final ArrayList<AvailabilityZoneDTO> availabilityZones = new ArrayList<>();
getLandscape().getAvailabilityZones(new AwsRegion(region, getLandscape()))
.forEach(az -> availabilityZones.add(new AvailabilityZoneDTO(az.getName(), region, az.getId())));
getLandscape()
.getAvailabilityZones(new AwsRegion(region, getLandscape()),
Optional.of(getLandscape().getDefaultSecurityGroupForApplicationLoadBalancer(
new AwsRegion(region, getLandscape())).getVpcId()))
.forEach(az -> availabilityZones.add(new AvailabilityZoneDTO(az.getName(), region, az.getId())));
return availabilityZones;
}
@@ -25,5 +25,4 @@ public interface SailingAnalyticsProcess<ShardingKey> extends AwsApplicationProc
*/
void refreshToRelease(Release release, Optional<String> optionalKeyName, byte[] privateKeyEncryptionPassphrase)
throws IOException, InterruptedException, JSchException, Exception;
}
@@ -31,12 +31,15 @@ import com.sap.sse.common.Duration;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.Util;
import com.sap.sse.landscape.Landscape;
import com.sap.sse.landscape.Region;
import com.sap.sse.landscape.Release;
import com.sap.sse.landscape.ReleaseRepository;
import com.sap.sse.landscape.aws.ApplicationProcessHost;
import com.sap.sse.landscape.aws.AwsLandscape;
import com.sap.sse.landscape.aws.MongoUriParser;
import com.sap.sse.landscape.aws.impl.AwsApplicationProcessImpl;
import com.sap.sse.landscape.impl.ReleaseImpl;
import com.sap.sse.landscape.mongodb.Database;
import com.sap.sse.shared.util.Wait;
import com.sap.sse.util.HttpUrlConnectionHelper;
import com.sap.sse.util.LaxRedirectStrategyForAllRedirectResponseCodes;
@@ -48,6 +51,7 @@ implements SailingAnalyticsProcess<ShardingKey> {
private static final String STATUS_SERVERNAME_PROPERTY_NAME = "servername";
private static final String STATUS_SERVERDIRECTORY_PROPERTY_NAME = "serverdirectory";
private static final String STATUS_RELEASE_PROPERTY_NAME = "release";
private static final String MONGODB_CONFIGURATION_PROPERTY_NAME = "mongoDbConfiguration";
private Integer expeditionUdpPort;
private Release release;
private TimePoint startTimePoint;
@@ -115,6 +119,13 @@ implements SailingAnalyticsProcess<ShardingKey> {
return release;
}
@Override
public Database getDatabaseConfiguration(Region region, Optional<Duration> optionalTimeout,
Optional<String> optionalKeyName, byte[] privateKeyEncryptionPassphrase) throws Exception {
final JSONObject mongoDBConfiguration = (JSONObject) getStatus(optionalTimeout).get(MONGODB_CONFIGURATION_PROPERTY_NAME);
return new MongoUriParser<ShardingKey>(getLandscape(), region).parseMongoDBConfigurationFromStatus(mongoDBConfiguration);
}
private void updateServerNameFromStatus(JSONObject status) {
serverName = status.get(STATUS_SERVERNAME_PROPERTY_NAME).toString();
}
@@ -1,5 +1,7 @@
package com.sap.sse.landscape.aws;
import software.amazon.awssdk.services.ec2.model.InstanceType;
public interface LandscapeConstants {
/**
* The key <strong>tag</strong>, indicating that an instance only acts as a reverse proxy
@@ -63,4 +65,11 @@ public interface LandscapeConstants {
* A tag key indicating that a subnet is not to be used for deploying instances, by autoscaling groups or by load balancers.
*/
String NO_INSTANCE_DEPLOYMENT = "noInstanceDeployment";
InstanceType[] INSTANCE_TYPES_BANNED_FROM_INSTANCE_BASED_NLB_TARGET_GROUPS = new InstanceType[] { InstanceType.CC1_4_XLARGE, InstanceType.C1_MEDIUM, InstanceType.C1_XLARGE,
InstanceType.CC2_8_XLARGE, InstanceType.CG1_4_XLARGE, InstanceType.CR1_8_XLARGE, InstanceType.G2_2_XLARGE,
InstanceType.G2_8_XLARGE, InstanceType.HI1_4_XLARGE, InstanceType.HS1_8_XLARGE, InstanceType.M1_LARGE,
InstanceType.M1_MEDIUM, InstanceType.M1_SMALL, InstanceType.M1_XLARGE, InstanceType.M2_2_XLARGE,
InstanceType.M2_4_XLARGE, InstanceType.M2_XLARGE, InstanceType.M3_2_XLARGE, InstanceType.M3_LARGE,
InstanceType.M3_MEDIUM, InstanceType.M3_XLARGE, InstanceType.T1_MICRO};
}
@@ -4,6 +4,11 @@ import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import com.sap.sse.common.Util;
import com.sap.sse.common.Util.Pair;
@@ -25,7 +30,7 @@ import com.sap.sse.landscape.mongodb.impl.MongoReplicaSetImpl;
* by the <tt>{value}</tt> of the {@code "replicaSet"} parameter; otherwise the result is a {@link MongoProcess}.
*/
public class MongoUriParser<ShardingKey> {
private final String SCHEME = "mongodb";
private final static String SCHEME = "mongodb";
private final AwsLandscape<ShardingKey> landscape;
private final Region region;
@@ -70,10 +75,42 @@ public class MongoUriParser<ShardingKey> {
}
return endpoint == null ? null : endpoint.getDatabase(dbName);
}
public Database parseMongoDBConfigurationFromStatus(JSONObject mongoDBConfigurationJSON) throws UnknownHostException {
final String databaseName = mongoDBConfigurationJSON.get("database").toString();
final String replicaSetName = mongoDBConfigurationJSON.get("replicaSet").toString();
final MongoEndpoint endpoint;
final List<Pair<AwsInstance<ShardingKey>, Integer>> hostnamesAndPorts = new ArrayList<>();
final JSONArray serversJSON = (JSONArray) mongoDBConfigurationJSON.get("servers");
for (final Object serverObject : serversJSON) {
final JSONObject serverJSON = (JSONObject) serverObject;
final String hostname = serverJSON.get("host").toString();
final int port = ((Number) serverJSON.get("port")).intValue();
hostnamesAndPorts.add(getHostAndPort(hostname, port));
}
if (replicaSetName != null) {
MongoReplicaSet replicaSet = new MongoReplicaSetImpl(replicaSetName);
for (final Pair<AwsInstance<ShardingKey>, Integer> hostnameAndPort : hostnamesAndPorts) {
final MongoProcessInReplicaSet mongoProcessInReplicaSet = getMongoProcessInReplicaSet(replicaSet, hostnameAndPort);
if (mongoProcessInReplicaSet != null) {
replicaSet.addReplica(mongoProcessInReplicaSet);
}
}
endpoint = replicaSet;
} else {
endpoint = getMongoProcess(hostnamesAndPorts.get(0));
}
return endpoint == null ? null : endpoint.getDatabase(databaseName);
}
private MongoEndpoint getMongoProcess(final String hostnameAndOptionalPort) throws UnknownHostException {
final MongoEndpoint endpoint;
Pair<AwsInstance<ShardingKey>, Integer> hostAndOptionalPort = getHostAndPort(hostnameAndOptionalPort);
return getMongoProcess(hostAndOptionalPort);
}
private MongoEndpoint getMongoProcess(Pair<AwsInstance<ShardingKey>, Integer> hostAndOptionalPort) {
final MongoEndpoint endpoint;
if (hostAndOptionalPort.getA() != null) {
if (hostAndOptionalPort.getB() != null) {
endpoint = new MongoProcessImpl(hostAndOptionalPort.getA(), hostAndOptionalPort.getB());
@@ -87,8 +124,12 @@ public class MongoUriParser<ShardingKey> {
}
private MongoProcessInReplicaSet getMongoProcessInReplicaSet(final MongoReplicaSet replicaSet, final String hostnameAndOptionalPort) throws UnknownHostException {
final MongoProcessInReplicaSet endpoint;
Pair<AwsInstance<ShardingKey>, Integer> hostAndOptionalPort = getHostAndPort(hostnameAndOptionalPort);
return getMongoProcessInReplicaSet(replicaSet, hostAndOptionalPort);
}
private MongoProcessInReplicaSet getMongoProcessInReplicaSet(final MongoReplicaSet replicaSet, Pair<AwsInstance<ShardingKey>, Integer> hostAndOptionalPort) {
final MongoProcessInReplicaSet endpoint;
if (hostAndOptionalPort.getA() != null) {
if (hostAndOptionalPort.getB() != null) {
endpoint = new MongoProcessInReplicaSetImpl(replicaSet, hostAndOptionalPort.getB(), hostAndOptionalPort.getA());
@@ -106,8 +147,17 @@ public class MongoUriParser<ShardingKey> {
*/
private Pair<AwsInstance<ShardingKey>, Integer> getHostAndPort(String hostnameAndOptionalPort) throws UnknownHostException {
final String[] hostnameAndOptionalPortSplit = hostnameAndOptionalPort.split(":");
final InetAddress address = InetAddress.getByName(hostnameAndOptionalPortSplit[0]);
final String hostname = hostnameAndOptionalPortSplit[0];
final Integer port = hostnameAndOptionalPortSplit.length<2?null:Integer.valueOf(hostnameAndOptionalPortSplit[1]);
return getHostAndPort(hostname, port);
}
/**
* If the host isn't found in the landscape, the {@link Pair#getA()} component of the pair returned will be {@code null}.
*/
private Pair<AwsInstance<ShardingKey>, Integer> getHostAndPort(String hostname, Integer optionalPort) throws UnknownHostException {
final InetAddress address = InetAddress.getByName(hostname);
final AwsInstance<ShardingKey> hostByPrivateIp = landscape.getHostByPrivateIpAddress(region, address.getHostAddress(), AwsInstanceImpl::new);
return new Pair<>(hostByPrivateIp, hostnameAndOptionalPortSplit.length<2?null:Integer.valueOf(hostnameAndOptionalPortSplit[1]));
return new Pair<>(hostByPrivateIp, optionalPort);
}
}
@@ -50,6 +50,10 @@ implements AwsApplicationProcess<ShardingKey, MetricsT, ProcessT> {
this.landscape = landscape;
}
protected AwsLandscape<ShardingKey> getLandscape() {
return landscape;
}
@Override
public AwsInstance<ShardingKey> getHost() {
@SuppressWarnings("unchecked")
@@ -32,3 +32,4 @@ Require-Bundle: com.sap.sse.common,
org.mongodb.driver-core;bundle-version="4.3.1",
org.mongodb.driver-sync;bundle-version="4.3.1"
Bundle-ActivationPolicy: lazy
Import-Package: com.sap.sse.mongodb
@@ -16,7 +16,7 @@ public interface Landscape<ShardingKey> {
/**
* The timeout for a host to come up
*/
Optional<Duration> WAIT_FOR_HOST_TIMEOUT = Optional.of(Duration.ONE_MINUTE.times(30));
Optional<Duration> WAIT_FOR_HOST_TIMEOUT = Optional.of(Duration.ONE_HOUR.times(2));
/**
* The timeout for a running process to respond
*/
@@ -11,7 +11,6 @@ import org.bson.Document;
import com.mongodb.ClientSessionOptions;
import com.mongodb.ConnectionString;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.connection.ClusterConnectionMode;
@@ -20,6 +19,7 @@ import com.sap.sse.common.Duration;
import com.sap.sse.common.Util;
import com.sap.sse.landscape.mongodb.Database;
import com.sap.sse.landscape.mongodb.MongoEndpoint;
import com.sap.sse.mongodb.MongoDBService;
public abstract class MongoEndpointImpl implements MongoEndpoint {
private static final Logger logger = Logger.getLogger(MongoEndpointImpl.class.getName());
@@ -86,12 +86,12 @@ public abstract class MongoEndpointImpl implements MongoEndpoint {
@Override
public MongoClient getClient() throws URISyntaxException {
return MongoClients.create(getConnectionString(Optional.empty()));
return MongoDBService.INSTANCE.getMongo(getConnectionString(Optional.empty()));
}
@Override
public MongoClient getClient(Optional<Duration> timeoutEmptyMeaningForever) throws URISyntaxException {
return MongoClients.create(getConnectionString(Optional.empty(), timeoutEmptyMeaningForever));
return MongoDBService.INSTANCE.getMongo(getConnectionString(Optional.empty(), timeoutEmptyMeaningForever));
}
@Override
@@ -2,6 +2,7 @@ package com.sap.sse.mongodb;
import java.lang.ref.WeakReference;
import com.mongodb.ConnectionString;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoDatabase;
@@ -51,4 +52,10 @@ public interface MongoDBService {
ClientSession startAutoRefreshingSession();
ClientSession startCausallyConsistentSession();
MongoClient getMongoClient();
ConnectionString getMongoClientURI();
MongoClient getMongo(ConnectionString mongoConnectionString);
}
@@ -137,11 +137,28 @@ public class MongoDBServiceImpl implements MongoDBService {
}
private MongoClient getMongo(MongoDBConfiguration mongoDBConfiguration) {
MongoClient mongo = mongos.computeIfAbsent(mongoDBConfiguration.getMongoClientURI(),
k-> MongoClients.create(mongoDBConfiguration.getMongoClientURI()));
return getMongo(mongoDBConfiguration.getMongoClientURI());
}
@Override
public MongoClient getMongo(ConnectionString mongoConnectionString) {
MongoClient mongo = mongos.computeIfAbsent(mongoConnectionString,
k-> MongoClients.create(mongoConnectionString));
return mongo;
}
@Override
public ConnectionString getMongoClientURI() {
ensureConfigurationDefaultingToTest();
return configuration.getMongoClientURI();
}
@Override
public MongoClient getMongoClient() {
ensureConfigurationDefaultingToTest();
return getMongo(getConfiguration());
}
@Override
public void registerExclusively(Class<?> registerForInterface, String collectionName)
throws AlreadyRegisteredException {