| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the License. You may obtain a |
| * copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package org.apache.geode.management.internal.cli.commands; |
| |
| import static org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT; |
| import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER; |
| import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_PORT; |
| import static org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_START; |
| import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS; |
| import static org.apache.geode.distributed.ConfigurationProperties.LOG_FILE; |
| import static org.apache.geode.distributed.ConfigurationProperties.MAX_WAIT_TIME_RECONNECT; |
| import static org.apache.geode.distributed.ConfigurationProperties.MEMBER_TIMEOUT; |
| import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPorts; |
| import static org.apache.geode.test.awaitility.GeodeAwaitility.await; |
| import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException; |
| import static org.apache.geode.test.dunit.VM.getVM; |
| import static org.apache.geode.test.dunit.VM.getVMId; |
| import static org.apache.geode.test.dunit.VM.toArray; |
| import static org.assertj.core.api.Assertions.assertThat; |
| |
| import java.io.File; |
| import java.io.Serializable; |
| import java.util.concurrent.atomic.AtomicReference; |
| |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.experimental.categories.Category; |
| |
| import org.apache.geode.cache.Cache; |
| import org.apache.geode.distributed.DistributedSystemDisconnectedException; |
| import org.apache.geode.distributed.LocatorLauncher; |
| import org.apache.geode.distributed.ServerLauncher; |
| import org.apache.geode.distributed.internal.InternalLocator; |
| import org.apache.geode.test.dunit.VM; |
| import org.apache.geode.test.dunit.rules.DistributedRule; |
| import org.apache.geode.test.junit.categories.GfshTest; |
| import org.apache.geode.test.junit.rules.GfshCommandRule; |
| import org.apache.geode.test.junit.rules.GfshCommandRule.PortType; |
| import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder; |
| |
| @Category(GfshTest.class) |
| public class ShutdownCommandOverHttpDUnitTest implements Serializable { |
| |
| private static final String LOCATOR_NAME = "locator"; |
| private static final String SERVER1_NAME = "server1"; |
| private static final String SERVER2_NAME = "server2"; |
| private static final AtomicReference<LocatorLauncher> LOCATOR_LAUNCHER = new AtomicReference<>(); |
| private static final AtomicReference<ServerLauncher> SERVER_LAUNCHER = new AtomicReference<>(); |
| |
| private VM locator; |
| private VM server1; |
| private VM server2; |
| |
| private String locatorString; |
| private int locatorPort; |
| private int locatorJmxPort; |
| private int locatorHttpPort; |
| |
| @Rule |
| public DistributedRule distributedRule = new DistributedRule(); |
| @Rule |
| public SerializableTemporaryFolder temporaryFolder = new SerializableTemporaryFolder(); |
| @Rule |
| public transient GfshCommandRule gfsh = new GfshCommandRule(); |
| |
| @Before |
| public void setUp() throws Exception { |
| locator = getVM(0); |
| server1 = getVM(1); |
| server2 = getVM(2); |
| |
| File locatorDir = temporaryFolder.newFolder(LOCATOR_NAME); |
| File server1Dir = temporaryFolder.newFolder(SERVER1_NAME); |
| File server2Dir = temporaryFolder.newFolder(SERVER2_NAME); |
| |
| int[] ports = getRandomAvailableTCPPorts(3); |
| locatorPort = ports[0]; |
| locatorJmxPort = ports[1]; |
| locatorHttpPort = ports[2]; |
| |
| locatorString = "localhost[" + locatorPort + "]"; |
| |
| locator.invoke(() -> startLocator(locatorDir, locatorPort, locatorJmxPort, locatorHttpPort)); |
| server1.invoke(() -> startServer(SERVER1_NAME, server1Dir, locatorString)); |
| server2.invoke(() -> startServer(SERVER2_NAME, server2Dir, locatorString)); |
| |
| gfsh.connectAndVerify(locatorHttpPort, PortType.http); |
| |
| addIgnoredException(DistributedSystemDisconnectedException.class); |
| } |
| |
| @Test |
| public void testShutdownServers() { |
| String command = "shutdown"; |
| |
| gfsh.executeAndAssertThat(command) |
| .statusIsSuccess() |
| .containsOutput("Shutdown is triggered"); |
| |
| for (VM vm : toArray(server1, server2)) { |
| vm.invoke(() -> verifyNotConnected(SERVER_LAUNCHER.get().getCache())); |
| } |
| |
| gfsh.executeAndAssertThat("list members") |
| .statusIsSuccess(); |
| |
| assertThat(gfsh.getGfshOutput()).contains("locator"); |
| } |
| |
| @Test |
| public void testShutdownAll() { |
| String command = "shutdown --include-locators=true"; |
| |
| gfsh.executeAndAssertThat(command) |
| .statusIsSuccess() |
| .containsOutput("Shutdown is triggered"); |
| |
| server1.invoke(() -> verifyNotConnected(SERVER_LAUNCHER.get().getCache())); |
| server2.invoke(() -> verifyNotConnected(SERVER_LAUNCHER.get().getCache())); |
| locator.invoke(() -> verifyNotConnected(LOCATOR_LAUNCHER.get().getCache())); |
| } |
| |
| private void verifyNotConnected(Cache cache) { |
| await().untilAsserted(() -> { |
| assertThat(cache.getDistributedSystem().isConnected()) |
| .as("cache.getDistributedSystem().isConnected()") |
| .isFalse(); |
| }); |
| } |
| |
| private void startLocator(File directory, int port, int jmxPort, int httpPort) { |
| LOCATOR_LAUNCHER.set(new LocatorLauncher.Builder() |
| .setDeletePidFileOnStop(true) |
| .setMemberName(LOCATOR_NAME) |
| .setPort(port) |
| .setWorkingDirectory(directory.getAbsolutePath()) |
| .set(HTTP_SERVICE_PORT, String.valueOf(httpPort)) |
| .set(JMX_MANAGER, "true") |
| .set(JMX_MANAGER_PORT, String.valueOf(jmxPort)) |
| .set(JMX_MANAGER_START, "true") |
| .set(LOG_FILE, new File(directory, LOCATOR_NAME + ".log").getAbsolutePath()) |
| .set(MAX_WAIT_TIME_RECONNECT, "1000") |
| .set(MEMBER_TIMEOUT, "2000") |
| .build()); |
| |
| LOCATOR_LAUNCHER.get().start(); |
| |
| InternalLocator locator = (InternalLocator) LOCATOR_LAUNCHER.get().getLocator(); |
| |
| await().untilAsserted(() -> { |
| assertThat(locator.isSharedConfigurationRunning()) |
| .as("Locator shared configuration is running on locator" + getVMId()) |
| .isTrue(); |
| }); |
| } |
| |
| private void startServer(String name, File workingDirectory, String locator) { |
| SERVER_LAUNCHER.set(new ServerLauncher.Builder() |
| .setDeletePidFileOnStop(true) |
| .setDisableDefaultServer(true) |
| .setMemberName(name) |
| .setWorkingDirectory(workingDirectory.getAbsolutePath()) |
| .set(HTTP_SERVICE_PORT, "0") |
| .set(LOCATORS, locator) |
| .set(LOG_FILE, new File(workingDirectory, name + ".log").getAbsolutePath()) |
| .set(MAX_WAIT_TIME_RECONNECT, "1000") |
| .set(MEMBER_TIMEOUT, "2000") |
| .build()); |
| |
| SERVER_LAUNCHER.get().start(); |
| } |
| } |