Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 7811A200BD1 for ; Mon, 28 Nov 2016 21:51:39 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 76CE8160B0D; Mon, 28 Nov 2016 20:51:39 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 4C63C160B00 for ; Mon, 28 Nov 2016 21:51:38 +0100 (CET) Received: (qmail 76897 invoked by uid 500); 28 Nov 2016 20:51:37 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 76887 invoked by uid 99); 28 Nov 2016 20:51:37 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 28 Nov 2016 20:51:37 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 3CFF7E04BB; Mon, 28 Nov 2016 20:51:37 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dili@apache.org To: commits@ambari.apache.org Message-Id: <56013a2c085c484a8dc178e646a887e7@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: ambari git commit: AMBARI-18987 A general preupgrade check on if services cannot be upgrade are installed (dili) Date: Mon, 28 Nov 2016 20:51:37 +0000 (UTC) archived-at: Mon, 28 Nov 2016 20:51:39 -0000 Repository: ambari Updated Branches: refs/heads/trunk 640d85a50 -> bb803fb33 AMBARI-18987 A general preupgrade check on if services cannot be upgrade are installed (dili) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/bb803fb3 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/bb803fb3 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/bb803fb3 Branch: refs/heads/trunk Commit: bb803fb332d8d247e236b5e1b29fe97acfd7a7ec Parents: 640d85a Author: Di Li Authored: Mon Nov 28 15:51:11 2016 -0500 Committer: Di Li Committed: Mon Nov 28 15:51:11 2016 -0500 ---------------------------------------------------------------------- .../ambari/server/checks/CheckDescription.java | 13 ++ .../server/checks/ServicePresenceCheck.java | 177 +++++++++++++++ .../server/checks/ServicePresenceCheckTest.java | 217 +++++++++++++++++++ 3 files changed, 407 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/bb803fb3/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java index fbc4be1..7f24bf4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/CheckDescription.java @@ -277,6 +277,19 @@ public class CheckDescription { "This service does not support upgrades and must be removed before the upgrade can continue. " + "After upgrading, Atlas can be reinstalled").build()); + public static CheckDescription SERVICE_PRESENCE_CHECK = new CheckDescription("SERVICE_PRESENCE_CHECK", + PrereqCheckType.SERVICE, + "Service Is Not Supported For Upgrades", + new ImmutableMap.Builder() + .put(AbstractCheckDescriptor.DEFAULT, + "The %s service is currently installed on the cluster. " + + "This service does not support upgrades and must be removed before the upgrade can continue. " + + "After upgrading, %s can be reinstalled") + .put(ServicePresenceCheck.KEY_SERVICE_REMOVED, + "The %s service is currently installed on the cluster. " + + "This service is removed from the new release and must be removed before the upgrade can continue. " + + "After upgrading, %s can be installed").build()); + public static CheckDescription RANGER_SERVICE_AUDIT_DB_CHECK = new CheckDescription("RANGER_SERVICE_AUDIT_DB_CHECK", PrereqCheckType.SERVICE, "Remove the Ranger Audit to Database Capability", http://git-wip-us.apache.org/repos/asf/ambari/blob/bb803fb3/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicePresenceCheck.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicePresenceCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicePresenceCheck.java new file mode 100644 index 0000000..0f4eeb1 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServicePresenceCheck.java @@ -0,0 +1,177 @@ +/** + * 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.checks; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.controller.PrereqCheckRequest; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.apache.ambari.server.state.stack.UpgradePack.PrerequisiteCheckConfig; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.Singleton; + +/** + * Checks if Atlas service is present. Upgrade to stack HDP 2.5 can't pursuit + * with existed on the cluster Atlas service. + */ +@Singleton +@UpgradeCheck(group = UpgradeCheckGroup.DEFAULT) +public class ServicePresenceCheck extends AbstractCheckDescriptor{ + + private static final Logger LOG = LoggerFactory.getLogger(ServicePresenceCheck.class); + + static final String KEY_SERVICE_REMOVED = "servcie_removed"; + /* + * List of services that do not support upgrade + * services must be removed before the stack upgrade + * */ + static final String NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME = "no-upgrade-support-service-names"; + + /* + * List of services removed from the new release + * */ + static final String REMOVED_SERVICES_PROPERTY_NAME = "removed-service-names"; + + /* + * Such as Spark to Spark2 + */ + static final String NEW_SERVICES_PROPERTY_NAME = "new-service-names"; + + public ServicePresenceCheck(){ + super(CheckDescription.SERVICE_PRESENCE_CHECK); + } + + @Override + public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request) throws AmbariException { + final Cluster cluster = clustersProvider.get().getCluster(request.getClusterName()); + Set installedServices = cluster.getServices().keySet(); + + List noUpgradeSupportServices = getNoUpgradeSupportServices(request); + Map removedServices = getRemovedServices(request); + List failReasons = new ArrayList<>(); + + if(null != noUpgradeSupportServices && !noUpgradeSupportServices.isEmpty()){ + String reason = getFailReason(prerequisiteCheck, request); + for(String service: noUpgradeSupportServices){ + if (installedServices.contains(service.toUpperCase())){ + prerequisiteCheck.getFailedOn().add(service); + String msg = String.format(reason, service, service); + failReasons.add(msg); + } + } + } + if(null != removedServices){ + String reason = getFailReason(KEY_SERVICE_REMOVED, prerequisiteCheck, request); + for (Map.Entry entry : removedServices.entrySet()) { + String removedService = entry.getKey(); + if(installedServices.contains(removedService.toUpperCase())){ + prerequisiteCheck.getFailedOn().add(removedService); + String newService = entry.getValue(); + String msg = String.format(reason, removedService, newService); + failReasons.add(msg); + } + } + } + if(!failReasons.isEmpty()){ + prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL); + prerequisiteCheck.setFailReason(StringUtils.join(failReasons, '\n')); + } + } + + /** + * Obtain property value specified in the upgrade XML + * @return service name + * */ + private String getPropertyValue(PrereqCheckRequest request, String propertyKey){ + String value = null; + PrerequisiteCheckConfig prerequisiteCheckConfig = request.getPrerequisiteCheckConfig(); + Map checkProperties = null; + if(prerequisiteCheckConfig != null) { + checkProperties = prerequisiteCheckConfig.getCheckProperties(this.getClass().getName()); + } + if(checkProperties != null && checkProperties.containsKey(propertyKey)) { + value = checkProperties.get(propertyKey); + } + return value; + } + + /** + * @return service names + * */ + private List getNoUpgradeSupportServices(PrereqCheckRequest request){ + String value = getPropertyValue(request, NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME); + if (null != value){ + String[] services = value.split(","); + List result = new ArrayList(); + for(String service: services){ + service = service.trim(); + if (!service.isEmpty()){ + result.add(service); + } + } + return result; + } else { + return null; + } + } + + /** + * @return service names and new service names map + * */ + private Map getRemovedServices(PrereqCheckRequest request) throws AmbariException{ + String value = getPropertyValue(request, REMOVED_SERVICES_PROPERTY_NAME); + String newValue = getPropertyValue(request, NEW_SERVICES_PROPERTY_NAME); + if(value == null && newValue == null){ + return null; //no need to check removed services as they are not specified in the upgrade xml file. + } else { + if (value == null || newValue == null){ + throw new AmbariException("Removed services must be paired with new services list."); + } else { + List oldServices = Arrays.asList(value.split(",")); + List newServices = Arrays.asList(newValue.split(",")); + if (oldServices.size() != newServices.size()){ + throw new AmbariException("Removed services must be paired with new services list."); + } else { + Map result = new LinkedHashMap(); + for (int i = 0; i < oldServices.size(); i++){ + String oldService = oldServices.get(i).trim(); + String newService = newServices.get(i).trim(); + if (oldService.isEmpty() || newService.isEmpty()) { + throw new AmbariException("Removed services must be paired with new services list."); + } else { + result.put(oldService, newService); + } + } + return result; + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/bb803fb3/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicePresenceCheckTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicePresenceCheckTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicePresenceCheckTest.java new file mode 100644 index 0000000..03b0e81 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/ServicePresenceCheckTest.java @@ -0,0 +1,217 @@ +/* + * 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.checks; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.ambari.server.controller.PrereqCheckRequest; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.Service; +import org.apache.ambari.server.state.stack.PrereqCheckStatus; +import org.apache.ambari.server.state.stack.PrerequisiteCheck; +import org.apache.ambari.server.state.stack.UpgradePack.PrerequisiteCheckConfig; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import com.google.inject.Provider; + +/** + * Tests for {@link ServicePresenceCheck} + */ +public class ServicePresenceCheckTest { + private final Clusters m_clusters = Mockito.mock(Clusters.class); + + private final ServicePresenceCheck m_check = new ServicePresenceCheck(); + + /** + * + */ + @Before + public void setup() { + m_check.clustersProvider = new Provider() { + + @Override + public Clusters get() { + return m_clusters; + } + }; + } + + @Test + public void testPerformPass() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + Map checkProperties = new HashMap(); + checkProperties.put(ServicePresenceCheck.NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME,"MyServiceOne, MyServiceTwo"); + checkProperties.put(ServicePresenceCheck.REMOVED_SERVICES_PROPERTY_NAME,"OldServiceOne, OldServiceTwo"); + checkProperties.put(ServicePresenceCheck.NEW_SERVICES_PROPERTY_NAME,"NewServiceOne, NewServiceTwo"); + + PrerequisiteCheckConfig prerequisiteCheckConfig = Mockito.mock(PrerequisiteCheckConfig.class); + Mockito.when(prerequisiteCheckConfig.getCheckProperties( + m_check.getClass().getName())).thenReturn(checkProperties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setRepositoryVersion("2.5.0.0"); + request.setPrerequisiteCheckConfig(prerequisiteCheckConfig); + + m_check.perform(check, request); + Assert.assertEquals(PrereqCheckStatus.PASS, check.getStatus()); + } + + @Test + public void testPerformHasNoUpgradeSupportServices() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + Map services = new HashMap(); + services.put("ATLAS", Mockito.mock(Service.class)); + Mockito.when(cluster.getServices()).thenReturn(services); + + Map checkProperties = new HashMap(); + checkProperties.put(ServicePresenceCheck.NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME,"Atlas, MyService"); + PrerequisiteCheckConfig prerequisiteCheckConfig = Mockito.mock(PrerequisiteCheckConfig.class); + Mockito.when(prerequisiteCheckConfig.getCheckProperties( + m_check.getClass().getName())).thenReturn(checkProperties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setPrerequisiteCheckConfig(prerequisiteCheckConfig); + + m_check.perform(check, request); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + } + + @Test + public void testPerformHasRemovedServices() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + Map services = new HashMap(); + services.put("ATLAS", Mockito.mock(Service.class)); + services.put("OLDSERVICE", Mockito.mock(Service.class)); + Mockito.when(cluster.getServices()).thenReturn(services); + + Map checkProperties = new HashMap(); + checkProperties.put(ServicePresenceCheck.REMOVED_SERVICES_PROPERTY_NAME,"Atlas, OldService"); + checkProperties.put(ServicePresenceCheck.NEW_SERVICES_PROPERTY_NAME,"Atlas2, NewService"); + + PrerequisiteCheckConfig prerequisiteCheckConfig = Mockito.mock(PrerequisiteCheckConfig.class); + Mockito.when(prerequisiteCheckConfig.getCheckProperties( + m_check.getClass().getName())).thenReturn(checkProperties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setPrerequisiteCheckConfig(prerequisiteCheckConfig); + + m_check.perform(check, request); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + } + + @Test + public void testPerformMixOne() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + Map services = new HashMap(); + services.put("ATLAS", Mockito.mock(Service.class)); + Mockito.when(cluster.getServices()).thenReturn(services); + + Map checkProperties = new HashMap(); + checkProperties.put(ServicePresenceCheck.NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME,"MyServiceOne, MyServiceTwo"); + checkProperties.put(ServicePresenceCheck.REMOVED_SERVICES_PROPERTY_NAME,"Atlas, OldService"); + checkProperties.put(ServicePresenceCheck.NEW_SERVICES_PROPERTY_NAME,"Atlas2, NewService"); + + PrerequisiteCheckConfig prerequisiteCheckConfig = Mockito.mock(PrerequisiteCheckConfig.class); + Mockito.when(prerequisiteCheckConfig.getCheckProperties( + m_check.getClass().getName())).thenReturn(checkProperties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setPrerequisiteCheckConfig(prerequisiteCheckConfig); + + m_check.perform(check, request); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + } + + @Test + public void testPerformMixTwo() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + Map services = new HashMap(); + services.put("OLDSERVICE", Mockito.mock(Service.class)); + Mockito.when(cluster.getServices()).thenReturn(services); + + Map checkProperties = new HashMap(); + checkProperties.put(ServicePresenceCheck.NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME,"Atlas, MyService"); + checkProperties.put(ServicePresenceCheck.REMOVED_SERVICES_PROPERTY_NAME,"OldService"); + checkProperties.put(ServicePresenceCheck.NEW_SERVICES_PROPERTY_NAME,"NewService"); + + PrerequisiteCheckConfig prerequisiteCheckConfig = Mockito.mock(PrerequisiteCheckConfig.class); + Mockito.when(prerequisiteCheckConfig.getCheckProperties( + m_check.getClass().getName())).thenReturn(checkProperties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setPrerequisiteCheckConfig(prerequisiteCheckConfig); + + m_check.perform(check, request); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + } + + @Test + public void testPerformMixThree() throws Exception { + final Cluster cluster = Mockito.mock(Cluster.class); + Mockito.when(cluster.getClusterId()).thenReturn(1L); + Mockito.when(m_clusters.getCluster("cluster")).thenReturn(cluster); + + Map services = new HashMap(); + services.put("ATLAS", Mockito.mock(Service.class)); + services.put("HDFS", Mockito.mock(Service.class)); + services.put("STORM", Mockito.mock(Service.class)); + services.put("RANGER", Mockito.mock(Service.class)); + Mockito.when(cluster.getServices()).thenReturn(services); + + Map checkProperties = new HashMap(); + checkProperties.put(ServicePresenceCheck.NO_UPGRADE_SUPPORT_SERVICES_PROPERTY_NAME,"Atlas, HDFS"); + checkProperties.put(ServicePresenceCheck.REMOVED_SERVICES_PROPERTY_NAME,"Storm, Ranger"); + checkProperties.put(ServicePresenceCheck.NEW_SERVICES_PROPERTY_NAME,"Storm2, Ranger2"); + + PrerequisiteCheckConfig prerequisiteCheckConfig = Mockito.mock(PrerequisiteCheckConfig.class); + Mockito.when(prerequisiteCheckConfig.getCheckProperties( + m_check.getClass().getName())).thenReturn(checkProperties); + + PrerequisiteCheck check = new PrerequisiteCheck(null, null); + PrereqCheckRequest request = new PrereqCheckRequest("cluster"); + request.setPrerequisiteCheckConfig(prerequisiteCheckConfig); + + m_check.perform(check, request); + Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus()); + } +}