You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by vb...@apache.org on 2015/10/27 12:25:43 UTC
ambari git commit: AMBARI-13507. Create a script to change host names
for a stopped cluster.(vbrodetskyi)
Repository: ambari
Updated Branches:
refs/heads/branch-2.1 961b9d103 -> 5491d2aeb
AMBARI-13507. Create a script to change host names for a stopped cluster.(vbrodetskyi)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/5491d2ae
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/5491d2ae
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/5491d2ae
Branch: refs/heads/branch-2.1
Commit: 5491d2aebae14387601a8002f3cb8e28e4952ef7
Parents: 961b9d1
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Tue Oct 27 13:22:10 2015 +0200
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Tue Oct 27 13:22:10 2015 +0200
----------------------------------------------------------------------
ambari-server/sbin/ambari-server | 6 +-
.../server/configuration/Configuration.java | 57 +-
.../ambari/server/update/HostUpdateHelper.java | 546 +++++++++++++++++++
ambari-server/src/main/python/ambari-server.py | 8 +-
.../src/main/python/ambari_server/hostUpdate.py | 105 ++++
.../main/python/ambari_server/setupActions.py | 1 +
6 files changed, 705 insertions(+), 18 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/5491d2ae/ambari-server/sbin/ambari-server
----------------------------------------------------------------------
diff --git a/ambari-server/sbin/ambari-server b/ambari-server/sbin/ambari-server
index 1843cd6..490d54d 100755
--- a/ambari-server/sbin/ambari-server
+++ b/ambari-server/sbin/ambari-server
@@ -144,9 +144,13 @@ case "$1" in
echo -e "Restoring Ambari File System state"
$PYTHON /usr/sbin/ambari-server.py $@
;;
+ update-host-names)
+ echo -e "Updating host names"
+ $PYTHON /usr/sbin/ambari-server.py $@
+ ;;
*)
echo "Usage: /usr/sbin/ambari-server
- {start|stop|restart|setup|setup-jce|upgrade|status|upgradestack|setup-ldap|sync-ldap|set-current|setup-security|refresh-stack-hash|backup|restore} [options]
+ {start|stop|restart|setup|setup-jce|upgrade|status|upgradestack|setup-ldap|sync-ldap|set-current|setup-security|refresh-stack-hash|backup|restore|update-host-names} [options]
Use usr/sbin/ambari-server <action> --help to get details on options available.
Or, simply invoke ambari-server.py --help to print the options."
exit 1
http://git-wip-us.apache.org/repos/asf/ambari/blob/5491d2ae/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
index 04ab1ef..e97a54e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java
@@ -17,18 +17,11 @@
*/
package org.apache.ambari.server.configuration;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Properties;
-
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
import org.apache.ambari.annotations.Experimental;
import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.actionmanager.Stage;
@@ -47,8 +40,18 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
/**
@@ -487,6 +490,7 @@ public class Configuration {
Configuration.class);
private Properties properties;
+ private JsonObject hostChangesJson;
private Map<String, String> configsMap;
private Map<String, String> agentConfigsMap;
private CredentialProvider credentialProvider = null;
@@ -834,6 +838,31 @@ public class Configuration {
return properties;
}
+ public JsonObject getHostChangesJson(String hostChangesFile) {
+ if (hostChangesJson == null) {
+ hostChangesJson = readFileToJSON(hostChangesFile);
+ }
+ return hostChangesJson;
+ }
+
+ private JsonObject readFileToJSON (String file) {
+
+ // Read from File to String
+ JsonObject jsonObject = new JsonObject();
+
+ try {
+ JsonParser parser = new JsonParser();
+ JsonElement jsonElement = parser.parse(new FileReader(file));
+ jsonObject = jsonElement.getAsJsonObject();
+ } catch (FileNotFoundException e) {
+ throw new IllegalArgumentException("No file " + file, e);
+ } catch (IOException ioe){
+ throw new IllegalArgumentException("Can't read file " + file, ioe);
+ }
+
+ return jsonObject;
+ }
+
/**
* Get the views directory.
*
http://git-wip-us.apache.org/repos/asf/ambari/blob/5491d2ae/ambari-server/src/main/java/org/apache/ambari/server/update/HostUpdateHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/update/HostUpdateHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/update/HostUpdateHelper.java
new file mode 100644
index 0000000..672cd4e
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/update/HostUpdateHelper.java
@@ -0,0 +1,546 @@
+/*
+ * 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.update;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.inject.Guice;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+import com.google.inject.persist.PersistService;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.configuration.Configuration;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.ControllerModule;
+import org.apache.ambari.server.controller.KerberosHelper;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
+import org.apache.ambari.server.orm.dao.AlertsDAO;
+import org.apache.ambari.server.orm.dao.ClusterDAO;
+import org.apache.ambari.server.orm.dao.HostDAO;
+import org.apache.ambari.server.orm.dao.TopologyHostGroupDAO;
+import org.apache.ambari.server.orm.dao.TopologyHostRequestDAO;
+import org.apache.ambari.server.orm.dao.TopologyRequestDAO;
+import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+import org.apache.ambari.server.orm.entities.ClusterConfigEntity;
+import org.apache.ambari.server.orm.entities.ClusterEntity;
+import org.apache.ambari.server.orm.entities.HostEntity;
+import org.apache.ambari.server.orm.entities.TopologyHostGroupEntity;
+import org.apache.ambari.server.orm.entities.TopologyHostInfoEntity;
+import org.apache.ambari.server.orm.entities.TopologyHostRequestEntity;
+import org.apache.ambari.server.orm.entities.TopologyLogicalRequestEntity;
+import org.apache.ambari.server.orm.entities.TopologyRequestEntity;
+import org.apache.ambari.server.state.Cluster;
+import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.Config;
+import org.apache.ambari.server.state.ConfigHelper;
+import org.apache.ambari.server.state.ConfigImpl;
+import org.apache.ambari.server.state.Host;
+import org.apache.ambari.server.utils.EventBusSynchronizer;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/*
+* Class for host names update.
+* Can be used by command "ambari-server update-host-names /hosts_changes.json"
+*
+* Simple example of hosts_changes.json
+* {
+* "cluster1" : {
+* "c6400.ambari.apache.org" : "c6411.ambari.apache.org"
+* }
+* }
+*
+*/
+public class HostUpdateHelper {
+ private static final Logger LOG = LoggerFactory.getLogger
+ (HostUpdateHelper.class);
+
+ private static final String AUTHENTICATED_USER_NAME = "ambari-host-update";
+
+
+ private PersistService persistService;
+ private Configuration configuration;
+ private Injector injector;
+
+ protected String hostChangesFile;
+ protected Map<String, Map<String, String>> hostChangesFileMap;
+
+
+ @Inject
+ public HostUpdateHelper(PersistService persistService,
+ Configuration configuration,
+ Injector injector) {
+ this.persistService = persistService;
+ this.configuration = configuration;
+ this.injector = injector;
+ }
+
+ public void startPersistenceService() {
+ persistService.start();
+ }
+
+ public void stopPersistenceService() {
+ persistService.stop();
+ }
+
+ public String getHostChangesFile() {
+ return hostChangesFile;
+ }
+
+ public void setHostChangesFile(String hostChangesFile) {
+ this.hostChangesFile = hostChangesFile;
+ }
+
+ /**
+ * Extension of main controller module
+ */
+ public static class UpdateHelperModule extends ControllerModule {
+
+ public UpdateHelperModule() throws Exception {
+ }
+
+ @Override
+ protected void configure() {
+ super.configure();
+ EventBusSynchronizer.synchronizeAmbariEventPublisher(binder());
+ }
+ }
+
+ /*
+ * Method which validates json with host changes.
+ * Check cluster and hosts existence.
+ * Check on valid structure of json.
+ * */
+ private void validateHostChanges() throws AmbariException {
+ if (hostChangesFileMap == null && hostChangesFileMap.isEmpty()) {
+ throw new AmbariException(String.format("File with host names changes is null or empty"));
+ }
+
+ AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+ Clusters clusters = ambariManagementController.getClusters();
+
+ if (clusters != null) {
+
+ for (Map.Entry<String, Map<String, String>> clusterHosts : hostChangesFileMap.entrySet()) {
+ String clusterName = clusterHosts.getKey();
+ Cluster cluster = clusters.getCluster(clusterName);
+
+ if (cluster != null) {
+ Collection<Host> hosts = cluster.getHosts();
+ List<String> invalidHostNames = new ArrayList<>();
+ List<String> hostNames = new ArrayList<>();
+
+ for (Host host : hosts) {
+ hostNames.add(host.getHostName());
+ }
+
+ for (Map.Entry<String,String> hostPair : clusterHosts.getValue().entrySet()) {
+ if (!hostNames.contains(hostPair.getKey())) {
+ invalidHostNames.add(hostPair.getKey());
+ }
+ }
+
+ if (!invalidHostNames.isEmpty()) {
+ throw new AmbariException(String.format("Hostname(s): %s was(were) not found.", StringUtils.join(invalidHostNames, ", ")));
+ }
+ } else {
+ throw new AmbariException(String.format("Cluster %s was not found.", clusterName));
+ }
+ }
+ }
+ }
+
+ /*
+ * Method updates all properties in all configs,
+ * which value contains hostname that should be updated
+ * */
+ private void updateHostsInConfigurations() throws AmbariException {
+ ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+ AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+ Clusters clusters = ambariManagementController.getClusters();
+ ConfigHelper configHelper = injector.getInstance(ConfigHelper.class);
+
+ if (clusters != null) {
+
+ // going through all clusters with host pairs from file
+ for (Map.Entry<String, Map<String,String>> clusterHosts : hostChangesFileMap.entrySet()) {
+ String clusterName = clusterHosts.getKey();
+ ClusterEntity clusterEntity = clusterDAO.findByName(clusterName);
+ Cluster cluster = clusters.getCluster(clusterName);
+ Map<String, String> hostMapping = clusterHosts.getValue();
+ List<String> currentHostNames = new ArrayList<>();
+ String updatedPropertyValue;
+
+ for (Map.Entry<String, String> hostPair : hostMapping.entrySet()) {
+ currentHostNames.add(hostPair.getKey());
+ }
+
+ //******************************
+
+ if (clusterEntity != null) {
+ Collection<ClusterConfigEntity> clusterConfigEntities = clusterEntity.getClusterConfigEntities();
+ boolean configUpdated;
+
+ // going through all cluster configs and update property values
+ for (ClusterConfigEntity clusterConfigEntity : clusterConfigEntities) {
+ ConfigImpl config = new ConfigImpl(cluster, clusterConfigEntity, injector);
+ configUpdated = false;
+
+ for (Map.Entry<String,String> property : config.getProperties().entrySet()) {
+
+ updatedPropertyValue = replaceHosts(property.getValue(), currentHostNames, hostMapping);
+
+ if (updatedPropertyValue != null) {
+ Map<String,String> propertiesWithUpdates = config.getProperties();
+ propertiesWithUpdates.put(property.getKey(), updatedPropertyValue);
+ config.setProperties(propertiesWithUpdates);
+ configUpdated = true;
+ }
+ }
+ if (configUpdated) {
+ config.persist(false);
+ }
+ }
+ }
+
+ //******************************
+ }
+ }
+ }
+
+ private String replaceHosts(String propertyValue, List<String> currentHostNames, Map<String,String> hostMapping) {
+ List<String> currentHostNamesWhichPropertyValueIncludes = new ArrayList<>();
+ List<String> hostListForReplace = new ArrayList<>();
+ String updatedPropertyValue = null;
+
+ currentHostNamesWhichPropertyValueIncludes = getHostNamesWhichValueIncludes(currentHostNames, propertyValue);
+
+ if (!currentHostNamesWhichPropertyValueIncludes.isEmpty() && hostMapping != null) {
+ // filter current hosts which are included in other hosts
+ hostListForReplace = filterHostNamesIncludedInOtherHostNames(currentHostNamesWhichPropertyValueIncludes);
+
+ updatedPropertyValue = propertyValue;
+ // create map with replace codes, it will help us to replace every hostname only once
+ // replace hosts in value with codes
+ Map<String, String> hostNameCode = new HashMap<>();
+ int counter = 0;
+ for (String hostName : hostListForReplace) {
+ String code = String.format("{replace_code_%d}", counter++);
+ hostNameCode.put(hostName, code);
+ updatedPropertyValue = updatedPropertyValue.replace(hostName, code);
+ }
+
+ // replace codes with new host names according to ald host names
+ for (String hostName : hostListForReplace) {
+ updatedPropertyValue = updatedPropertyValue.replace(hostNameCode.get(hostName), hostMapping.get(hostName));
+ }
+
+ }
+
+ return updatedPropertyValue;
+ }
+
+
+ /*
+ * Method return host names which are included in value
+ * */
+ private List<String> getHostNamesWhichValueIncludes(List<String> hostNames, String value) {
+ List<String> includedHostNames = new ArrayList<>();
+
+ if (value != null && hostNames != null && !value.isEmpty()) {
+ for (String host : hostNames) {
+ if (value.contains(host)) {
+ includedHostNames.add(host);
+ }
+ }
+ }
+
+ return includedHostNames;
+ }
+
+ /*
+ * Method returns filtered list of host names
+ * which are not includes each other
+ * */
+ private List<String> filterHostNamesIncludedInOtherHostNames(List<String> hostNames) {
+ if (hostNames != null && !hostNames.isEmpty()) {
+ int includeCounter;
+ List<String> hostNamesToExclude = new ArrayList<>();
+ for (String hostNameToCheck : hostNames) {
+ includeCounter = 0;
+ for (String hostName : hostNames) {
+ if (StringUtils.contains(hostName, hostNameToCheck)) {
+ includeCounter++;
+ }
+ }
+ if (includeCounter > 1) {
+ hostNamesToExclude.add(hostNameToCheck);
+ }
+ }
+
+ hostNames.removeAll(hostNamesToExclude);
+ return hostNames;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ /*
+ * Method check if security enabled for clusters from file.
+ * If enabled for someone, then we will throw exception
+ * and put message to log.
+ * */
+ private void checkForSecurity() throws AmbariException {
+ AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+ Clusters clusters = ambariManagementController.getClusters();
+ List<String> clustersInSecure = new ArrayList<>();
+
+ if (clusters != null) {
+ for (String clusterName : hostChangesFileMap.keySet()) {
+ Cluster cluster = clusters.getCluster(clusterName);
+ Config clusterEnv = cluster.getDesiredConfigByType(ConfigHelper.CLUSTER_ENV);
+ if (clusterEnv != null) {
+ String securityEnabled = clusterEnv.getProperties().get(KerberosHelper.SECURITY_ENABLED_PROPERTY_NAME);
+ if (securityEnabled.toLowerCase().equals("true")) {
+ clustersInSecure.add(clusterName);
+ }
+ }
+ }
+
+ if (!clustersInSecure.isEmpty()) {
+ throw new AmbariException(String.format("Cluster(s) %s from file, is(are) in secure mode. Please, turn off security mode.",
+ StringUtils.join(clustersInSecure, ", ")));
+ }
+ }
+
+ }
+
+ /*
+ * Method initialize Map with json data from file
+ * */
+ private void initHostChangesFileMap() throws AmbariException {
+ JsonObject hostChangesJsonObject = configuration.getHostChangesJson(hostChangesFile);
+ hostChangesFileMap = new HashMap<>();
+
+ for (Map.Entry<String, JsonElement> clusterEntry : hostChangesJsonObject.entrySet()) {
+ try {
+ Gson gson = new Gson();
+ hostChangesFileMap.put(clusterEntry.getKey(), gson.fromJson(clusterEntry.getValue(), Map.class));
+ } catch(Exception e) {
+ throw new AmbariException("Error occurred during mapping Json to Map structure. Please check json structure in file.", e);
+ }
+ }
+ }
+
+ /*
+ * Method updates host names in db for hosts table..
+ * */
+ private void updateHostsInDB() {
+ ClusterDAO clusterDAO = injector.getInstance(ClusterDAO.class);
+ HostDAO hostDAO = injector.getInstance(HostDAO.class);
+
+ for (Map.Entry<String, Map<String,String>> clusterHosts : hostChangesFileMap.entrySet()) {
+ String clusterName = clusterHosts.getKey();
+ Map<String, String> hostMapping = clusterHosts.getValue();
+ ClusterEntity clusterEntity = clusterDAO.findByName(clusterName);
+ List<String> currentHostNames = new ArrayList<>();
+
+ for (Map.Entry<String, String> hostPair : hostMapping.entrySet()) {
+ currentHostNames.add(hostPair.getKey());
+ }
+
+ if (clusterEntity != null) {
+ Collection<HostEntity> hostEntities = clusterEntity.getHostEntities();
+ for (HostEntity hostEntity : hostEntities) {
+ if (currentHostNames.contains(hostEntity.getHostName())) {
+ hostEntity.setHostName(hostMapping.get(hostEntity.getHostName()));
+ hostDAO.merge(hostEntity);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Method updates Current Alerts host name and
+ * regenerates hash for alert definitions(for alerts to be recreated)
+ * */
+ private void updateHostsForAlertsInDB() {
+ AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+ AlertsDAO alertsDAO = injector.getInstance(AlertsDAO.class);
+ AlertDefinitionDAO alertDefinitionDAO = injector.getInstance(AlertDefinitionDAO.class);
+ Clusters clusters = ambariManagementController.getClusters();
+
+ if (clusters != null) {
+ Map<String, Cluster> clusterMap = clusters.getClusters();
+
+ if (clusterMap != null) {
+
+ for (Map.Entry<String, Map<String,String>> clusterHosts : hostChangesFileMap.entrySet()) {
+ List<String> currentHostNames = new ArrayList<>();
+ Map<String, String> hostMapping = clusterHosts.getValue();
+ Long clusterId = clusterMap.get(clusterHosts.getKey()).getClusterId();
+
+ for (Map.Entry<String, String> hostPair : hostMapping.entrySet()) {
+ currentHostNames.add(hostPair.getKey());
+ }
+
+ List<AlertCurrentEntity> currentEntities = alertsDAO.findCurrentByCluster(clusterId);
+ for (AlertCurrentEntity alertCurrentEntity : currentEntities) {
+ AlertHistoryEntity alertHistoryEntity = alertCurrentEntity.getAlertHistory();
+ if (currentHostNames.contains(alertHistoryEntity.getHostName())) {
+ alertHistoryEntity.setHostName(hostMapping.get(alertHistoryEntity.getHostName()));
+ alertsDAO.merge(alertHistoryEntity);
+ }
+ }
+
+ List<AlertDefinitionEntity> alertDefinitionEntities = alertDefinitionDAO.findAll(clusterId);
+ for (AlertDefinitionEntity alertDefinitionEntity : alertDefinitionEntities) {
+ alertDefinitionEntity.setHash(UUID.randomUUID().toString());
+ alertDefinitionDAO.merge(alertDefinitionEntity);
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Method updates hosts for Topology Requests (Blue Prints logic)
+ * */
+ private void updateHostsForTopologyRequests() {
+ AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class);
+ TopologyRequestDAO topologyRequestDAO = injector.getInstance(TopologyRequestDAO.class);
+ TopologyHostRequestDAO topologyHostRequestDAO = injector.getInstance(TopologyHostRequestDAO.class);
+ TopologyHostGroupDAO topologyHostGroupDAO = injector.getInstance(TopologyHostGroupDAO.class);
+ Clusters clusters = ambariManagementController.getClusters();
+
+ if (clusters != null) {
+ Map<String, Cluster> clusterMap = clusters.getClusters();
+
+ if (clusterMap != null) {
+
+ for (Map.Entry<String, Map<String, String>> clusterHosts : hostChangesFileMap.entrySet()) {
+ Long clusterId = clusterMap.get(clusterHosts.getKey()).getClusterId();
+ List<TopologyRequestEntity> topologyRequestEntities = topologyRequestDAO.findByClusterId(clusterId);
+ List<String> currentHostNames = new ArrayList<>();
+ Map<String, String> hostMapping = clusterHosts.getValue();
+
+ for (Map.Entry<String, String> hostPair : hostMapping.entrySet()) {
+ currentHostNames.add(hostPair.getKey());
+ }
+
+ for (TopologyRequestEntity topologyRequestEntity : topologyRequestEntities) {
+ TopologyLogicalRequestEntity topologyLogicalRequestEntity = topologyRequestEntity.getTopologyLogicalRequestEntity();
+ Collection<TopologyHostGroupEntity> topologyHostGroupEntities = topologyRequestEntity.getTopologyHostGroupEntities();
+
+ // update topology host infos
+ if (topologyHostGroupEntities != null) {
+ for (TopologyHostGroupEntity topologyHostGroupEntity : topologyHostGroupEntities) {
+ Collection<TopologyHostInfoEntity> topologyHostInfoEntities = topologyHostGroupEntity.getTopologyHostInfoEntities();
+ boolean updatesAvailable = false;
+
+ if (topologyHostGroupEntities != null) {
+ for (TopologyHostInfoEntity topologyHostInfoEntity : topologyHostInfoEntities) {
+ if (currentHostNames.contains(topologyHostInfoEntity.getFqdn())) {
+ topologyHostInfoEntity.setFqdn(hostMapping.get(topologyHostInfoEntity.getFqdn()));
+ updatesAvailable = true;
+ }
+ }
+ }
+ if (updatesAvailable) {
+ topologyHostGroupDAO.merge(topologyHostGroupEntity);
+ }
+ }
+ }
+
+ // update topology host requests
+ if (topologyLogicalRequestEntity != null) {
+ Collection<TopologyHostRequestEntity> topologyHostRequestEntities = topologyLogicalRequestEntity.getTopologyHostRequestEntities();
+
+ if (topologyHostRequestEntities != null) {
+ for (TopologyHostRequestEntity topologyHostRequestEntity : topologyHostRequestEntities) {
+ if (currentHostNames.contains(topologyHostRequestEntity.getHostName())) {
+ topologyHostRequestEntity.setHostName(hostMapping.get(topologyHostRequestEntity.getHostName()));
+ topologyHostRequestDAO.merge(topologyHostRequestEntity);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ try {
+ LOG.info("Host names update started.");
+
+ String hostChangesFile = args[0];
+
+ if (hostChangesFile == null || hostChangesFile.isEmpty()) {
+ throw new AmbariException("Path to file with host names changes is empty or null.");
+ }
+
+ Injector injector = Guice.createInjector(new UpdateHelperModule());
+ HostUpdateHelper hostUpdateHelper = injector.getInstance(HostUpdateHelper.class);
+
+ hostUpdateHelper.setHostChangesFile(hostChangesFile);
+
+ hostUpdateHelper.initHostChangesFileMap();
+
+ hostUpdateHelper.startPersistenceService();
+
+ hostUpdateHelper.validateHostChanges();
+
+ hostUpdateHelper.checkForSecurity();
+
+ hostUpdateHelper.updateHostsInDB();
+
+ hostUpdateHelper.updateHostsForTopologyRequests();
+
+ hostUpdateHelper.updateHostsForAlertsInDB();
+
+ hostUpdateHelper.updateHostsInConfigurations();
+
+ LOG.info("Host names update completed successfully.");
+
+ hostUpdateHelper.stopPersistenceService();
+ } catch (Throwable e) {
+ if (e instanceof AmbariException) {
+ LOG.error("Exception occurred during host names update, failed", e);
+ throw (AmbariException)e;
+ }else{
+ LOG.error("Unexpected error, host names update failed", e);
+ throw new Exception("Unexpected error, host names update failed", e);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/5491d2ae/ambari-server/src/main/python/ambari-server.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari-server.py b/ambari-server/src/main/python/ambari-server.py
index 88df81a..2963322 100755
--- a/ambari-server/src/main/python/ambari-server.py
+++ b/ambari-server/src/main/python/ambari-server.py
@@ -36,10 +36,11 @@ from ambari_server.serverUtils import is_server_runing, refresh_stack_hash
from ambari_server.serverSetup import reset, setup, setup_jce_policy
from ambari_server.serverUpgrade import upgrade, upgrade_stack, set_current
from ambari_server.setupHttps import setup_https, setup_truststore
+from ambari_server.hostUpdate import update_host_names
from ambari_server.setupActions import BACKUP_ACTION, LDAP_SETUP_ACTION, LDAP_SYNC_ACTION, PSTART_ACTION, \
- REFRESH_STACK_HASH_ACTION, RESET_ACTION, RESTORE_ACTION, SETUP_ACTION, SETUP_SECURITY_ACTION, START_ACTION, \
- STATUS_ACTION, STOP_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION, SETUP_JCE_ACTION, SET_CURRENT_ACTION
+ REFRESH_STACK_HASH_ACTION, RESET_ACTION, RESTORE_ACTION, UPDATE_HOST_NAMES_ACTION, SETUP_ACTION, SETUP_SECURITY_ACTION, \
+ START_ACTION, STATUS_ACTION, STOP_ACTION, UPGRADE_ACTION, UPGRADE_STACK_ACTION, SETUP_JCE_ACTION, SET_CURRENT_ACTION
from ambari_server.setupSecurity import setup_ldap, sync_ldap, setup_master_key, setup_ambari_krb5_jaas
from ambari_server.userInput import get_validated_string_input
@@ -516,7 +517,8 @@ def create_user_action_map(args, options):
SETUP_SECURITY_ACTION: UserActionRestart(setup_security, options),
REFRESH_STACK_HASH_ACTION: UserAction(refresh_stack_hash_action),
BACKUP_ACTION: UserActionPossibleArgs(backup, [1, 2], args),
- RESTORE_ACTION: UserActionPossibleArgs(restore, [1, 2], args)
+ RESTORE_ACTION: UserActionPossibleArgs(restore, [1, 2], args),
+ UPDATE_HOST_NAMES_ACTION: UserActionPossibleArgs(update_host_names, [2], args, options)
}
return action_map
http://git-wip-us.apache.org/repos/asf/ambari/blob/5491d2ae/ambari-server/src/main/python/ambari_server/hostUpdate.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/hostUpdate.py b/ambari-server/src/main/python/ambari_server/hostUpdate.py
new file mode 100644
index 0000000..bfd6651
--- /dev/null
+++ b/ambari-server/src/main/python/ambari_server/hostUpdate.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+
+'''
+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.
+'''
+
+import os
+import sys
+
+from ambari_commons.exceptions import FatalException
+from ambari_server.serverConfiguration import configDefaults, get_java_exe_path, get_ambari_properties, read_ambari_user, \
+ parse_properties_file, JDBC_DATABASE_PROPERTY
+from ambari_commons.logging_utils import print_info_msg, print_warning_msg, print_error_msg
+from ambari_server.dbConfiguration import ensure_jdbc_driver_is_installed, LINUX_DBMS_KEYS_LIST
+from ambari_server.serverClassPath import ServerClassPath
+from ambari_server.setupSecurity import ensure_can_start_under_current_user, generate_env
+from ambari_commons.os_utils import run_os_command
+from ambari_server.serverUtils import is_server_runing
+from ambari_server.userInput import get_YN_input
+
+HOST_UPDATE_HELPER_CMD = "{0} -cp {1} " + \
+ "org.apache.ambari.server.update.HostUpdateHelper {2}" + \
+ " > " + configDefaults.SERVER_OUT_FILE + " 2>&1"
+
+def update_host_names(args, options):
+ services_stopped = get_YN_input("Please, confirm Ambari services are stopped [y/n] (n)? ", False)
+ if not services_stopped:
+ print 'Exiting...'
+ sys.exit(1)
+
+ pending_commands = get_YN_input("Please, confirm there are no pending commands on cluster [y/n] (n)? ", False)
+ if not pending_commands:
+ print 'Exiting...'
+ sys.exit(1)
+
+ db_backup_done = get_YN_input("Please, confirm you have made backup of the Ambari db [y/n] (n)? ", False)
+ if not db_backup_done:
+ print 'Exiting...'
+ sys.exit(1)
+
+ status, pid = is_server_runing()
+ if status:
+ raise FatalException(1, "Ambari Server should be stopped")
+
+ try:
+ host_mapping_file_path = args[1]
+ except IndexError:
+ #host_mapping file is mandatory
+ raise FatalException(1, "Invalid number of host update arguments. Probably, you forgot to add json file with "
+ "host changes.")
+
+ if not os.path.isfile(host_mapping_file_path):
+ raise FatalException(1, "Invalid file path or file doesn't exist")
+
+ if not os.access(host_mapping_file_path, os.R_OK):
+ raise FatalException(1, "File is not readable")
+
+ jdk_path = get_java_exe_path()
+
+ if jdk_path is None:
+ print_error_msg("No JDK found, please run the \"setup\" "
+ "command to install a JDK automatically or install any "
+ "JDK manually to " + configDefaults.JDK_INSTALL_DIR)
+ sys.exit(1)
+
+ properties = get_ambari_properties()
+ parse_properties_file(options)
+ options.database_index = LINUX_DBMS_KEYS_LIST.index(properties[JDBC_DATABASE_PROPERTY])
+
+ ensure_jdbc_driver_is_installed(options, get_ambari_properties())
+
+ serverClassPath = ServerClassPath(get_ambari_properties(), options)
+ class_path = serverClassPath.get_full_ambari_classpath_escaped_for_shell()
+
+ command = HOST_UPDATE_HELPER_CMD.format(jdk_path, class_path, host_mapping_file_path)
+
+ ambari_user = read_ambari_user()
+ current_user = ensure_can_start_under_current_user(ambari_user)
+ environ = generate_env(options, ambari_user, current_user)
+
+ (retcode, stdout, stderr) = run_os_command(command, env=environ)
+ print_info_msg("Return code from update host names command, retcode = " + str(retcode))
+
+ if retcode > 0:
+ print_error_msg("Error executing update host names, please check the server logs.")
+ raise FatalException(1, 'Host names update failed.')
+ else:
+ print_info_msg('Host names update completed successfully')
+
+
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/5491d2ae/ambari-server/src/main/python/ambari_server/setupActions.py
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/python/ambari_server/setupActions.py b/ambari-server/src/main/python/ambari_server/setupActions.py
index 6c6e7ea..686ac9a 100644
--- a/ambari-server/src/main/python/ambari_server/setupActions.py
+++ b/ambari-server/src/main/python/ambari_server/setupActions.py
@@ -35,6 +35,7 @@ SET_CURRENT_ACTION = "set-current"
SETUP_GANGLIA_HTTPS_ACTION = "setup-ganglia-https"
ENCRYPT_PASSWORDS_ACTION = "encrypt-passwords"
SETUP_SECURITY_ACTION = "setup-security"
+UPDATE_HOST_NAMES_ACTION = "update-host-names"
BACKUP_ACTION = "backup"
RESTORE_ACTION = "restore"
SETUP_JCE_ACTION = "setup-jce"