blob: b94d50347e81189a4db2c32979ecfdbac3778df0 [file] [log] [blame]
/*
* 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.serveraction.upgrades;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.agent.CommandReport;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.orm.dao.HostVersionDAO;
import org.apache.ambari.server.orm.entities.HostVersionEntity;
import org.apache.ambari.server.orm.entities.RepositoryVersionEntity;
import org.apache.ambari.server.serveraction.ServerAction;
import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.RepositoryType;
import org.apache.ambari.server.state.RepositoryVersionState;
import org.apache.ambari.server.state.StackId;
import org.apache.ambari.server.state.UpgradeContext;
import org.apache.ambari.server.state.stack.upgrade.Direction;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
/**
* Action that represents updating the Desired Stack Id during the middle of a stack upgrade (typically NonRolling).
* In a {@link org.apache.ambari.server.state.stack.upgrade.UpgradeType#NON_ROLLING}, the effective Stack Id is
* actually changed half-way through calculating the Actions, and this serves to update the database to make it
* evident to the user at which point it changed.
*/
public class UpdateDesiredRepositoryAction extends AbstractUpgradeServerAction {
/**
* Logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(UpdateDesiredRepositoryAction.class);
/**
* The Ambari configuration.
*/
@Inject
private Configuration m_configuration;
/**
* Used for restting host version states on downgrade.
*/
@Inject
private HostVersionDAO m_hostVersionDAO;
/**
* {@inheritDoc}
*/
@Override
public CommandReport execute(ConcurrentMap<String, Object> requestSharedDataContext)
throws AmbariException, InterruptedException {
String clusterName = getExecutionCommand().getClusterName();
Cluster cluster = getClusters().getCluster(clusterName);
UpgradeContext upgradeContext = getUpgradeContext(cluster);
Map<String, String> roleParams = getExecutionCommand().getRoleParams();
// Make a best attempt at setting the username
String userName;
if (roleParams != null && roleParams.containsKey(ServerAction.ACTION_USER_NAME)) {
userName = roleParams.get(ServerAction.ACTION_USER_NAME);
} else {
userName = m_configuration.getAnonymousAuditName();
LOG.warn(String.format("Did not receive role parameter %s, will save configs using anonymous username %s", ServerAction.ACTION_USER_NAME, userName));
}
CommandReport commandReport = updateDesiredRepositoryVersion(cluster, upgradeContext, userName);
m_upgradeHelper.publishDesiredRepositoriesUpdates(upgradeContext);
return commandReport;
}
/**
* Sets the desired repository version for services participating in the
* upgrade.
*
* @param cluster
* the cluster
* @param upgradeContext
* the upgrade context
* @param userName
* username performing the action
* @return the command report to return
*/
@Transactional
CommandReport updateDesiredRepositoryVersion(
Cluster cluster, UpgradeContext upgradeContext, String userName)
throws AmbariException, InterruptedException {
StringBuilder out = new StringBuilder();
StringBuilder err = new StringBuilder();
try {
// the desired repository message to put in the command report - this will
// change based on the type of upgrade and the services participating
if (upgradeContext.getDirection() == Direction.UPGRADE) {
final String message;
RepositoryVersionEntity targetRepositoryVersion = upgradeContext.getRepositoryVersion();
if (upgradeContext.getOrchestrationType() == RepositoryType.STANDARD) {
message = MessageFormat.format(
"Updating the desired repository version to {0} for all cluster services.",
targetRepositoryVersion.getVersion());
} else {
Set<String> servicesInUpgrade = upgradeContext.getSupportedServices();
message = MessageFormat.format(
"Updating the desired repository version to {0} for the following services: {1}",
targetRepositoryVersion.getVersion(), StringUtils.join(servicesInUpgrade, ','));
}
out.append(message).append(System.lineSeparator());
// move the cluster's desired stack as well
StackId targetStackId = targetRepositoryVersion.getStackId();
cluster.setDesiredStackVersion(targetStackId);
}
if( upgradeContext.getDirection() == Direction.DOWNGRADE ){
String message = "Updating the desired repository back their original values for the following services:";
out.append(message).append(System.lineSeparator());
Map<String, RepositoryVersionEntity> targetVersionsByService = upgradeContext.getTargetVersions();
for (String serviceName : targetVersionsByService.keySet()) {
RepositoryVersionEntity repositoryVersion = targetVersionsByService.get(serviceName);
message = String.format(" %s to %s", serviceName, repositoryVersion.getVersion());
out.append(message).append(System.lineSeparator());
}
}
// move repositories to the right version and create/revert configs
m_upgradeHelper.updateDesiredRepositoriesAndConfigs(upgradeContext);
// a downgrade must force host versions back to INSTALLED for the
// repository which failed to be upgraded.
if (upgradeContext.getDirection() == Direction.DOWNGRADE) {
RepositoryVersionEntity downgradeFromRepositoryVersion = upgradeContext.getRepositoryVersion();
out.append(String.format("Setting host versions back to %s for repository version %s",
RepositoryVersionState.INSTALLED, downgradeFromRepositoryVersion.getVersion()));
List<HostVersionEntity> hostVersionsToReset = m_hostVersionDAO.findHostVersionByClusterAndRepository(
cluster.getClusterId(), downgradeFromRepositoryVersion);
for (HostVersionEntity hostVersion : hostVersionsToReset) {
if( hostVersion.getState() != RepositoryVersionState.NOT_REQUIRED ){
hostVersion.setState(RepositoryVersionState.INSTALLED);
}
}
// move the cluster's desired stack back to it's current stack on downgrade
StackId targetStackId = cluster.getCurrentStackVersion();
cluster.setDesiredStackVersion(targetStackId);
}
return createCommandReport(0, HostRoleStatus.COMPLETED, "{}", out.toString(), err.toString());
} catch (Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
err.append(sw);
return createCommandReport(-1, HostRoleStatus.FAILED, "{}", out.toString(), err.toString());
}
}
}