Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package org.apache.ambari.server.api.query.render;

import static java.util.stream.Collectors.toList;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
Expand All @@ -26,10 +28,12 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.apache.ambari.server.AmbariException;
import org.apache.ambari.server.api.query.QueryInfo;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.api.services.Request;
import org.apache.ambari.server.api.services.Result;
import org.apache.ambari.server.api.services.ResultImpl;
Expand All @@ -42,6 +46,7 @@
import org.apache.ambari.server.controller.internal.ArtifactResourceProvider;
import org.apache.ambari.server.controller.internal.BlueprintConfigurationProcessor;
import org.apache.ambari.server.controller.internal.BlueprintResourceProvider;
import org.apache.ambari.server.controller.internal.ClusterSettingResourceProvider;
import org.apache.ambari.server.controller.internal.ExportBlueprintRequest;
import org.apache.ambari.server.controller.internal.RequestImpl;
import org.apache.ambari.server.controller.internal.ResourceImpl;
Expand All @@ -68,7 +73,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableMap;

/**
* Renderer which renders a cluster resource as a blueprint.
Expand All @@ -80,6 +85,12 @@ public class ClusterBlueprintRenderer extends BaseRenderer implements Renderer {
*/
private AmbariManagementController controller = AmbariServer.getController();


/**
* MetaInfo used to get stack and mpack information.
*/
private AmbariMetaInfo metaInfo = controller.getAmbariMetaInfo();

// /**
// * Map of configuration type to configuration properties which are required that a user
// * input. These properties will be stripped from the exported blueprint.
Expand All @@ -101,48 +112,38 @@ public TreeNode<Set<String>> finalizeProperties(

copyPropertiesToResult(queryProperties, resultTree);

String configType = Resource.Type.Configuration.name();
if (resultTree.getChild(configType) == null) {
resultTree.addChild(new HashSet<>(), configType);
}
ensureChild(resultTree, Resource.Type.Configuration, "properties");

String serviceType = Resource.Type.Service.name();
if (resultTree.getChild(serviceType) == null) {
resultTree.addChild(new HashSet<>(), serviceType);
}
TreeNode<Set<String>> serviceNode = resultTree.getChild(serviceType);
if (serviceNode == null) {
serviceNode = resultTree.addChild(new HashSet<>(), serviceType);
}
String serviceComponentType = Resource.Type.Component.name();
TreeNode<Set<String>> serviceComponentNode = resultTree.getChild(
serviceType + "/" + serviceComponentType);
if (serviceComponentNode == null) {
serviceComponentNode = serviceNode.addChild(new HashSet<>(), serviceComponentType);
}
serviceComponentNode.getObject().add("ServiceComponentInfo/cluster_name");
serviceComponentNode.getObject().add("ServiceComponentInfo/service_name");
serviceComponentNode.getObject().add("ServiceComponentInfo/component_name");
serviceComponentNode.getObject().add("ServiceComponentInfo/recovery_enabled");

String hostType = Resource.Type.Host.name();
String hostComponentType = Resource.Type.HostComponent.name();
TreeNode<Set<String>> hostComponentNode = resultTree.getChild(
hostType + "/" + hostComponentType);

if (hostComponentNode == null) {
TreeNode<Set<String>> hostNode = resultTree.getChild(hostType);
if (hostNode == null) {
hostNode = resultTree.addChild(new HashSet<>(), hostType);
}
hostComponentNode = hostNode.addChild(new HashSet<>(), hostComponentType);
}
resultTree.getChild(configType).getObject().add("properties");
hostComponentNode.getObject().add("HostRoles/component_name");
ensureChild(resultTree, Resource.Type.ClusterSetting);

TreeNode<Set<String>> serviceGroupNode = ensureChild(resultTree, Resource.Type.ServiceGroup);
TreeNode<Set<String>> serviceNode = ensureChild(serviceGroupNode, Resource.Type.Service);
ensureChild(serviceNode, Resource.Type.Component,
"ServiceComponentInfo/cluster_name",
"ServiceComponentInfo/service_name",
"ServiceComponentInfo/component_name",
"ServiceComponentInfo/recovery_enabled");

TreeNode<Set<String>> hostNode = ensureChild(resultTree, Resource.Type.Host);
ensureChild(hostNode, Resource.Type.HostComponent, "HostRoles/component_name");

return resultTree;
}

private TreeNode<Set<String>> ensureChild(TreeNode<Set<String>> parent,
Resource.Type resourceType,
String... properties) {
TreeNode<Set<String>> child = parent.getChild(resourceType.name());
if (null == child) {
child = parent.addChild(new HashSet<>(), resourceType.name());
}
for (String property: properties) {
child.getObject().add(property);
}
return child;
}


@Override
public Result finalizeResult(Result queryResult) {
TreeNode<Resource> resultTree = queryResult.getResultTree();
Expand Down Expand Up @@ -198,11 +199,10 @@ private Resource createBlueprintResource(TreeNode<Resource> clusterNode) {
configProcessor.doUpdateForBlueprintExport();

Set<StackId> stackIds = topology.getStackIds();
if (stackIds.size() == 1) {
StackId stackId = Iterables.getOnlyElement(stackIds);
blueprintResource.setProperty("Blueprints/stack_name", stackId.getStackName());
blueprintResource.setProperty("Blueprints/stack_version", stackId.getStackVersion());
}
// TODO: mpacks should come from service groups once https://github.com/apache/ambari/pull/234 will be committed
Collection<Map<String, String>> mpackInstances = stackIds.stream().

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this query work for clusters that have been created by the Ambari UI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I am testing it with a cluster that has been created via UI.

map( stackId -> ImmutableMap.of("name", stackId.getStackName(), "version", stackId.getStackVersion())).collect(toList());
blueprintResource.setProperty(BlueprintResourceProvider.MPACK_INSTANCES_PROPERTY_ID, mpackInstances);

if (topology.isClusterKerberosEnabled()) {
Map<String, Object> securityConfigMap = new LinkedHashMap<>();
Expand Down Expand Up @@ -237,7 +237,7 @@ private Resource createBlueprintResource(TreeNode<Resource> clusterNode) {
/***
* Constructs the Settings object of the following form:
* "settings": [ {
"recovery_settings": [
"cluster_settings": [
{
"recovery_enabled": "true"
} ] },
Expand All @@ -261,6 +261,8 @@ private Resource createBlueprintResource(TreeNode<Resource> clusterNode) {
"recovery_enabled": "true"
} ] } ]
*
* <b>NOTE:</b> As of 3.0 global recovery settings will move under a new section called cluster_settings.
*
* @param clusterNode
* @return A Collection<Map<String, Object>> which represents the Setting Object
*/
Expand All @@ -270,25 +272,27 @@ private Collection<Map<String, Object>> getSettings(TreeNode<Resource> clusterNo
//Initialize collections to create appropriate json structure
Collection<Map<String, Object>> blueprintSetting = new ArrayList<>();

Set<Map<String, String>> recoverySettingValue = new HashSet<>();
Set<Map<String, String>> serviceSettingValue = new HashSet<>();
Set<Map<String, String>> componentSettingValue = new HashSet<>();

HashMap<String, String> property = new HashMap<>();
HashMap<String, String> componentProperty = new HashMap<>();
Boolean globalRecoveryEnabled = false;

//Fetch the services, to obtain ServiceInfo and ServiceComponents
Collection<TreeNode<Resource>> serviceChildren = clusterNode.getChild("services").getChildren();
// TODO: set mpack instance if needed (multi-mpack case)
Collection<TreeNode<Resource>> serviceChildren =
clusterNode.getChild("servicegroups").
getChildren().stream().flatMap(
node -> node.getChild("services").getChildren().stream()).
collect(toList());

HashMap<String, String> serviceProperty;
for (TreeNode serviceNode : serviceChildren) {
ResourceImpl service = (ResourceImpl) serviceNode.getObject();
Map<String, Object> ServiceInfoMap = service.getPropertiesMap().get("ServiceInfo");

//service_settings population
property = new HashMap<>();
serviceProperty = new HashMap<>();
if (ServiceInfoMap.get("credential_store_enabled").equals("true")) {
property.put("name", ServiceInfoMap.get("service_name").toString());
property.put("credential_store_enabled", "true");
serviceProperty.put("name", ServiceInfoMap.get("service_name").toString());
serviceProperty.put("credential_store_enabled", "true");
}

//Fetch the service Components to obtain ServiceComponentInfo
Expand All @@ -298,34 +302,36 @@ private Collection<Map<String, Object>> getSettings(TreeNode<Resource> clusterNo
Map<String, Object> ServiceComponentInfoMap = component.getPropertiesMap().get("ServiceComponentInfo");

if (ServiceComponentInfoMap.get("recovery_enabled").equals("true")) {
globalRecoveryEnabled = true;
property.put("name", ServiceInfoMap.get("service_name").toString());
property.put("recovery_enabled", "true");
serviceProperty.put("name", ServiceInfoMap.get("service_name").toString());
serviceProperty.put("recovery_enabled", "true");

//component_settings population
componentProperty = new HashMap<>();
HashMap<String, String> componentProperty = new HashMap<>();
componentProperty.put("name", ServiceComponentInfoMap.get("component_name").toString());
componentProperty.put("recovery_enabled", "true");
componentSettingValue.add(componentProperty);
}
}

if (!property.isEmpty())
serviceSettingValue.add(property);
if (!componentProperty.isEmpty())
componentSettingValue.add(componentProperty);
if (!serviceProperty.isEmpty())
serviceSettingValue.add(serviceProperty);
}
//recovery_settings population
property = new HashMap<>();
if (globalRecoveryEnabled) {
property.put("recovery_enabled", "true");
} else {
property.put("recovery_enabled", "false");

// Add cluster settings
Set<Map<String, String>> clusterSettings = new HashSet<>();
TreeNode<Resource> settingsNode = clusterNode.getChild("settings");
if (null != settingsNode) {
for (TreeNode<Resource> clusterSettingNode: settingsNode.getChildren()) {
Map<String, Object> nodeProperties = clusterSettingNode.getObject().getPropertiesMap().get(ClusterSettingResourceProvider.RESPONSE_KEY);
String key = Objects.toString(nodeProperties.get(ClusterSettingResourceProvider.CLUSTER_SETTING_NAME_PROPERTY_ID));
String value = Objects.toString(nodeProperties.get(ClusterSettingResourceProvider.CLUSTER_SETTING_VALUE_PROPERTY_ID));
clusterSettings.add(ImmutableMap.of(key, value));
}
}
recoverySettingValue.add(property);

//Add all the different setting values.
Map<String, Object> settingMap = new HashMap<>();
settingMap.put("recovery_settings", recoverySettingValue);
settingMap.put("cluster_settings", clusterSettings);
blueprintSetting.add(settingMap);

settingMap = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,16 @@ public class ClusterSettingResourceProvider extends AbstractControllerResourcePr

// ----- Property ID constants ---------------------------------------------

public static final String CLUSTER_SETTING_NAME_PROPERTY_ID = "cluster_setting_name";
public static final String CLUSTER_SETTING_VALUE_PROPERTY_ID = "cluster_setting_value";

public static final String RESPONSE_KEY = "ClusterSettingInfo";
public static final String ALL_PROPERTIES = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "*";
public static final String CLUSTER_SETTING_CLUSTER_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_id";
public static final String CLUSTER_SETTING_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_name";
public static final String CLUSTER_SETTING_CLUSTER_SETTING_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_setting_id";
public static final String CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_setting_name";
public static final String CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_setting_value";
public static final String CLUSTER_SETTING_CLUSTER_SETTING_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + CLUSTER_SETTING_NAME_PROPERTY_ID;
public static final String CLUSTER_SETTING_CLUSTER_SETTING_VALUE_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + CLUSTER_SETTING_VALUE_PROPERTY_ID;

private static final Set<String> pkPropertyIds =
Sets.newHashSet(new String[]{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,15 @@ public RequestStatus createResourcesAuthorized(final Request request)
associatedResources.add(resource);
return getRequestStatus(null, associatedResources);
}
} catch (IOException e) {
if (e instanceof ConnectException)
throw new SystemException("The Mpack Uri : " + mpackRequest.getMpackUri() + " is not valid. Please try again");
e.printStackTrace();
} catch (BodyParseException e1) {
e1.printStackTrace();
}
catch (ConnectException e) {
throw new SystemException("The Mpack Uri: " + mpackRequest.getMpackUri() + " is not valid. Please try again", e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't a ConnectException also sometimes occur for a valid URI that happens to not be reachable with the given connection?

Its not a big deal for now, but maybe we should consider changing the error message here to make the error cause a little clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed it could be improved. The reason why I made this change is that the original code was swallowing exceptions and I could only see an NPE thrown elsewhere and had to spend time debugging what was actually happening.

}
catch (IOException e) {
throw new SystemException("I/O exception occured during installing mpack: " + mpackRequest.getMpackUri(), e);
}
catch (BodyParseException e) {
throw new SystemException("Invalid mpack registration request", e);
}
return null;
}
Expand Down
Loading