This is an automated email from the ASF dual-hosted git repository. jluniya pushed a commit to branch branch-feature-AMBARI-14714 in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/branch-feature-AMBARI-14714 by this push: new 7675ce8 [AMBARI-22883] A new REST API: GET /api/v1/hosts?format=summary or /api/v1/clusters/… (#285) 7675ce8 is described below commit 7675ce84aeb2604c5c6c5b9480e91bda9ccc6e72 Author: sduan <sd...@hortonworks.com> AuthorDate: Thu Feb 22 11:46:49 2018 -0800 [AMBARI-22883] A new REST API: GET /api/v1/hosts?format=summary or /api/v1/clusters/… (#285) * A new REST API: GET /api/v1/hosts?format=summary or /api/v1/clusters/{cluster_name}/hosts?format=summary is supported with this implementation and return the number of hosts running each possible operating system. More aggregation info of hosts can be also added in this code structure. * A new REST API: GET /api/v1/hosts?format=summary or /api/v1/clusters/{cluster_name}/hosts?format=summary is supported with this implementation and return the number of hosts running each possible operating system. More aggregation info of hosts can be also added in this code structure. (Rebased) * A new REST API: GET /api/v1/hosts?format=summary or /api/v1/clusters/{cluster_name}/hosts?format=summary is supported with this implementation and return the number of hosts running each possible operating system. More aggregation info of hosts can be also added in this code structure. (Rebased) --- .../ambari/server/api/handlers/ReadHandler.java | 1 + .../api/query/render/HostSummaryRenderer.java | 99 ++++++++++++++++++++++ .../resources/DetachedHostResourceDefinition.java | 11 +++ .../api/resources/HostResourceDefinition.java | 10 +++ .../ambari/server/api/services/HostService.java | 4 +- .../ambari/server/controller/HostResponse.java | 38 +++++++++ .../controller/internal/DefaultProviderModule.java | 2 + .../controller/internal/HostResourceProvider.java | 17 ++-- 8 files changed, 176 insertions(+), 6 deletions(-) diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java index 077c1cc..0e307b2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/handlers/ReadHandler.java @@ -121,4 +121,5 @@ public class ReadHandler implements RequestHandler { query.addProperty(propertyId, entry.getValue()); } } + } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/HostSummaryRenderer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/HostSummaryRenderer.java new file mode 100644 index 0000000..3d6b843 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/HostSummaryRenderer.java @@ -0,0 +1,99 @@ +/* + * 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.api.query.render; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.ambari.server.api.services.Result; +import org.apache.ambari.server.api.services.ResultImpl; +import org.apache.ambari.server.api.util.TreeNode; +import org.apache.ambari.server.controller.internal.HostResourceProvider; +import org.apache.ambari.server.controller.internal.ResourceImpl; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.commons.lang.StringUtils; + +/** + * HostSummaryRenderere + * + * This renderer is to summarize the properties of all hosts within a cluster and returns + * a list of proerpties summary information: i.e + * + * summary:[ + * { + * "operating_systems" : { + * "centos6" : 5, + * "centos7" : 10 + * } + * } + * ] + * + */ +public class HostSummaryRenderer extends DefaultRenderer { + + // A list of host properties to be summarized + enum HostSummaryProperties { + OPERATINGSYSTEMS("operating_systems"); + + private final String property; + HostSummaryProperties(String property) { + this.property = property; + } + public String getProperty() { + return property; + } + } + + @Override + public Result finalizeResult(Result queryResult) { + TreeNode<Resource> queryResultTree = queryResult.getResultTree(); + // Iterate over all returned flattened hosts and build the summary info + List<Object> summary = new ArrayList<>(); + // Build all summary info + buildFinalizedSummary(queryResultTree, summary); + // Create finalized result + return buildFinalizedResult(summary); + } + + private void buildFinalizedSummary(TreeNode<Resource> queryResultTree, List<Object> summary) { + // Build osSummary info at this time + Map<String, Map<String, Integer>> osSummary = new HashMap<>(); + summary.add(osSummary); + Map<String, Integer> osTypeCount = new HashMap<>(); + osSummary.put(HostSummaryProperties.OPERATINGSYSTEMS.getProperty(), osTypeCount); + for (TreeNode<Resource> node : queryResultTree.getChildren()) { + Resource resource = node.getObject(); + String osType = (String) resource.getPropertyValue(HostResourceProvider.HOST_OS_TYPE_PROPERTY_ID); + if (StringUtils.isNotBlank(osType)) { + osTypeCount.put(osType, osTypeCount.getOrDefault(osTypeCount, 0) + 1); + } + } + } + + private Result buildFinalizedResult(List<Object> summary) { + Result result = new ResultImpl(true); + Resource resource = new ResourceImpl(Resource.Type.Host); + TreeNode<Resource> summaryTree = result.getResultTree(); + summaryTree.addChild(resource, HostResourceProvider.SUMMARY_PROPERTY_ID); + resource.setProperty(HostResourceProvider.SUMMARY_PROPERTY_ID, summary); + return result; + } +} diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/DetachedHostResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/DetachedHostResourceDefinition.java index 1cc4211..35e237c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/DetachedHostResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/DetachedHostResourceDefinition.java @@ -19,6 +19,8 @@ package org.apache.ambari.server.api.resources; +import org.apache.ambari.server.api.query.render.HostSummaryRenderer; +import org.apache.ambari.server.api.query.render.Renderer; import org.apache.ambari.server.controller.spi.Resource; @@ -40,4 +42,13 @@ public class DetachedHostResourceDefinition extends BaseResourceDefinition { public String getSingularName() { return "host"; } + + @Override + public Renderer getRenderer(String name) { + if (name.equals("summary")) { + return new HostSummaryRenderer(); + } + return super.getRenderer(name); + } + } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java index d22b5f6..46ca04a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/HostResourceDefinition.java @@ -24,6 +24,8 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; +import org.apache.ambari.server.api.query.render.HostSummaryRenderer; +import org.apache.ambari.server.api.query.render.Renderer; import org.apache.ambari.server.controller.spi.Request; import org.apache.ambari.server.controller.spi.Resource; @@ -55,6 +57,14 @@ public class HostResourceDefinition extends BaseResourceDefinition { } @Override + public Renderer getRenderer(String name) { + if (name.equals("summary")) { + return new HostSummaryRenderer(); + } + return super.getRenderer(name); + } + + @Override public Set<SubResourceDefinition> getSubResourceDefinitions() { Set<SubResourceDefinition> subs = new HashSet<>(); subs.add(new SubResourceDefinition(Resource.Type.HostComponent)); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java index 58d1d1d..aa9089e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/HostService.java @@ -28,6 +28,7 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; @@ -133,7 +134,8 @@ public class HostService extends BaseService { @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), }) - public Response getHosts(String body, @Context HttpHeaders headers, @Context UriInfo ui) { + public Response getHosts(String body, @Context HttpHeaders headers, @Context UriInfo ui, + @ApiParam(value = "summary", required = false) @QueryParam("format") String format) { return handleRequest(headers, body, ui, Request.Type.GET, createHostResource(m_clusterName, null)); } diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java index 9d02a0b..2c40b05 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/HostResponse.java @@ -146,6 +146,29 @@ public class HostResponse { private MaintenanceState maintenanceState; + /** + * Summary information of all hosts in a cluster or multiple clusters + * + * The response json schema is: + * { + * "Hosts" : { + * "cluster_name" : "c1", + * "summary" : [ + * { + * "operating_systems" : [ + * { + * "centos6" : 2 + * }, + * { + * "centos7" : 5 + * } + * ] + * } + * ] + * } + */ + private List<Object> hostsSummary; + public HostResponse(String hostname, String clusterName, String ipv4, int cpuCount, int phCpuCount, String osArch, String osType, long totalMemBytes, @@ -422,6 +445,21 @@ public class HostResponse { } /** + * Set the hostsSummary + */ + public void setHostsSummary(List<Object> hostsSummary) { + this.hostsSummary = hostsSummary; + } + + /** + * Get the aggregation info of hosts in a cluster or in multiple clusters + */ + @ApiModelProperty(name = HostResourceProvider.SUMMARY_PROPERTY_ID) + public List<Object> getHostsSummary() { + return hostsSummary; + } + + /** * Set the detailed recovery report */ public void setRecoveryReport(RecoveryReport recoveryReport) { diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java index 1dbe903..b7f2501 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java @@ -132,6 +132,8 @@ public class DefaultProviderModule extends AbstractProviderModule { return new ArtifactResourceProvider(managementController); case RemoteCluster: return new RemoteClusterResourceProvider(); + case Host: + return new HostResourceProvider(managementController); default: LOGGER.debug("Delegating creation of resource provider for: {} to the AbstractControllerResourceProvider", type.getInternalType()); return AbstractControllerResourceProvider.getResourceProvider(type, managementController); diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java index 7ecbfdc1..79f4233 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostResourceProvider.java @@ -116,6 +116,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { public static final String STATE_PROPERTY_ID = "host_state"; public static final String TOTAL_MEM_PROPERTY_ID = "total_mem"; public static final String ATTRIBUTES_PROPERTY_ID = "attributes"; + public static final String SUMMARY_PROPERTY_ID = "summary"; public static final String HOST_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + CLUSTER_NAME_PROPERTY_ID; public static final String HOST_CPU_COUNT_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + CPU_COUNT_PROPERTY_ID; @@ -139,7 +140,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { public static final String HOST_RECOVERY_SUMMARY_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + RECOVERY_SUMMARY_PROPERTY_ID; public static final String HOST_STATE_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + STATE_PROPERTY_ID; public static final String HOST_TOTAL_MEM_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + TOTAL_MEM_PROPERTY_ID; - public static final String HOST_ATTRIBUTES_PROPERTY_ID = PropertyHelper.getPropertyId(RESPONSE_KEY,ATTRIBUTES_PROPERTY_ID); + public static final String HOST_ATTRIBUTES_PROPERTY_ID = PropertyHelper.getPropertyId(RESPONSE_KEY, ATTRIBUTES_PROPERTY_ID); public static final String BLUEPRINT_PROPERTY_ID = "blueprint"; public static final String HOST_GROUP_PROPERTY_ID = "host_group"; @@ -154,6 +155,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { public static Map<Resource.Type, String> keyPropertyIds = ImmutableMap.<Resource.Type, String>builder() .put(Resource.Type.Host, HOST_HOST_NAME_PROPERTY_ID) .put(Resource.Type.Cluster, HOST_CLUSTER_NAME_PROPERTY_ID) + .put(Resource.Type.HostComponent, HOST_OS_TYPE_PROPERTY_ID) .build(); /** @@ -195,7 +197,7 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { /** * Create a new resource provider for the given management controller. * - * @param managementController the management controller + * @param managementController the management controller */ @AssistedInject HostResourceProvider(@Assisted AmbariManagementController managementController) { @@ -214,9 +216,9 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { @Override protected RequestStatus createResourcesAuthorized(final Request request) throws SystemException, - UnsupportedPropertyException, - ResourceAlreadyExistsException, - NoSuchParentResourceException { + UnsupportedPropertyException, + ResourceAlreadyExistsException, + NoSuchParentResourceException { RequestStatusResponse createResponse = null; if (isHostGroupRequest(request)) { @@ -238,6 +240,11 @@ public class HostResourceProvider extends AbstractControllerResourceProvider { @Override protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { + return getHostResource(request, predicate); + } + + private Set<Resource> getHostResource(Request request, Predicate predicate) + throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { final Set<HostRequest> requests = new HashSet<>(); -- To stop receiving notification emails like this one, please contact jlun...@apache.org.