Java tutorial
/* * Copyright 2015 VMware, Inc. All Rights Reserved. * * Licensed 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 com.vmware.photon.controller.housekeeper.xenon; import com.vmware.photon.controller.apibackend.ApiBackendFactory; import com.vmware.photon.controller.common.clients.HostClient; import com.vmware.photon.controller.common.clients.HostClientFactory; import com.vmware.photon.controller.common.config.ConfigBuilder; import com.vmware.photon.controller.common.thrift.ServerSet; import com.vmware.photon.controller.common.xenon.CloudStoreHelper; import com.vmware.photon.controller.common.xenon.ServiceHostUtils; import com.vmware.photon.controller.common.xenon.host.PhotonControllerXenonHost; import com.vmware.photon.controller.common.xenon.host.XenonConfig; import com.vmware.photon.controller.common.xenon.scheduler.TaskSchedulerServiceFactory; import com.vmware.photon.controller.common.xenon.scheduler.TaskTriggerFactoryService; import com.vmware.photon.controller.housekeeper.HousekeeperConfig; import com.vmware.photon.controller.nsxclient.NsxClientFactory; import com.vmware.xenon.common.Service; import com.vmware.xenon.services.common.LuceneDocumentIndexService; import com.vmware.xenon.services.common.RootNamespaceService; import com.vmware.xenon.services.common.ServiceUriPaths; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.ArrayUtils; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Tests {@link HousekeeperServiceGroup}. */ public class HousekeeperServiceGroupTest { private static File storageDir; private static final String configFilePath = "/config.yml"; /** * Maximum time to wait for all factories to become available. */ private static final long SERVICES_STARTUP_TIMEOUT = TimeUnit.SECONDS.toMillis(30); private PhotonControllerXenonHost host; private HousekeeperServiceGroup housekeeperServiceGroup; private HousekeeperConfig config; private CloudStoreHelper cloudStoreHelper; private HostClientFactory hostClientFactory; private NsxClientFactory nsxClientFactory; private ServerSet cloudStoreServerSet; private String[] serviceSelfLinks = createServiceSelfLinks(); /** * Dummy test case to make Intellij recognize this as a test class. */ @Test private void dummy() { } /** * Tests for the constructors. */ public class InitializationTest { @BeforeClass public void setUpClass() throws Exception { config = ConfigBuilder.build(HousekeeperConfig.class, HousekeeperServiceGroupTest.class.getResource(configFilePath).getPath()); cloudStoreServerSet = mock(ServerSet.class); cloudStoreHelper = new CloudStoreHelper(cloudStoreServerSet); hostClientFactory = mock(HostClientFactory.class); HostClient client = mock(HostClient.class); when(hostClientFactory.create()).thenReturn(client); nsxClientFactory = new NsxClientFactory(); storageDir = new File(config.getXenonConfig().getStoragePath()); FileUtils.deleteDirectory(storageDir); } @BeforeMethod public void setUp() throws Throwable { host = new PhotonControllerXenonHost(config.getXenonConfig(), hostClientFactory, null, nsxClientFactory, cloudStoreHelper); housekeeperServiceGroup = new HousekeeperServiceGroup(); host.registerHousekeeper(housekeeperServiceGroup); } @AfterMethod public void tearDown() throws Exception { FileUtils.deleteDirectory(storageDir); } @Test public void testStoragePathExists() throws IOException { // make sure folder exists storageDir.mkdirs(); assertThat(storageDir.exists(), is(true)); assertThat(host, is(notNullValue())); } @Test public void testStoragePathDoesNotExist() throws Throwable { // make sure folder does not exist FileUtils.deleteDirectory(storageDir); assertThat(storageDir.exists(), is(false)); // Check that the host will create the storage directory. host = new PhotonControllerXenonHost(config.getXenonConfig(), hostClientFactory, null, nsxClientFactory, cloudStoreHelper); housekeeperServiceGroup = new HousekeeperServiceGroup(); host.registerHousekeeper(housekeeperServiceGroup); assertThat(storageDir.exists(), is(true)); assertThat(host, is(notNullValue())); } @Test public void testParams() { assertThat(host.getPort(), is(16000)); Path storagePath = Paths.get(storageDir.getPath()).resolve(Integer.toString(16000)); assertThat(host.getStorageSandbox().getPath(), is(storagePath.toString())); } @Test public void testGetHostClientFactory() { assertThat(host.getHostClient(), notNullValue()); } @Test public void testGetNsxClientFactory() { assertThat(host.getNsxClientFactory(), notNullValue()); } } /** * Tests for the start method. */ public class StartTest { @BeforeClass private void setUpClass() throws Throwable { config = ConfigBuilder.build(HousekeeperConfig.class, HousekeeperServiceGroupTest.class.getResource(configFilePath).getPath()); cloudStoreServerSet = mock(ServerSet.class); cloudStoreHelper = new CloudStoreHelper(cloudStoreServerSet); hostClientFactory = mock(HostClientFactory.class); nsxClientFactory = new NsxClientFactory(); storageDir = new File(config.getXenonConfig().getStoragePath()); FileUtils.deleteDirectory(storageDir); } @BeforeMethod private void setUp() throws Throwable { host = new PhotonControllerXenonHost(config.getXenonConfig(), hostClientFactory, null, nsxClientFactory, cloudStoreHelper); housekeeperServiceGroup = new HousekeeperServiceGroup(); host.registerHousekeeper(housekeeperServiceGroup); } @AfterMethod private void tearDown() throws Throwable { if (host != null) { host.stop(); } FileUtils.deleteDirectory(storageDir); } @Test public void testStart() throws Throwable { host.start(); try { ServiceHostUtils.waitForServiceAvailability(host, SERVICES_STARTUP_TIMEOUT, serviceSelfLinks.clone()); } catch (TimeoutException e) { // we swallow up this exception so that down below we get a better message of what // service failed to start. } assertThat(host.checkServiceAvailable(ServiceUriPaths.DEFAULT_NODE_GROUP), is(true)); assertThat(host.checkServiceAvailable(LuceneDocumentIndexService.SELF_LINK), is(true)); assertThat(host.checkServiceAvailable(ServiceUriPaths.CORE_QUERY_TASKS), is(true)); for (String selfLink : serviceSelfLinks) { assertThat(String.format("Failed to start service: %s", selfLink), host.checkServiceAvailable(selfLink), is(true)); } } } /** * Tests for the isReady method. */ public class IsReadyTest { @BeforeClass private void setUpClass() throws Throwable { config = ConfigBuilder.build(HousekeeperConfig.class, HousekeeperServiceGroupTest.class.getResource(configFilePath).getPath()); cloudStoreServerSet = mock(ServerSet.class); cloudStoreHelper = new CloudStoreHelper(cloudStoreServerSet); hostClientFactory = mock(HostClientFactory.class); nsxClientFactory = new NsxClientFactory(); storageDir = new File(config.getXenonConfig().getStoragePath()); FileUtils.deleteDirectory(storageDir); } @BeforeMethod private void setUp() throws Throwable { host = new PhotonControllerXenonHost(config.getXenonConfig(), hostClientFactory, null, nsxClientFactory, cloudStoreHelper); housekeeperServiceGroup = new HousekeeperServiceGroup(); host.registerHousekeeper(housekeeperServiceGroup); host.start(); ServiceHostUtils.waitForServiceAvailability(host, SERVICES_STARTUP_TIMEOUT, serviceSelfLinks.clone()); } @AfterMethod private void tearDown() throws Throwable { if (host != null) { host.stop(); } FileUtils.deleteDirectory(storageDir); } @Test public void testAllReady() { assertThat(host.isReady(), is(true)); } @Test(enabled = false) public void testNotReady() { doReturn(false).when(host).checkServiceAvailable(anyString()); assertThat(host.isReady(), is(false)); } } /** * Tests for joining node group. */ public class JoinNodeGroupTest { private final long maintenanceInterval = TimeUnit.MILLISECONDS.toMicros(500); private final File storageDir2 = new File("/tmp/xenon/16001/"); private PhotonControllerXenonHost host2; @BeforeClass private void setUpClass() throws Throwable { config = ConfigBuilder.build(HousekeeperConfig.class, HousekeeperServiceGroupTest.class.getResource(configFilePath).getPath()); cloudStoreServerSet = mock(ServerSet.class); cloudStoreHelper = new CloudStoreHelper(cloudStoreServerSet); hostClientFactory = mock(HostClientFactory.class); nsxClientFactory = new NsxClientFactory(); storageDir = new File(config.getXenonConfig().getStoragePath()); FileUtils.deleteDirectory(storageDir); } @BeforeMethod private void setUp() throws Throwable { XenonConfig xenonConfig = new XenonConfig(); xenonConfig.setBindAddress("0.0.0.0"); xenonConfig.setPort(16000); xenonConfig.setStoragePath(storageDir.getAbsolutePath()); host = new PhotonControllerXenonHost(xenonConfig, hostClientFactory, null, nsxClientFactory, cloudStoreHelper); housekeeperServiceGroup = new HousekeeperServiceGroup(); host.registerHousekeeper(housekeeperServiceGroup); host.setMaintenanceIntervalMicros(maintenanceInterval); host.start(); ServiceHostUtils.waitForServiceAvailability(host, SERVICES_STARTUP_TIMEOUT, serviceSelfLinks.clone()); XenonConfig xenonConfig2 = new XenonConfig(); xenonConfig2.setBindAddress("0.0.0.0"); xenonConfig2.setPort(16001); xenonConfig2.setStoragePath(storageDir2.getAbsolutePath()); host2 = new PhotonControllerXenonHost(xenonConfig2, hostClientFactory, null, nsxClientFactory, cloudStoreHelper); HousekeeperServiceGroup housekeeperServiceGroup2 = new HousekeeperServiceGroup(); host2.registerHousekeeper(housekeeperServiceGroup2); host2.setMaintenanceIntervalMicros(maintenanceInterval); host2.start(); ServiceHostUtils.waitForServiceAvailability(host2, SERVICES_STARTUP_TIMEOUT, serviceSelfLinks.clone()); } @AfterMethod private void tearDown() throws Throwable { if (host != null) { host.stop(); } FileUtils.deleteDirectory(storageDir); if (host2 != null) { host2.stop(); } FileUtils.deleteDirectory(storageDir2); } @Test public void testJoinNodeGroup() throws Throwable { ServiceHostUtils.joinNodeGroup(host2, host.getUri().getHost(), host.getPort()); ServiceHostUtils.waitForNodeGroupConvergence(new PhotonControllerXenonHost[] { host, host2 }, ServiceUriPaths.DEFAULT_NODE_GROUP, ServiceHostUtils.DEFAULT_NODE_GROUP_CONVERGENCE_MAX_RETRIES, ServiceHostUtils.DEFAULT_NODE_GROUP_CONVERGENCE_SLEEP); } } private String[] createServiceSelfLinks() { List<String> apiBackendServiceSelfLinks = new ArrayList<>(); Set<Class<? extends Service>> set = ApiBackendFactory.FACTORY_SERVICES_MAP.keySet(); for (Class cls : set) { try { Field fld = cls.getField("FACTORY_LINK"); apiBackendServiceSelfLinks.add((String) fld.get(null)); } catch (IllegalAccessException | NoSuchFieldException e) { // Simply ignore them } } return ArrayUtils.addAll(apiBackendServiceSelfLinks.toArray(new String[0]), RootNamespaceService.SELF_LINK, ImageReplicatorServiceFactory.SELF_LINK, ImageCopyServiceFactory.SELF_LINK, ImageHostToHostCopyServiceFactory.SELF_LINK, ImageDatastoreSweeperServiceFactory.SELF_LINK, ImageCleanerServiceFactory.SELF_LINK, ImageSeederSyncServiceFactory.SELF_LINK, TaskSchedulerServiceFactory.SELF_LINK, TaskTriggerFactoryService.SELF_LINK, HousekeeperServiceGroup.getTriggerCleanerServiceUri(), HousekeeperServiceGroup.getImageSeederSyncTriggerServiceUri(), HousekeeperServiceGroup.IMAGE_COPY_SCHEDULER_SERVICE); } }