/* * 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.configuration; import org.apache.geode.cache.Cache; import org.apache.geode.cache.DiskStoreFactory; import org.apache.geode.cache.RegionFactory; import org.apache.geode.cache.RegionShortcut; import org.apache.geode.distributed.Locator; import org.apache.geode.distributed.internal.ClusterConfigurationService; import org.apache.geode.distributed.internal.DM; import org.apache.geode.distributed.internal.InternalLocator; import org.apache.geode.distributed.internal.membership.InternalDistributedMember; import org.apache.geode.distributed.internal.tcpserver.TcpClient; import org.apache.geode.internal.cache.GemFireCacheImpl; import org.apache.geode.internal.cache.xmlcache.CacheXml; import org.apache.geode.management.internal.configuration.domain.Configuration; import org.apache.geode.management.internal.configuration.domain.XmlEntity; import org.apache.geode.management.internal.configuration.handlers.ConfigurationRequestHandler; import org.apache.geode.management.internal.configuration.messages.ConfigurationRequest; import org.apache.geode.management.internal.configuration.messages.ConfigurationResponse; import org.apache.geode.test.dunit.VM; import org.apache.geode.test.dunit.WaitCriterion; import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase; import org.apache.geode.test.junit.categories.DistributedTest; import org.junit.Test; import org.junit.experimental.categories.Category; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.util.*; import static org.apache.geode.distributed.ConfigurationProperties.*; import static org.apache.geode.internal.AvailablePortHelper.getRandomAvailableTCPPorts; import static org.apache.geode.test.dunit.Assert.*; import static org.apache.geode.test.dunit.Host.getHost; import static org.apache.geode.test.dunit.Wait.waitForCriterion; /** * Tests the starting up of shared configuration, installation of * {@link ConfigurationRequestHandler} */ @Category(DistributedTest.class) public class ClusterConfigurationServiceDUnitTest extends JUnit4CacheTestCase { private static final String REGION1 = "region1"; private static final int TIMEOUT = 10000; private static final int INTERVAL = 500; private static final String DISKSTORENAME = "diskStore1"; @Override public final void postSetUp() throws Exception { disconnectAllFromDS(); } @Override public final void postTearDownCacheTestCase() throws Exception { for (int i = 0; i < 4; i++) { getHost(0).getVM(i).invoke(SharedConfigurationTestUtils.cleanupLocator); } } @Test public void testGetHostedLocatorsWithSharedConfiguration() throws Exception { final VM locator1Vm = getHost(0).getVM(1); final VM locator2Vm = getHost(0).getVM(2); final String testName = getName(); final int[] ports = getRandomAvailableTCPPorts(3); final int locator1Port = ports[0]; final String locator1Name = "locator1" + locator1Port; locator1Vm.invoke(() -> { final File locatorLogFile = new File(testName + "-locator-" + locator1Port + ".log"); final Properties locatorProps = new Properties(); locatorProps.setProperty(NAME, locator1Name); locatorProps.setProperty(MCAST_PORT, "0"); locatorProps.setProperty(LOG_LEVEL, "fine"); locatorProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "true"); try { final InternalLocator locator = (InternalLocator) Locator.startLocatorAndDS(locator1Port, locatorLogFile, null, locatorProps); WaitCriterion wc = new WaitCriterion() { @Override public boolean done() { return locator.isSharedConfigurationRunning(); } @Override public String description() { return "Waiting for shared configuration to be started"; } }; waitForCriterion(wc, TIMEOUT, INTERVAL, true); } catch (IOException e) { fail("Unable to create a locator with a shared configuration", e); } GemFireCacheImpl cache = GemFireCacheImpl.getInstance(); InternalDistributedMember me = cache.getMyId(); DM dm = cache.getDistributionManager(); Map<InternalDistributedMember, Collection<String>> hostedLocators = dm.getAllHostedLocators(); assertFalse(hostedLocators.isEmpty()); Map<InternalDistributedMember, Collection<String>> hostedLocatorsWithSharedConfiguration = dm.getAllHostedLocatorsWithSharedConfiguration(); assertFalse(hostedLocatorsWithSharedConfiguration.isEmpty()); assertNotNull(hostedLocators.get(me)); assertNotNull(hostedLocatorsWithSharedConfiguration.get(me)); return null; }); final int locator2Port = ports[1]; final String locator2Name = "locator2" + locator2Port; locator2Vm.invoke(() -> { final File locatorLogFile = new File(testName + "-locator-" + locator2Port + ".log"); final Properties locatorProps = new Properties(); locatorProps.setProperty(NAME, locator2Name); locatorProps.setProperty(MCAST_PORT, "0"); locatorProps.setProperty(LOG_LEVEL, "fine"); locatorProps.setProperty(LOCATORS, "localhost[" + locator1Port + "]"); locatorProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "false"); final InternalLocator locator = (InternalLocator) Locator.startLocatorAndDS(locator2Port, locatorLogFile, null, locatorProps); GemFireCacheImpl cache = GemFireCacheImpl.getInstance(); InternalDistributedMember me = cache.getMyId(); DM dm = cache.getDistributionManager(); Map<InternalDistributedMember, Collection<String>> hostedLocators = dm.getAllHostedLocators(); assertFalse(hostedLocators.isEmpty()); Map<InternalDistributedMember, Collection<String>> hostedLocatorsWithSharedConfiguration = dm.getAllHostedLocatorsWithSharedConfiguration(); assertFalse(hostedLocatorsWithSharedConfiguration.isEmpty()); assertNotNull(hostedLocators.get(me)); assertNull(hostedLocatorsWithSharedConfiguration.get(me)); assertTrue(hostedLocators.size() == 2); assertTrue(hostedLocatorsWithSharedConfiguration.size() == 1); Set<InternalDistributedMember> locatorsWithSharedConfig = hostedLocatorsWithSharedConfiguration.keySet(); Set<String> locatorsWithSharedConfigNames = new HashSet<String>(); for (InternalDistributedMember locatorWithSharedConfig : locatorsWithSharedConfig) { locatorsWithSharedConfigNames.add(locatorWithSharedConfig.getName()); } assertTrue(locatorsWithSharedConfigNames.contains(locator1Name)); return null; }); locator1Vm.invoke(() -> { InternalLocator locator = (InternalLocator) Locator.getLocator(); ClusterConfigurationService sharedConfig = locator.getSharedConfiguration(); sharedConfig.destroySharedConfiguration(); locator.stop(); return null; }); locator2Vm.invoke(() -> { GemFireCacheImpl cache = GemFireCacheImpl.getInstance(); InternalDistributedMember me = cache.getMyId(); DM dm = cache.getDistributionManager(); Map<InternalDistributedMember, Collection<String>> hostedLocators = dm.getAllHostedLocators(); assertFalse(hostedLocators.isEmpty()); Map<InternalDistributedMember, Collection<String>> hostedLocatorsWithSharedConfiguration = dm.getAllHostedLocatorsWithSharedConfiguration(); assertTrue(hostedLocatorsWithSharedConfiguration.isEmpty()); assertNotNull(hostedLocators.get(me)); assertNull(hostedLocatorsWithSharedConfiguration.get(me)); assertTrue(hostedLocators.size() == 1); assertTrue(hostedLocatorsWithSharedConfiguration.size() == 0); return null; }); } @Test public void testSharedConfigurationService() throws Exception { // Start the Locator and wait for shared configuration to be available final String testGroup = "G1"; final String clusterLogLevel = "error"; final String groupLogLevel = "fine"; final String testName = getName(); final VM locator1Vm = getHost(0).getVM(1); final VM dataMemberVm = getHost(0).getVM(2); final VM locator2Vm = getHost(0).getVM(3); final int[] ports = getRandomAvailableTCPPorts(3); final int locator1Port = ports[0]; locator1Vm.invoke(() -> { final File locatorLogFile = new File(testName + "-locator-" + locator1Port + ".log"); final Properties locatorProps = new Properties(); locatorProps.setProperty(NAME, "Locator1"); locatorProps.setProperty(MCAST_PORT, "0"); locatorProps.setProperty(LOG_LEVEL, "info"); locatorProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "true"); try { final InternalLocator locator = (InternalLocator) Locator.startLocatorAndDS(locator1Port, locatorLogFile, null, locatorProps); WaitCriterion wc = new WaitCriterion() { @Override public boolean done() { return locator.isSharedConfigurationRunning(); } @Override public String description() { return "Waiting for shared configuration to be started"; } }; waitForCriterion(wc, TIMEOUT, INTERVAL, true); } catch (IOException e) { fail("Unable to create a locator with a shared configuration", e); } }); XmlEntity xmlEntity = dataMemberVm.invoke(() -> { Properties localProps = new Properties(); localProps.setProperty(MCAST_PORT, "0"); localProps.setProperty(LOCATORS, "localhost[" + locator1Port + "]"); localProps.setProperty(GROUPS, testGroup); getSystem(localProps); Cache cache = getCache(); assertNotNull(cache); DiskStoreFactory dsFactory = cache.createDiskStoreFactory(); File dsDir = new File("dsDir"); if (!dsDir.exists()) { dsDir.mkdir(); } dsFactory.setDiskDirs(new File[] {dsDir}); dsFactory.create(DISKSTORENAME); RegionFactory regionFactory = getCache().createRegionFactory(RegionShortcut.REPLICATE); regionFactory.create(REGION1); return new XmlEntity(CacheXml.REGION, "name", REGION1); }); locator1Vm.invoke(() -> { ClusterConfigurationService sc = InternalLocator.getLocator().getSharedConfiguration(); sc.addXmlEntity(xmlEntity, new String[] {testGroup}); // Modify property and cache attributes Properties clusterProperties = new Properties(); clusterProperties.setProperty(LOG_LEVEL, clusterLogLevel); XmlEntity cacheEntity = XmlEntity.builder().withType(CacheXml.CACHE).build(); Map<String, String> cacheAttributes = new HashMap<String, String>(); cacheAttributes.put(CacheXml.COPY_ON_READ, "true"); sc.modifyXmlAndProperties(clusterProperties, cacheEntity, null); clusterProperties.setProperty(LOG_LEVEL, groupLogLevel); sc.modifyXmlAndProperties(clusterProperties, cacheEntity, new String[] {testGroup}); // Add a jar byte[][] jarBytes = new byte[1][]; jarBytes[0] = "Hello".getBytes(); assertTrue(sc.addJarsToThisLocator(new String[] {"foo.jar"}, jarBytes, null)); // Add a jar for the group jarBytes = new byte[1][]; jarBytes[0] = "Hello".getBytes(); assertTrue( sc.addJarsToThisLocator(new String[] {"bar.jar"}, jarBytes, new String[] {testGroup})); }); final int locator2Port = ports[1]; // Create another locator in VM2 locator2Vm.invoke(() -> { final File locatorLogFile = new File(testName + "-locator-" + locator2Port + ".log"); final Properties locatorProps = new Properties(); locatorProps.setProperty(NAME, "Locator2"); locatorProps.setProperty(MCAST_PORT, "0"); locatorProps.setProperty(LOG_LEVEL, "info"); locatorProps.setProperty(ENABLE_CLUSTER_CONFIGURATION, "true"); locatorProps.setProperty(LOCATORS, "localhost[" + locator1Port + "]"); try { final InternalLocator locator = (InternalLocator) Locator.startLocatorAndDS(locator2Port, locatorLogFile, null, locatorProps); WaitCriterion wc = new WaitCriterion() { @Override public boolean done() { return locator.isSharedConfigurationRunning(); } @Override public String description() { return "Waiting for shared configuration to be started"; } }; waitForCriterion(wc, TIMEOUT, INTERVAL, true); } catch (IOException e) { fail("Unable to create a locator with a shared configuration", e); } InternalLocator locator = (InternalLocator) Locator.getLocator(); ClusterConfigurationService sharedConfig = locator.getSharedConfiguration(); Map<String, Configuration> entireConfiguration = sharedConfig.getEntireConfiguration(); Configuration clusterConfig = entireConfiguration.get(ClusterConfigurationService.CLUSTER_CONFIG); assertNotNull(clusterConfig); assertNotNull(clusterConfig.getJarNames()); assertTrue(clusterConfig.getJarNames().contains("foo.jar")); assertTrue( clusterConfig.getGemfireProperties().getProperty(LOG_LEVEL).equals(clusterLogLevel)); assertNotNull(clusterConfig.getCacheXmlContent()); Configuration testGroupConfiguration = entireConfiguration.get(testGroup); assertNotNull(testGroupConfiguration); assertNotNull(testGroupConfiguration.getJarNames()); assertTrue(testGroupConfiguration.getJarNames().contains("bar.jar")); assertTrue(testGroupConfiguration.getGemfireProperties().getProperty(LOG_LEVEL) .equals(groupLogLevel)); assertNotNull(testGroupConfiguration.getCacheXmlContent()); assertTrue(testGroupConfiguration.getCacheXmlContent().contains(REGION1)); Map<String, byte[]> jarData = sharedConfig.getAllJarsFromThisLocator(entireConfiguration.keySet()); String[] jarNames = jarData.keySet().stream().toArray(String[]::new); byte[][] jarBytes = jarData.values().toArray(new byte[jarNames.length][]); assertNotNull(jarNames); assertNotNull(jarBytes); sharedConfig.deleteXmlEntity(new XmlEntity(CacheXml.REGION, "name", REGION1), new String[] {testGroup}); sharedConfig.removeJars(new String[] {"foo.jar"}, null); sharedConfig.removeJars(null, null); }); dataMemberVm.invoke(() -> { Set<String> groups = new HashSet<String>(); groups.add(testGroup); ConfigurationRequest configRequest = new ConfigurationRequest(groups); ConfigurationResponse configResponse = (ConfigurationResponse) new TcpClient() .requestToServer(InetAddress.getByName("localhost"), locator2Port, configRequest, 1000); assertNotNull(configResponse); Map<String, Configuration> requestedConfiguration = configResponse.getRequestedConfiguration(); Configuration clusterConfiguration = requestedConfiguration.get(ClusterConfigurationService.CLUSTER_CONFIG); assertNotNull(clusterConfiguration); assertTrue(configResponse.getJarNames().length == 0); assertTrue(configResponse.getJars().length == 0); assertTrue(clusterConfiguration.getJarNames().isEmpty()); assertTrue(clusterConfiguration.getGemfireProperties().getProperty(LOG_LEVEL) .equals(clusterLogLevel)); Configuration testGroupConfiguration = requestedConfiguration.get(testGroup); assertNotNull(testGroupConfiguration); assertFalse(testGroupConfiguration.getCacheXmlContent().contains(REGION1)); assertTrue(testGroupConfiguration.getJarNames().isEmpty()); assertTrue(testGroupConfiguration.getGemfireProperties().getProperty(LOG_LEVEL) .equals(groupLogLevel)); GemFireCacheImpl cache = (GemFireCacheImpl) getCache(); Map<InternalDistributedMember, Collection<String>> locatorsWithSharedConfiguration = cache.getDistributionManager().getAllHostedLocatorsWithSharedConfiguration(); assertFalse(locatorsWithSharedConfiguration.isEmpty()); assertTrue(locatorsWithSharedConfiguration.size() == 2); Set<InternalDistributedMember> locatorMembers = locatorsWithSharedConfiguration.keySet(); for (InternalDistributedMember locatorMember : locatorMembers) { System.out.println(locatorMember); } return null; }); } }