You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by dm...@apache.org on 2016/04/28 19:03:17 UTC
ambari git commit: AMBARI-16134. Force running service checks for
services before upgrade (dlysnichenko)
Repository: ambari
Updated Branches:
refs/heads/trunk 7cfcf6579 -> 1b49c6c97
AMBARI-16134. Force running service checks for services before upgrade (dlysnichenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/1b49c6c9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/1b49c6c9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/1b49c6c9
Branch: refs/heads/trunk
Commit: 1b49c6c97f3a38652b9b8231b7c65cec2c2a0a2e
Parents: 7cfcf65
Author: Lisnichenko Dmitro <dl...@hortonworks.com>
Authored: Thu Apr 28 20:01:29 2016 +0300
Committer: Lisnichenko Dmitro <dl...@hortonworks.com>
Committed: Thu Apr 28 20:01:29 2016 +0300
----------------------------------------------------------------------
.../ambari/server/checks/CheckDescription.java | 7 +
.../ambari/server/checks/HealthCheck.java | 6 +-
.../checks/ServiceCheckValidityCheck.java | 147 +++++++++++++++++++
.../checks/ServiceCheckValidityCheckTest.java | 125 ++++++++++++++++
4 files changed, 284 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/1b49c6c9/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 d701bdc..6b39082 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
@@ -54,6 +54,13 @@ public enum CheckDescription {
"The following issues have been detected on this cluster and should be addressed before upgrading: %s");
}}),
+ SERVICE_CHECK(PrereqCheckType.SERVICE,
+ "Last Service Check should be more recent than the last configuration change for the given service",
+ new HashMap<String, String>() {{
+ put(AbstractCheckDescriptor.DEFAULT,
+ "The following service configurations have been updated and their Service Checks should be run again: %s");
+ }}),
+
HOSTS_MAINTENANCE_MODE(PrereqCheckType.HOST,
"Hosts in Maintenance Mode will be excluded from the upgrade.",
new HashMap<String, String>() {{
http://git-wip-us.apache.org/repos/asf/ambari/blob/1b49c6c9/ambari-server/src/main/java/org/apache/ambari/server/checks/HealthCheck.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/HealthCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/HealthCheck.java
index a1ab1eb..b75e923 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/checks/HealthCheck.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/HealthCheck.java
@@ -83,7 +83,11 @@ public class HealthCheck extends AbstractCheckDescriptor {
String label = alertHistory.getAlertDefinition().getLabel();
String hostName = alertHistory.getHostName();
- errorMessages.add(state + ": " + label + ": " + hostName);
+ if (hostName == null) {
+ errorMessages.add(state + ": " + label);
+ } else {
+ errorMessages.add(state + ": " + label + ": " + hostName);
+ }
prerequisiteCheck.getFailedDetail().add(new AlertDetail(state, label, hostName));
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1b49c6c9/ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
new file mode 100644
index 0000000..8b39863
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/checks/ServiceCheckValidityCheck.java
@@ -0,0 +1,147 @@
+/*
+ * 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.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.RoleCommand;
+import org.apache.ambari.server.controller.PrereqCheckRequest;
+import org.apache.ambari.server.controller.internal.PageRequestImpl;
+import org.apache.ambari.server.controller.internal.RequestImpl;
+import org.apache.ambari.server.controller.spi.PageRequest;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.utilities.PredicateBuilder;
+import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
+import org.apache.ambari.server.orm.dao.ServiceConfigDAO;
+import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
+import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.MaintenanceState;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
+import org.apache.ambari.server.state.stack.PrereqCheckStatus;
+import org.apache.ambari.server.state.stack.PrerequisiteCheck;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+
+/**
+ * Checks that all Service Checks are less recent than last
+ * configuration update for given services.
+ * That is a potential problem when doing stack update.
+ */
+@Singleton
+@UpgradeCheck(group = UpgradeCheckGroup.DEFAULT, required = true)
+public class ServiceCheckValidityCheck extends AbstractCheckDescriptor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ServiceCheckValidityCheck.class);
+
+ private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
+ private static final PageRequestImpl PAGE_REQUEST = new PageRequestImpl(PageRequest.StartingPoint.End, 1000, 0, null, null);
+ private static final RequestImpl REQUEST = new RequestImpl(null, null, null, null, null, PAGE_REQUEST);
+
+
+ @Inject
+ Provider<ServiceConfigDAO> serviceConfigDAOProvider;
+
+ @Inject
+ Provider<HostRoleCommandDAO> hostRoleCommandDAOProvider;
+
+ /**
+ * Constructor.
+ */
+ public ServiceCheckValidityCheck() {
+ super(CheckDescription.SERVICE_CHECK);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void perform(PrerequisiteCheck prerequisiteCheck, PrereqCheckRequest request)
+ throws AmbariException {
+
+ ServiceConfigDAO serviceConfigDAO = serviceConfigDAOProvider.get();
+ HostRoleCommandDAO hostRoleCommandDAO = hostRoleCommandDAOProvider.get();
+
+ final String clusterName = request.getClusterName();
+ final Cluster cluster = clustersProvider.get().getCluster(clusterName);
+ long clusterId = cluster.getClusterId();
+
+ Map<String, Long> lastServiceConfigUpdates = new HashMap<>();
+
+ for (Service service : cluster.getServices().values()) {
+ if (service.getMaintenanceState() != MaintenanceState.OFF || !hasAtLeastOneComponentVersionAdvertised(service)) {
+ continue;
+ }
+ ServiceConfigEntity lastServiceConfig = serviceConfigDAO.getLastServiceConfig(clusterId, service.getName());
+ lastServiceConfigUpdates.put(service.getName(), lastServiceConfig.getCreateTimestamp());
+ }
+
+ List<HostRoleCommandEntity> commands = hostRoleCommandDAO.findAll(REQUEST, null);
+ Collections.reverse(commands);
+
+ LinkedHashSet<String> failedServiceNames = new LinkedHashSet<>();
+ for (Map.Entry<String, Long> serviceEntry : lastServiceConfigUpdates.entrySet()) {
+ String serviceName = serviceEntry.getKey();
+ Long configTimestamp = serviceEntry.getValue();
+ for (HostRoleCommandEntity command : commands) {
+ if (RoleCommand.SERVICE_CHECK.equals(command.getRoleCommand()) && command.getCommandDetail().contains(serviceName)) {
+ Long serviceCheckTimestamp = command.getStartTime();
+ if (serviceCheckTimestamp < configTimestamp) {
+ failedServiceNames.add(serviceName);
+ LOG.info("Service {} latest config change is {}, latest service check executed at {}",
+ serviceName,
+ DATE_FORMAT.format(new Date(configTimestamp)),
+ DATE_FORMAT.format(new Date(serviceCheckTimestamp))
+ );
+ }
+ }
+ }
+ }
+
+ if (!failedServiceNames.isEmpty()) {
+ prerequisiteCheck.setFailedOn(failedServiceNames);
+ prerequisiteCheck.setStatus(PrereqCheckStatus.FAIL);
+ String failReason = getFailReason(prerequisiteCheck, request);
+ prerequisiteCheck.setFailReason(String.format(failReason, StringUtils.join(failedServiceNames, ", ")));
+ }
+ }
+
+ private boolean hasAtLeastOneComponentVersionAdvertised(Service service) {
+ Collection<ServiceComponent> components = service.getServiceComponents().values();
+ for (ServiceComponent component : components) {
+ if (component.isVersionAdvertised()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/1b49c6c9/ambari-server/src/test/java/org/apache/ambari/server/checks/ServiceCheckValidityCheckTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/checks/ServiceCheckValidityCheckTest.java b/ambari-server/src/test/java/org/apache/ambari/server/checks/ServiceCheckValidityCheckTest.java
new file mode 100644
index 0000000..4a3ae5c
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/checks/ServiceCheckValidityCheckTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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 static java.util.Collections.singletonList;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.RoleCommand;
+import org.apache.ambari.server.controller.PrereqCheckRequest;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
+import org.apache.ambari.server.orm.dao.ServiceConfigDAO;
+import org.apache.ambari.server.orm.entities.HostRoleCommandEntity;
+import org.apache.ambari.server.orm.entities.ServiceConfigEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.MaintenanceState;
+import org.apache.ambari.server.state.Service;
+import org.apache.ambari.server.state.ServiceComponent;
+import org.apache.ambari.server.state.stack.PrereqCheckStatus;
+import org.apache.ambari.server.state.stack.PrerequisiteCheck;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Provider;
+
+public class ServiceCheckValidityCheckTest {
+ private static final String CLUSTER_NAME = "cluster1";
+ private static final long CLUSTER_ID = 1L;
+ private static final String SERVICE_NAME = "HDFS";
+ private static final long CONFIG_CREATE_TIMESTAMP = 1461518722202L;
+ private static final String COMMAND_DETAIL = "HDFS service check";
+ private static final long SERVICE_CHECK_START_TIME = CONFIG_CREATE_TIMESTAMP - 2000L;
+ private static final String SERVICE_COMPONENT_NAME = "service component";
+ private ServiceCheckValidityCheck serviceCheckValidityCheck;
+
+ private ServiceConfigDAO serviceConfigDAO;
+ private HostRoleCommandDAO hostRoleCommandDAO;
+ private Service service;
+
+
+ @Before
+ public void setUp() throws Exception {
+ final Clusters clusters = mock(Clusters.class);
+ service = mock(Service.class);
+ serviceConfigDAO = mock(ServiceConfigDAO.class);
+ hostRoleCommandDAO = mock(HostRoleCommandDAO.class);
+
+ serviceCheckValidityCheck = new ServiceCheckValidityCheck();
+ serviceCheckValidityCheck.hostRoleCommandDAOProvider = new Provider<HostRoleCommandDAO>() {
+ @Override
+ public HostRoleCommandDAO get() {
+ return hostRoleCommandDAO;
+ }
+ };
+ serviceCheckValidityCheck.serviceConfigDAOProvider = new Provider<ServiceConfigDAO>() {
+ @Override
+ public ServiceConfigDAO get() {
+ return serviceConfigDAO;
+ }
+ };
+ serviceCheckValidityCheck.clustersProvider = new Provider<Clusters>() {
+ @Override
+ public Clusters get() {
+ return clusters;
+ }
+ };
+
+ Cluster cluster = mock(Cluster.class);
+ when(clusters.getCluster(CLUSTER_NAME)).thenReturn(cluster);
+ when(cluster.getClusterId()).thenReturn(CLUSTER_ID);
+ when(cluster.getServices()).thenReturn(ImmutableMap.of(SERVICE_NAME, service));
+
+ when(service.getName()).thenReturn(SERVICE_NAME);
+
+ }
+
+ @Test
+ public void testFailWhenServiceWithOutdatedServiceCheckExists() throws AmbariException {
+ ServiceComponent serviceComponent = mock(ServiceComponent.class);
+ when(serviceComponent.isVersionAdvertised()).thenReturn(true);
+
+ when(service.getMaintenanceState()).thenReturn(MaintenanceState.OFF);
+ when(service.getServiceComponents()).thenReturn(ImmutableMap.of(SERVICE_COMPONENT_NAME, serviceComponent));
+
+ ServiceConfigEntity serviceConfigEntity = new ServiceConfigEntity();
+ serviceConfigEntity.setServiceName(SERVICE_NAME);
+ serviceConfigEntity.setCreateTimestamp(CONFIG_CREATE_TIMESTAMP);
+
+ HostRoleCommandEntity hostRoleCommandEntity = new HostRoleCommandEntity();
+ hostRoleCommandEntity.setRoleCommand(RoleCommand.SERVICE_CHECK);
+ hostRoleCommandEntity.setCommandDetail(COMMAND_DETAIL);
+ hostRoleCommandEntity.setStartTime(SERVICE_CHECK_START_TIME);
+
+ when(serviceConfigDAO.getLastServiceConfig(eq(CLUSTER_ID), eq(SERVICE_NAME))).thenReturn(serviceConfigEntity);
+ when(hostRoleCommandDAO.findAll(any(Request.class), isNull(Predicate.class))).thenReturn(singletonList(hostRoleCommandEntity));
+
+ PrerequisiteCheck check = new PrerequisiteCheck(null, CLUSTER_NAME);
+ serviceCheckValidityCheck.perform(check, new PrereqCheckRequest(CLUSTER_NAME));
+ Assert.assertEquals(PrereqCheckStatus.FAIL, check.getStatus());
+ }
+}
\ No newline at end of file