0a1a52120a867b15c70baccca5942d0a0ad58df9
java/com.sap.sailing.landscape.common/META-INF/MANIFEST.MF
| ... | ... | @@ -11,3 +11,4 @@ Require-Bundle: com.sap.sse.security.common, |
| 11 | 11 | com.sap.sse.landscape.aws.common |
| 12 | 12 | Bundle-ActivationPolicy: lazy |
| 13 | 13 | Export-Package: com.sap.sailing.landscape.common |
| 14 | +Import-Package: software.amazon.awssdk.regions |
java/com.sap.sailing.landscape.common/src/com/sap/sailing/landscape/common/SharedLandscapeConstants.java
| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | package com.sap.sailing.landscape.common; |
| 2 | 2 | |
| 3 | +import software.amazon.awssdk.regions.Region; |
|
| 4 | + |
|
| 3 | 5 | public interface SharedLandscapeConstants { |
| 4 | 6 | /** |
| 5 | 7 | * If no specific domain name is provided, e.g., when creating a new application replica set, this will be |
| ... | ... | @@ -20,6 +22,15 @@ public interface SharedLandscapeConstants { |
| 20 | 22 | */ |
| 21 | 23 | String DEFAULT_SECURITY_SERVICE_REPLICA_SET_NAME = "security-service"; |
| 22 | 24 | |
| 25 | + String RABBIT_IN_DEFAULT_REGION_HOSTNAME = "rabbit.internal.sapsailing.com"; |
|
| 26 | + |
|
| 27 | + Region DEFAULT_REGION = Region.EU_WEST_1; |
|
| 28 | + |
|
| 29 | + /** |
|
| 30 | + * We maintain a DNS entry for "rabbit.internal.sapsailing.com" (see {@link #RABBIT_IN_DEFAULT_REGION_HOSTNAME}) in this region |
|
| 31 | + */ |
|
| 32 | + String REGION_WITH_RABBITMQ_DNS_HOSTNAME = DEFAULT_REGION.id(); |
|
| 33 | + |
|
| 23 | 34 | /** |
| 24 | 35 | * This is the region of the load balancer handling the default traffic for {@code *.sapsailing.com}. It is also |
| 25 | 36 | * called the "dynamic" load balancer because adding, removing or changing any hostname-based rule in its HTTPS |
| ... | ... | @@ -38,8 +49,14 @@ public interface SharedLandscapeConstants { |
| 38 | 49 | * for archived events. If such a state is reached, "dynamic" load balancing may potentially be used regardless |
| 39 | 50 | * the region. |
| 40 | 51 | */ |
| 41 | - String REGION_WITH_DEFAULT_LOAD_BALANCER = "eu-west-1"; |
|
| 42 | - |
|
| 52 | + String REGION_WITH_DEFAULT_LOAD_BALANCER = DEFAULT_REGION.id(); |
|
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * Tag name used to identify instances on which a RabbitMQ installation is running. The tag value is currently interpreted to |
|
| 56 | + * be the port number (usually 5672) on which the RabbitMQ endpoint can be reached. |
|
| 57 | + */ |
|
| 58 | + String RABBITMQ_TAG_NAME = "RabbitMQEndpoint"; |
|
| 59 | + |
|
| 43 | 60 | /** |
| 44 | 61 | * The tag value used to identify host images that can be launched in order to run one or more Sailing Analytics |
| 45 | 62 | * server processes on it. |
java/com.sap.sse.landscape.aws.test/src/com/sap/sse/landscape/aws/ConnectivityTest.java
| ... | ... | @@ -51,6 +51,7 @@ import com.sap.sse.landscape.aws.orchestration.CreateDNSBasedLoadBalancerMapping |
| 51 | 51 | import com.sap.sse.landscape.impl.ReleaseRepositoryImpl; |
| 52 | 52 | import com.sap.sse.landscape.mongodb.MongoEndpoint; |
| 53 | 53 | import com.sap.sse.landscape.mongodb.impl.DatabaseImpl; |
| 54 | +import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint; |
|
| 54 | 55 | import com.sap.sse.landscape.ssh.SSHKeyPair; |
| 55 | 56 | import com.sap.sse.landscape.ssh.SshCommandChannel; |
| 56 | 57 | |
| ... | ... | @@ -535,4 +536,18 @@ public class ConnectivityTest<ProcessT extends AwsApplicationProcess<String, Sai |
| 535 | 536 | assertEquals(200, healthCheckConnection.getResponseCode()); |
| 536 | 537 | healthCheckConnection.disconnect(); |
| 537 | 538 | } |
| 539 | + |
|
| 540 | + @Test |
|
| 541 | + public void getDefaultRabbitConfigForEuWest1() { |
|
| 542 | + final RabbitMQEndpoint rabbitConfig = landscape.getDefaultRabbitConfiguration(new AwsRegion(Region.EU_WEST_1, landscape)); |
|
| 543 | + assertEquals("rabbit.internal.sapsailing.com", rabbitConfig.getNodeName()); |
|
| 544 | + assertEquals(5672, rabbitConfig.getPort()); |
|
| 545 | + } |
|
| 546 | + |
|
| 547 | + @Test |
|
| 548 | + public void getDefaultRabbitConfigForEuWest2() { |
|
| 549 | + final RabbitMQEndpoint rabbitConfig = landscape.getDefaultRabbitConfiguration(new AwsRegion(Region.EU_WEST_2, landscape)); |
|
| 550 | + assertTrue(rabbitConfig.getNodeName().startsWith("172.31.")); |
|
| 551 | + assertEquals(5672, rabbitConfig.getPort()); |
|
| 552 | + } |
|
| 538 | 553 | } |
java/com.sap.sse.landscape.aws/META-INF/MANIFEST.MF
| ... | ... | @@ -26,7 +26,8 @@ Require-Bundle: com.amazon.aws.aws-java-api;bundle-version="2.13.50", |
| 26 | 26 | com.sap.sse.replication.interfaces, |
| 27 | 27 | com.sap.sse.operationaltransformation, |
| 28 | 28 | org.mongodb.driver-core;bundle-version="4.3.1", |
| 29 | - org.mongodb.driver-sync;bundle-version="4.3.1" |
|
| 29 | + org.mongodb.driver-sync;bundle-version="4.3.1", |
|
| 30 | + com.sap.sailing.landscape.common |
|
| 30 | 31 | Web-ContextPath: /landscape |
| 31 | 32 | Import-Package: org.apache.shiro;version="1.2.2", |
| 32 | 33 | org.osgi.framework;version="1.8.0", |
java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/AwsLandscape.java
| ... | ... | @@ -34,7 +34,6 @@ import com.sap.sse.landscape.mongodb.MongoProcess; |
| 34 | 34 | import com.sap.sse.landscape.mongodb.MongoProcessInReplicaSet; |
| 35 | 35 | import com.sap.sse.landscape.mongodb.MongoReplicaSet; |
| 36 | 36 | import com.sap.sse.landscape.mongodb.impl.MongoProcessImpl; |
| 37 | -import com.sap.sse.landscape.rabbitmq.RabbitMQEndpoint; |
|
| 38 | 37 | import com.sap.sse.landscape.ssh.SSHKeyPair; |
| 39 | 38 | |
| 40 | 39 | import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; |
| ... | ... | @@ -129,12 +128,6 @@ public interface AwsLandscape<ShardingKey> extends Landscape<ShardingKey> { |
| 129 | 128 | |
| 130 | 129 | String MONGO_REPLICA_SET_NAME_AND_PORT_SEPARATOR = ":"; |
| 131 | 130 | |
| 132 | - /** |
|
| 133 | - * Tag name used to identify instances on which a RabbitMQ installation is running. The tag value is currently interpreted to |
|
| 134 | - * be the port number (usually 5672) on which the RabbitMQ endpoint can be reached. |
|
| 135 | - */ |
|
| 136 | - String RABBITMQ_TAG_NAME = "RabbitMQEndpoint"; |
|
| 137 | - |
|
| 138 | 131 | String CENTRAL_REVERSE_PROXY_TAG_NAME = "CentralReverseProxy"; |
| 139 | 132 | |
| 140 | 133 | /** |
| ... | ... | @@ -677,13 +670,6 @@ public interface AwsLandscape<ShardingKey> extends Landscape<ShardingKey> { |
| 677 | 670 | |
| 678 | 671 | Iterable<MongoEndpoint> getMongoEndpoints(Region region); |
| 679 | 672 | |
| 680 | - /** |
|
| 681 | - * Gets a default RabbitMQ configuration for the {@code region} specified.<p> |
|
| 682 | - * |
|
| 683 | - * TODO For now, the method searches for accordingly-tagged instances and picks the first one it finds. We need to extend this to RabbitMQ replication. |
|
| 684 | - */ |
|
| 685 | - RabbitMQEndpoint getDefaultRabbitConfiguration(AwsRegion region); |
|
| 686 | - |
|
| 687 | 673 | Database getDatabase(Region region, String databaseName); |
| 688 | 674 | |
| 689 | 675 | /** |
java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/AwsLandscapeImpl.java
| ... | ... | @@ -35,6 +35,7 @@ import java.util.regex.Pattern; |
| 35 | 35 | import com.jcraft.jsch.JSch; |
| 36 | 36 | import com.jcraft.jsch.JSchException; |
| 37 | 37 | import com.jcraft.jsch.KeyPair; |
| 38 | +import com.sap.sailing.landscape.common.SharedLandscapeConstants; |
|
| 38 | 39 | import com.sap.sse.common.Duration; |
| 39 | 40 | import com.sap.sse.common.TimePoint; |
| 40 | 41 | import com.sap.sse.common.Util; |
| ... | ... | @@ -1463,26 +1464,31 @@ public class AwsLandscapeImpl<ShardingKey> implements AwsLandscape<ShardingKey> |
| 1463 | 1464 | } |
| 1464 | 1465 | |
| 1465 | 1466 | @Override |
| 1466 | - public RabbitMQEndpoint getDefaultRabbitConfiguration(AwsRegion region) { |
|
| 1467 | + public RabbitMQEndpoint getDefaultRabbitConfiguration(com.sap.sse.landscape.Region region) { |
|
| 1467 | 1468 | final RabbitMQEndpoint result; |
| 1468 | - final Iterable<AwsInstance<ShardingKey>> rabbitMQHostsInRegion = getRunningHostsWithTag(region, RABBITMQ_TAG_NAME, AwsInstanceImpl::new); |
|
| 1469 | - if (rabbitMQHostsInRegion.iterator().hasNext()) { |
|
| 1470 | - final AwsInstance<ShardingKey> anyRabbitMQHost = rabbitMQHostsInRegion.iterator().next(); |
|
| 1471 | - result = new RabbitMQEndpoint() { |
|
| 1472 | - @Override |
|
| 1473 | - public int getPort() { |
|
| 1474 | - return getTag(anyRabbitMQHost, RABBITMQ_TAG_NAME) |
|
| 1475 | - .map(t -> t.trim().isEmpty() ? RabbitMQEndpoint.DEFAULT_PORT : Integer.valueOf(t.trim())) |
|
| 1476 | - .orElse(RabbitMQEndpoint.DEFAULT_PORT); |
|
| 1477 | - } |
|
| 1478 | - |
|
| 1479 | - @Override |
|
| 1480 | - public String getNodeName() { |
|
| 1481 | - return anyRabbitMQHost.getPrivateAddress().getHostAddress(); |
|
| 1482 | - } |
|
| 1483 | - }; |
|
| 1469 | + if (region.getId().equals(Region.EU_WEST_1.id())) { |
|
| 1470 | + result = ()->SharedLandscapeConstants.RABBIT_IN_DEFAULT_REGION_HOSTNAME; // using default port RabbitMQEndpoint.DEFAULT_PORT |
|
| 1484 | 1471 | } else { |
| 1485 | - result = null; |
|
| 1472 | + final Iterable<AwsInstance<ShardingKey>> rabbitMQHostsInRegion = getRunningHostsWithTag( |
|
| 1473 | + region, SharedLandscapeConstants.RABBITMQ_TAG_NAME, AwsInstanceImpl::new); |
|
| 1474 | + if (rabbitMQHostsInRegion.iterator().hasNext()) { |
|
| 1475 | + final AwsInstance<ShardingKey> anyRabbitMQHost = rabbitMQHostsInRegion.iterator().next(); |
|
| 1476 | + result = new RabbitMQEndpoint() { |
|
| 1477 | + @Override |
|
| 1478 | + public int getPort() { |
|
| 1479 | + return getTag(anyRabbitMQHost, SharedLandscapeConstants.RABBITMQ_TAG_NAME) |
|
| 1480 | + .map(t -> t.trim().isEmpty() ? RabbitMQEndpoint.DEFAULT_PORT : Integer.valueOf(t.trim())) |
|
| 1481 | + .orElse(RabbitMQEndpoint.DEFAULT_PORT); |
|
| 1482 | + } |
|
| 1483 | + |
|
| 1484 | + @Override |
|
| 1485 | + public String getNodeName() { |
|
| 1486 | + return anyRabbitMQHost.getPrivateAddress().getHostAddress(); |
|
| 1487 | + } |
|
| 1488 | + }; |
|
| 1489 | + } else { |
|
| 1490 | + result = null; |
|
| 1491 | + } |
|
| 1486 | 1492 | } |
| 1487 | 1493 | return result; |
| 1488 | 1494 | } |
| ... | ... | @@ -1493,17 +1499,6 @@ public class AwsLandscapeImpl<ShardingKey> implements AwsLandscape<ShardingKey> |
| 1493 | 1499 | } |
| 1494 | 1500 | |
| 1495 | 1501 | @Override |
| 1496 | - public RabbitMQEndpoint getMessagingConfigurationForDefaultCluster(com.sap.sse.landscape.Region region) { |
|
| 1497 | - final RabbitMQEndpoint result; |
|
| 1498 | - if (region.getId().equals(Region.EU_WEST_1.id())) { |
|
| 1499 | - result = ()->"rabbit.internal.sapsailing.com"; |
|
| 1500 | - } else { |
|
| 1501 | - result = null; |
|
| 1502 | - } |
|
| 1503 | - return result; |
|
| 1504 | - } |
|
| 1505 | - |
|
| 1506 | - @Override |
|
| 1507 | 1502 | public <MetricsT extends ApplicationProcessMetrics, ProcessT extends AwsApplicationProcess<ShardingKey, MetricsT, ProcessT>, |
| 1508 | 1503 | HostT extends ApplicationProcessHost<ShardingKey, MetricsT, ProcessT>> |
| 1509 | 1504 | Iterable<HostT> getApplicationProcessHostsByTag(com.sap.sse.landscape.Region region, String tagName, |
java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/orchestration/AwsApplicationConfiguration.java
| ... | ... | @@ -9,6 +9,7 @@ import com.sap.sse.landscape.DefaultProcessConfigurationVariables; |
| 9 | 9 | import com.sap.sse.landscape.InboundReplicationConfiguration; |
| 10 | 10 | import com.sap.sse.landscape.OutboundReplicationConfiguration; |
| 11 | 11 | import com.sap.sse.landscape.ProcessConfigurationVariable; |
| 12 | +import com.sap.sse.landscape.Region; |
|
| 12 | 13 | import com.sap.sse.landscape.Release; |
| 13 | 14 | import com.sap.sse.landscape.UserDataProvider; |
| 14 | 15 | import com.sap.sse.landscape.application.ApplicationProcess; |
| ... | ... | @@ -43,7 +44,7 @@ implements UserDataProvider { |
| 43 | 44 | * {@link #getServerName() server name}.</li> |
| 44 | 45 | * <li>The {@link #setInboundReplicationConfiguration(InboundReplicationConfiguration) inbound replication} |
| 45 | 46 | * {@link InboundReplicationConfiguration#getInboundRabbitMQEndpoint() RabbitMQ endpoint} defaults to the region's |
| 46 | - * {@link AwsLandscape#getDefaultRabbitConfiguration(com.sap.sse.landscape.aws.impl.AwsRegion) default RabbitMQ |
|
| 47 | + * {@link AwsLandscape#getDefaultRabbitConfiguration(Region) default RabbitMQ |
|
| 47 | 48 | * configuration}. Note that this setting will take effect only if auto-replication is activated for one or more |
| 48 | 49 | * replicables (see {@link InboundReplicationConfiguration#getReplicableIds()}).</li> |
| 49 | 50 | * <li>The {@link #setOutboundReplicationConfiguration() outbound replication} |
java/com.sap.sse.landscape/src/com/sap/sse/landscape/Landscape.java
| ... | ... | @@ -49,10 +49,15 @@ public interface Landscape<ShardingKey> { |
| 49 | 49 | /** |
| 50 | 50 | * Obtains the default RabbitMQ configuration for the {@code region} specified. If nothing else is specified |
| 51 | 51 | * explicitly, application server replica sets launched in the {@code region} shall use this for their replication |
| 52 | - * message channels and exchanges. |
|
| 52 | + * message channels and exchanges.<p> |
|
| 53 | + * |
|
| 54 | + * For our default region, this will return a DNS name always pointing to the current private IP of |
|
| 55 | + * the instance running the default RabbitMQ service in the region. In other regions, the private IP |
|
| 56 | + * of the regional default RabbitMQ instance is discovered by scanning for running instances tagged |
|
| 57 | + * with {@link SharedLandscapeConstants#RABBITMQ_TAG_NAME}. |
|
| 53 | 58 | */ |
| 54 | - RabbitMQEndpoint getMessagingConfigurationForDefaultCluster(Region region); |
|
| 55 | - |
|
| 59 | + RabbitMQEndpoint getDefaultRabbitConfiguration(Region region); |
|
| 60 | + |
|
| 56 | 61 | /** |
| 57 | 62 | * Tells the regions supported. The underlying hyperscaler may have more, but we may not want to run in all. |
| 58 | 63 | */ |
wiki/info/landscape/creating-ec2-image-for-rabbitmq-from-scratch.md
| ... | ... | @@ -12,6 +12,8 @@ where ``a.b.c.d`` is the external IP address of your fresh instance. |
| 12 | 12 | |
| 13 | 13 | The script will ensure the login user's ``authorized_keys`` are updated periodically to contain those of the landscape managers, then will install the necessary packages, particularly ``rabbitmq-server`` and, to get real log files under ``/var/log``, the ``syslog-ng`` package. It then enables the ``rabbitmq_management`` plugin, so access to the management UI becomes possible through port ``15672``. The configuration file under ``/etc/rabbitmq/rabbitmq.conf`` is patched such that guest logins are possible also from non-localhost addresses, by adding the ``loopback_users = none`` directive to the config file. It finally (re-)starts the RabbitMQ server to let these config changes take effect. |
| 14 | 14 | |
| 15 | -Your RabbitMQ server then should be ready to handle requests. Test this by invoking the management UI, e.g., through an ssh port forward to port ``15672``. When this seems good, pick a smart time to change the DNS record for ``rabbit.internal.sapsailing.com`` because there will be a short time of interruptions on all application processes currently connected to the old RabbitMQ which you then have to stop. Those client applications will temporarily lose connection, but our replication component will re-establish these connections, using the DNS name which gets resolved again based on the DNS entry's TTL. Also, let ``rabbit.sapsailing.com`` point to the public IP of the instance. |
|
| 15 | +Your RabbitMQ server then should be ready to handle requests. Test this by invoking the management UI, e.g., through an ssh port forward to port ``15672``. When this seems good, pick a smart time to change the DNS record for ``rabbit.internal.sapsailing.com`` because there will be a short time of interruptions on all application processes currently connected to the old RabbitMQ which you then have to stop. Those client applications will temporarily lose connection, but our replication component will re-establish these connections, using the DNS name which gets resolved again based on the DNS entry's TTL. |
|
| 16 | 16 | |
| 17 | -Add a tag with key ``RabbitMQEndpoint`` and value ``5672``, specifying the port on which the RabbitMQ server listens. This tag can be used by our landscape automation procedures to discover the RabbitMQ default instance in the region. |
|
| ... | ... | \ No newline at end of file |
| 0 | +Then associate the elastic IP ``54.76.64.42`` as the external IP of the new instance. This will let ``rabbit.sapsailing.com`` point to the public IP of the instance. |
|
| 1 | + |
|
| 2 | +Add a tag with key ``RabbitMQEndpoint`` and value ``5672``, specifying the port on which the RabbitMQ server listens. This tag can be used by our landscape automation procedures to discover the RabbitMQ default instance in the region. |