| /** |
| * 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.ambari.server.controller.internal; |
| |
| import com.google.inject.Binder; |
| import com.google.inject.Guice; |
| import com.google.inject.Inject; |
| import com.google.inject.Injector; |
| import com.google.inject.Module; |
| import com.google.inject.persist.PersistService; |
| import com.google.inject.persist.Transactional; |
| import com.google.inject.util.Modules; |
| import junit.framework.Assert; |
| import org.apache.ambari.server.Role; |
| import org.apache.ambari.server.RoleCommand; |
| import org.apache.ambari.server.actionmanager.HostRoleStatus; |
| import org.apache.ambari.server.actionmanager.ServiceComponentHostEventWrapper; |
| import org.apache.ambari.server.controller.AmbariManagementController; |
| import org.apache.ambari.server.controller.AmbariServer; |
| import org.apache.ambari.server.controller.predicate.AndPredicate; |
| import org.apache.ambari.server.controller.spi.Predicate; |
| import org.apache.ambari.server.controller.spi.Request; |
| import org.apache.ambari.server.controller.spi.Resource; |
| import org.apache.ambari.server.controller.spi.ResourceProvider; |
| import org.apache.ambari.server.controller.utilities.PredicateBuilder; |
| import org.apache.ambari.server.controller.utilities.PropertyHelper; |
| import org.apache.ambari.server.orm.GuiceJpaInitializer; |
| import org.apache.ambari.server.orm.InMemoryDefaultTestModule; |
| import org.apache.ambari.server.orm.OrmTestHelper; |
| import org.apache.ambari.server.orm.dao.HostDAO; |
| import org.apache.ambari.server.orm.dao.HostRoleCommandDAO; |
| import org.apache.ambari.server.orm.dao.RepositoryVersionDAO; |
| import org.apache.ambari.server.orm.dao.RequestDAO; |
| import org.apache.ambari.server.orm.dao.StackDAO; |
| import org.apache.ambari.server.orm.dao.StageDAO; |
| import org.apache.ambari.server.orm.dao.UpgradeDAO; |
| import org.apache.ambari.server.orm.entities.HostEntity; |
| import org.apache.ambari.server.orm.entities.HostRoleCommandEntity; |
| import org.apache.ambari.server.orm.entities.RepositoryVersionEntity; |
| import org.apache.ambari.server.orm.entities.RequestEntity; |
| import org.apache.ambari.server.orm.entities.StackEntity; |
| import org.apache.ambari.server.orm.entities.StageEntity; |
| import org.apache.ambari.server.orm.entities.UpgradeEntity; |
| import org.apache.ambari.server.state.Cluster; |
| import org.apache.ambari.server.state.Clusters; |
| import org.apache.ambari.server.state.Host; |
| import org.apache.ambari.server.state.HostState; |
| import org.apache.ambari.server.state.RepositoryVersionState; |
| import org.apache.ambari.server.state.Service; |
| import org.apache.ambari.server.state.ServiceComponent; |
| import org.apache.ambari.server.state.ServiceComponentHost; |
| import org.apache.ambari.server.state.ServiceComponentHostEvent; |
| import org.apache.ambari.server.state.StackId; |
| import org.apache.ambari.server.state.UpgradeHelper; |
| import org.apache.ambari.server.state.stack.upgrade.Direction; |
| import org.apache.ambari.server.state.stack.upgrade.UpgradeType; |
| import org.apache.ambari.server.state.svccomphost.ServiceComponentHostOpInProgressEvent; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import static org.easymock.EasyMock.anyLong; |
| import static org.easymock.EasyMock.anyString; |
| import static org.easymock.EasyMock.createNiceMock; |
| import static org.easymock.EasyMock.expect; |
| import static org.easymock.EasyMock.replay; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| /** |
| * UpgradeSummaryResourceProvider tests. |
| */ |
| public class UpgradeSummaryResourceProviderTest { |
| |
| private HostDAO hostDAO; |
| private StackDAO stackDAO; |
| private RepositoryVersionDAO repoVersionDAO; |
| private UpgradeDAO upgradeDAO; |
| private RequestDAO requestDAO; |
| private StageDAO stageDAO; |
| private HostRoleCommandDAO hrcDAO; |
| |
| @Inject |
| private UpgradeHelper m_upgradeHelper; |
| |
| private Injector injector; |
| private Clusters clusters; |
| private OrmTestHelper helper; |
| private AmbariManagementController amc; |
| |
| private String clusterName = "c1"; |
| |
| @Before |
| public void before() throws Exception { |
| m_upgradeHelper = createNiceMock(UpgradeHelper.class); |
| |
| // Create an injector which will inject the mocks |
| injector = Guice.createInjector(Modules.override(new InMemoryDefaultTestModule()).with(new MockModule())); |
| injector.getInstance(GuiceJpaInitializer.class); |
| helper = injector.getInstance(OrmTestHelper.class); |
| amc = injector.getInstance(AmbariManagementController.class); |
| |
| Field field = AmbariServer.class.getDeclaredField("clusterController"); |
| field.setAccessible(true); |
| field.set(null, amc); |
| |
| hostDAO = injector.getInstance(HostDAO.class); |
| stackDAO = injector.getInstance(StackDAO.class); |
| repoVersionDAO = injector.getInstance(RepositoryVersionDAO.class); |
| upgradeDAO = injector.getInstance(UpgradeDAO.class); |
| requestDAO = injector.getInstance(RequestDAO.class); |
| stageDAO = injector.getInstance(StageDAO.class); |
| hrcDAO = injector.getInstance(HostRoleCommandDAO.class); |
| } |
| |
| @After |
| public void after() { |
| injector.getInstance(PersistService.class).stop(); |
| injector = null; |
| } |
| |
| /** |
| * Create a Cluster called c1 on HDP 2.2.0 with a single ZOOKEEPER_SERVER on Host h1 |
| */ |
| public void createCluster() throws Exception { |
| StackEntity stackEntity = stackDAO.find("HDP", "2.2.0"); |
| |
| RepositoryVersionEntity repoVersionEntity = new RepositoryVersionEntity(); |
| repoVersionEntity.setDisplayName("For Stack Version 2.2.0"); |
| repoVersionEntity.setOperatingSystems(""); |
| repoVersionEntity.setStack(stackEntity); |
| repoVersionEntity.setVersion("2.2.0.0"); |
| repoVersionDAO.create(repoVersionEntity); |
| |
| clusters = injector.getInstance(Clusters.class); |
| |
| StackId stackId = new StackId("HDP-2.2.0"); |
| clusters.addCluster(clusterName, stackId); |
| Cluster cluster = clusters.getCluster("c1"); |
| |
| helper.getOrCreateRepositoryVersion(stackId, stackId.getStackVersion()); |
| cluster.createClusterVersion(stackId, stackId.getStackVersion(), "admin", RepositoryVersionState.INSTALLING); |
| |
| clusters.addHost("h1"); |
| Host host = clusters.getHost("h1"); |
| Map<String, String> hostAttributes = new HashMap<String, String>(); |
| hostAttributes.put("os_family", "redhat"); |
| hostAttributes.put("os_release_version", "6.4"); |
| host.setHostAttributes(hostAttributes); |
| host.setState(HostState.HEALTHY); |
| host.persist(); |
| |
| clusters.mapHostToCluster("h1", "c1"); |
| |
| // add a single ZOOKEEPER server |
| Service service = cluster.addService("ZOOKEEPER"); |
| service.setDesiredStackVersion(cluster.getDesiredStackVersion()); |
| service.persist(); |
| |
| ServiceComponent component = service.addServiceComponent("ZOOKEEPER_SERVER"); |
| ServiceComponentHost sch = component.addServiceComponentHost("h1"); |
| sch.setVersion("2.2.0.0"); |
| |
| component = service.addServiceComponent("ZOOKEEPER_CLIENT"); |
| sch = component.addServiceComponentHost("h1"); |
| sch.setVersion("2.2.0.0"); |
| } |
| |
| /** |
| * Create a request, stage, and completed task. |
| * @param cluster |
| * @param upgradeRequestId |
| * @param stageId |
| */ |
| @Transactional |
| private void createCommands(Cluster cluster, Long upgradeRequestId, Long stageId) { |
| HostEntity h1 = hostDAO.findByName("h1"); |
| ServiceComponentHostEvent event = new ServiceComponentHostOpInProgressEvent("ZOOKEEPER_SERVER", "h1", 1L); |
| ServiceComponentHostEventWrapper eventWrapper = new ServiceComponentHostEventWrapper(event); |
| |
| RequestEntity requestEntity = new RequestEntity(); |
| requestEntity.setRequestId(upgradeRequestId); |
| requestEntity.setClusterId(cluster.getClusterId()); |
| requestEntity.setStatus(HostRoleStatus.PENDING); |
| requestDAO.create(requestEntity); |
| |
| // Create the stage and add it to the request |
| StageEntity stageEntity = new StageEntity(); |
| stageEntity.setRequest(requestEntity); |
| stageEntity.setClusterId(cluster.getClusterId()); |
| stageEntity.setRequestId(upgradeRequestId); |
| stageEntity.setStageId(stageId); |
| requestEntity.setStages(Collections.singletonList(stageEntity)); |
| stageDAO.create(stageEntity); |
| requestDAO.merge(requestEntity); |
| |
| // Create the task and add it to the stage |
| HostRoleCommandEntity hrc1 = new HostRoleCommandEntity(); |
| |
| hrc1.setStage(stageEntity); |
| hrc1.setStatus(HostRoleStatus.COMPLETED); |
| hrc1.setRole(Role.ZOOKEEPER_SERVER); |
| hrc1.setRoleCommand(RoleCommand.RESTART); |
| hrc1.setHostEntity(h1); |
| |
| stageEntity.setHostRoleCommands(new ArrayList<HostRoleCommandEntity>()); |
| stageEntity.getHostRoleCommands().add(hrc1); |
| h1.getHostRoleCommandEntities().add(hrc1); |
| |
| hrcDAO.create(hrc1); |
| hostDAO.merge(h1); |
| } |
| |
| /** |
| * Test UpgradeSummaryResourceProvider on several cases. |
| * 1. Incorrect cluster name throws exception |
| * 2. Upgrade with no tasks. |
| * 3. Construct Upgrade with a single COMPLETED task. Resource should not have a failed reason. |
| * 4. Append a failed task to the Upgrade. Resource should have a failed reason. |
| * @throws Exception |
| */ |
| @Test |
| public void testGetUpgradeSummary() throws Exception { |
| createCluster(); |
| |
| Cluster cluster = clusters.getCluster(clusterName); |
| ResourceProvider upgradeSummaryResourceProvider = createProvider(amc); |
| |
| // Case 1: Incorrect cluster name throws exception |
| Request requestResource = PropertyHelper.getReadRequest(); |
| Predicate pBogus = new PredicateBuilder().property(UpgradeSummaryResourceProvider.UPGRADE_SUMMARY_CLUSTER_NAME).equals("bogus name").toPredicate(); |
| try { |
| Set<Resource> resources = upgradeSummaryResourceProvider.getResources(requestResource, pBogus); |
| assertTrue("Expected exception to be thrown", false); |
| } catch (Exception e) { |
| ; |
| } |
| |
| // Case 2: Upgrade with no tasks. |
| Long upgradeRequestId = 1L; |
| |
| Predicate p1 = new PredicateBuilder().property(UpgradeSummaryResourceProvider.UPGRADE_SUMMARY_CLUSTER_NAME).equals(clusterName).toPredicate(); |
| Predicate p2 = new PredicateBuilder().property(UpgradeSummaryResourceProvider.UPGRADE_SUMMARY_REQUEST_ID).equals(upgradeRequestId.toString()).toPredicate(); |
| Predicate p1And2 = new AndPredicate(p1, p2); |
| |
| Set<Resource> resources = upgradeSummaryResourceProvider.getResources(requestResource, p1And2); |
| assertEquals(0, resources.size()); |
| |
| UpgradeEntity upgrade = new UpgradeEntity(); |
| upgrade.setRequestId(upgradeRequestId); |
| upgrade.setClusterId(cluster.getClusterId()); |
| upgrade.setId(1L); |
| upgrade.setUpgradePackage("some-name"); |
| upgrade.setUpgradeType(UpgradeType.ROLLING); |
| upgrade.setDirection(Direction.UPGRADE); |
| upgrade.setFromVersion("2.2.0.0"); |
| upgrade.setToVersion("2.2.0.1"); |
| upgradeDAO.create(upgrade); |
| |
| // Resource used to make assertions. |
| Resource r; |
| |
| resources = upgradeSummaryResourceProvider.getResources(requestResource, p1And2); |
| assertEquals(1, resources.size()); |
| r = resources.iterator().next(); |
| Assert.assertNull(r.getPropertyValue(UpgradeSummaryResourceProvider.UPGRADE_SUMMARY_FAIL_REASON)); |
| |
| // Case 3: Construct Upgrade with a single COMPLETED task. Resource should not have a failed reason. |
| Long currentStageId = 1L; |
| createCommands(cluster, upgradeRequestId, currentStageId); |
| |
| resources = upgradeSummaryResourceProvider.getResources(requestResource, p1And2); |
| assertEquals(1, resources.size()); |
| r = resources.iterator().next(); |
| Assert.assertNull(r.getPropertyValue(UpgradeSummaryResourceProvider.UPGRADE_SUMMARY_FAIL_REASON)); |
| |
| // Case 4: Append a failed task to the Upgrade. Resource should have a failed reason. |
| RequestEntity requestEntity = requestDAO.findByPK(upgradeRequestId); |
| HostEntity h1 = hostDAO.findByName("h1"); |
| |
| StageEntity nextStage = new StageEntity(); |
| nextStage.setRequest(requestEntity); |
| nextStage.setClusterId(cluster.getClusterId()); |
| nextStage.setRequestId(upgradeRequestId); |
| nextStage.setStageId(++currentStageId); |
| requestEntity.getStages().add(nextStage); |
| stageDAO.create(nextStage); |
| requestDAO.merge(requestEntity); |
| |
| // Create the task and add it to the stage |
| HostRoleCommandEntity hrc2 = new HostRoleCommandEntity(); |
| |
| hrc2.setStage(nextStage); |
| // Important that it's on its own stage with a FAILED status. |
| hrc2.setStatus(HostRoleStatus.FAILED); |
| hrc2.setRole(Role.ZOOKEEPER_SERVER); |
| hrc2.setRoleCommand(RoleCommand.RESTART); |
| hrc2.setCommandDetail("Restart ZOOKEEPER_SERVER"); |
| hrc2.setHostEntity(h1); |
| |
| nextStage.setHostRoleCommands(new ArrayList<HostRoleCommandEntity>()); |
| nextStage.getHostRoleCommands().add(hrc2); |
| h1.getHostRoleCommandEntities().add(hrc2); |
| |
| hrcDAO.create(hrc2); |
| hostDAO.merge(h1); |
| hrc2.setRequestId(upgradeRequestId); |
| hrc2.setStageId(nextStage.getStageId()); |
| hrcDAO.merge(hrc2); |
| |
| Resource failedTask = new ResourceImpl(Resource.Type.Task); |
| expect(m_upgradeHelper.getTaskResource(anyString(), anyLong(), anyLong(), anyLong())).andReturn(failedTask).anyTimes(); |
| replay(m_upgradeHelper); |
| |
| resources = upgradeSummaryResourceProvider.getResources(requestResource, p1And2); |
| assertEquals(1, resources.size()); |
| r = resources.iterator().next(); |
| assertEquals("Failed calling Restart ZOOKEEPER_SERVER on host h1", r.getPropertyValue(UpgradeSummaryResourceProvider.UPGRADE_SUMMARY_FAIL_REASON)); |
| } |
| |
| /** |
| * @param amc |
| * @return the provider |
| */ |
| private UpgradeSummaryResourceProvider createProvider(AmbariManagementController amc) { |
| return new UpgradeSummaryResourceProvider(amc); |
| } |
| |
| /** |
| * Mock module that will bind UpgradeHelper to a mock instance. |
| */ |
| private class MockModule implements Module { |
| @Override |
| public void configure(Binder binder) { |
| binder.bind(UpgradeHelper.class).toInstance(m_upgradeHelper); |
| } |
| } |
| } |