You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jl...@apache.org on 2017/07/24 23:52:04 UTC
ambari git commit: AMBARI-21558: Software Registry Recommendations
API - Initial patch (jluniya)
Repository: ambari
Updated Branches:
refs/heads/branch-feature-AMBARI-14714 c34c86935 -> 332053bcd
AMBARI-21558: Software Registry Recommendations API - Initial patch (jluniya)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/332053bc
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/332053bc
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/332053bc
Branch: refs/heads/branch-feature-AMBARI-14714
Commit: 332053bcddca0f1f36249d5f43ee64a1716fe58d
Parents: c34c869
Author: Jayush Luniya <jl...@hortonworks.com>
Authored: Mon Jul 24 16:51:59 2017 -0700
Committer: Jayush Luniya <jl...@hortonworks.com>
Committed: Mon Jul 24 16:51:59 2017 -0700
----------------------------------------------------------------------
...egistryRecommendationResourceDefinition.java | 48 +++
.../RegistryValidationResourceDefinition.java | 60 ++++
.../resources/ResourceInstanceFactoryImpl.java | 8 +
.../registry/RegistryRecommendationService.java | 74 ++++
.../api/services/registry/RegistryService.java | 2 +-
.../registry/RegistryValidationService.java | 74 ++++
.../ambari/server/controller/AmbariServer.java | 3 +
.../AbstractControllerResourceProvider.java | 4 +
.../internal/DefaultProviderModule.java | 10 +
.../RegistryAdvisorResourceProvider.java | 134 ++++++++
.../RegistryRecommendationResourceProvider.java | 125 +++++++
.../RegistryValidationResourceProvider.java | 122 +++++++
.../ambari/server/controller/spi/Resource.java | 4 +
.../exceptions/RegistryAdvisorException.java | 41 +++
.../ambari/server/registry/MpackEntry.java | 71 ++++
.../ambari/server/registry/RegistryAdvisor.java | 341 +++++++++++++++++++
.../server/registry/RegistryAdvisorRequest.java | 131 +++++++
.../registry/RegistryAdvisorResponse.java | 121 +++++++
.../RegistryRecommendationResponse.java | 115 +++++++
.../registry/RegistryValidationResponse.java | 124 +++++++
.../apache/ambari/server/utils/SetUtils.java | 40 +++
21 files changed, 1651 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryRecommendationResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryRecommendationResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryRecommendationResourceDefinition.java
new file mode 100644
index 0000000..69e6b69
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryRecommendationResourceDefinition.java
@@ -0,0 +1,48 @@
+/*
+ * 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.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Registry recommendation resource definition.
+ */
+public class RegistryRecommendationResourceDefinition extends BaseResourceDefinition {
+ /**
+ * Constructor.
+ */
+ public RegistryRecommendationResourceDefinition() {
+ super(Resource.Type.RegistryRecommendation);
+ }
+
+ @Override
+ public String getPluralName() {
+ return "recommendations";
+ }
+
+ @Override
+ public String getSingularName() {
+ return "recommendation";
+ }
+
+ @Override
+ public boolean isCreatable() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryValidationResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryValidationResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryValidationResourceDefinition.java
new file mode 100644
index 0000000..af4dcde
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/RegistryValidationResourceDefinition.java
@@ -0,0 +1,60 @@
+/*
+ * 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.resources;
+
+import org.apache.ambari.server.controller.spi.Resource;
+
+/**
+ * Registry validation resource definition.
+ */
+public class RegistryValidationResourceDefinition extends BaseResourceDefinition {
+ /**
+ * Constructor.
+ */
+ public RegistryValidationResourceDefinition() {
+ super(Resource.Type.RegistryValidation);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return
+ */
+ @Override
+ public String getPluralName() {
+ return "validations";
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return
+ */
+ @Override
+ public String getSingularName() {
+ return "validation";
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return
+ */
+ @Override
+ public boolean isCreatable() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index 34070e1..73963df 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -153,6 +153,14 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
resourceDefinition = new RegistryResourceDefinition();
break;
+ case RegistryRecommendation:
+ resourceDefinition = new RegistryRecommendationResourceDefinition();
+ break;
+
+ case RegistryValidation:
+ resourceDefinition = new RegistryValidationResourceDefinition();
+ break;
+
case RegistryScenario:
resourceDefinition = new RegistryScenarioResourceDefinition();
break;
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryRecommendationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryRecommendationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryRecommendationService.java
new file mode 100644
index 0000000..8a01dae
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryRecommendationService.java
@@ -0,0 +1,74 @@
+/*
+ * 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.services.registry;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.annotations.ApiIgnore;
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.BaseService;
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+
+
+/**
+ * REST API endpoint for registry recommendations
+ */
+@Path("/registries/{registryId}/recommendations")
+public class RegistryRecommendationService extends BaseService {
+
+ /**
+ * Create registry recommendation
+ * @param body Request body
+ * @param headers Http headers
+ * @param ui Uri info
+ * @param registryId Registry id
+ * @return {@link Response} containing registry recommendation response
+ */
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ @ApiIgnore // until documented
+ public Response createRegistryRecommendation(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("registryId") String registryId) {
+ return handleRequest(headers, body, ui, Request.Type.POST,
+ createRegistryRecommendationResource(registryId));
+ }
+
+ /**
+ * Create registry recommendation resource instance
+ * @param registryId Registry id
+ * @return Registry recommendation resource instance
+ */
+ ResourceInstance createRegistryRecommendationResource(String registryId) {
+ Map<Resource.Type, String> mapIds = new HashMap<>();
+ mapIds.put(Resource.Type.Registry, registryId);
+ return createResource(Resource.Type.RegistryRecommendation, mapIds);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryService.java
index 7704149..05ac1b9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryService.java
@@ -64,9 +64,9 @@ public class RegistryService extends BaseService {
/**
* Handles: POST /registries/
*
+ * @param body request body
* @param headers http headers
* @param ui uri info
- * @param body request body
* @return information regarding the software registry created
*/
@POST
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryValidationService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryValidationService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryValidationService.java
new file mode 100644
index 0000000..20e4b4f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/registry/RegistryValidationService.java
@@ -0,0 +1,74 @@
+/*
+ * 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.services.registry;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.ambari.annotations.ApiIgnore;
+import org.apache.ambari.server.api.resources.ResourceInstance;
+import org.apache.ambari.server.api.services.BaseService;
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+
+
+/**
+ * REST API endpoint for registry validations
+ */
+@Path("/registries/{registryId}/validations")
+public class RegistryValidationService extends BaseService {
+
+ /**
+ * Create registry validation
+ * @param body Request body
+ * @param headers Http headers
+ * @param ui Uri info
+ * @param registryId Registry id
+ * @return {@link Response} containing registry validation response
+ */
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ @ApiIgnore // until documented
+ public Response createRegistryValidation(String body, @Context HttpHeaders headers, @Context UriInfo ui,
+ @PathParam("registryId") String registryId) {
+ return handleRequest(headers, body, ui, Request.Type.POST,
+ createRegistryValidationResource(registryId));
+ }
+
+ /**
+ * Create registry validation resource
+ * @param registryId Registry id
+ * @return Registry validation resource instance
+ */
+ ResourceInstance createRegistryValidationResource(String registryId) {
+ Map<Resource.Type, String> mapIds = new HashMap<>();
+ mapIds.put(Resource.Type.Registry, registryId);
+ return createResource(Resource.Type.RegistryValidation, mapIds);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
index 8988be0..6d4d1c9 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariServer.java
@@ -69,6 +69,7 @@ import org.apache.ambari.server.controller.internal.ClusterResourceProvider;
import org.apache.ambari.server.controller.internal.HostResourceProvider;
import org.apache.ambari.server.controller.internal.PermissionResourceProvider;
import org.apache.ambari.server.controller.internal.PrivilegeResourceProvider;
+import org.apache.ambari.server.controller.internal.RegistryAdvisorResourceProvider;
import org.apache.ambari.server.controller.internal.StackAdvisorResourceProvider;
import org.apache.ambari.server.controller.internal.StackDefinedPropertyProvider;
import org.apache.ambari.server.controller.internal.StackDependencyResourceProvider;
@@ -91,6 +92,7 @@ import org.apache.ambari.server.orm.dao.ResourceDAO;
import org.apache.ambari.server.orm.dao.UserDAO;
import org.apache.ambari.server.orm.dao.ViewInstanceDAO;
import org.apache.ambari.server.orm.entities.MetainfoEntity;
+import org.apache.ambari.server.registry.RegistryAdvisor;
import org.apache.ambari.server.resources.ResourceManager;
import org.apache.ambari.server.resources.api.rest.GetResource;
import org.apache.ambari.server.scheduler.ExecutionScheduleManager;
@@ -908,6 +910,7 @@ public class AmbariServer {
KeyService.init(injector.getInstance(PersistKeyValueImpl.class));
BootStrapResource.init(injector.getInstance(BootStrapImpl.class));
StackAdvisorResourceProvider.init(injector.getInstance(StackAdvisorHelper.class));
+ RegistryAdvisorResourceProvider.init(injector.getInstance(RegistryAdvisor.class));
StageUtils.setGson(injector.getInstance(Gson.class));
StageUtils.setTopologyManager(injector.getInstance(TopologyManager.class));
StageUtils.setConfiguration(injector.getInstance(Configuration.class));
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
index 5cfcdc7..3228a7f 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AbstractControllerResourceProvider.java
@@ -182,6 +182,10 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori
return new StackResourceProvider(propertyIds, keyPropertyIds, managementController);
case Registry:
return new RegistryResourceProvider(managementController);
+ case RegistryRecommendation:
+ return new RegistryRecommendationResourceProvider(managementController);
+ case RegistryValidation:
+ return new RegistryValidationResourceProvider(managementController);
case RegistryScenario:
return new RegistryScenarioResourceProvider(managementController);
case RegistryMpack:
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/DefaultProviderModule.java
----------------------------------------------------------------------
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 7466bb4..248abad 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
@@ -92,6 +92,16 @@ public class DefaultProviderModule extends AbstractProviderModule {
return new AlertResourceProvider(managementController);
case Registry:
return new RegistryResourceProvider(managementController);
+ case RegistryRecommendation:
+ return new RegistryRecommendationResourceProvider(managementController);
+ case RegistryValidation:
+ return new RegistryValidationResourceProvider(managementController);
+ case RegistryScenario:
+ return new RegistryScenarioResourceProvider(managementController);
+ case RegistryMpack:
+ return new RegistryMpackResourceProvider(managementController);
+ case RegistryMpackVersion:
+ return new RegistryMpackVersionResourceProvider(managementController);
case Mpack:
return new MpackResourceProvider(managementController);
case AlertDefinition:
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryAdvisorResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryAdvisorResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryAdvisorResourceProvider.java
new file mode 100644
index 0000000..87d8102
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryAdvisorResourceProvider.java
@@ -0,0 +1,134 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.controller.internal;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.registry.MpackEntry;
+import org.apache.ambari.server.registry.RegistryAdvisor;
+import org.apache.ambari.server.registry.RegistryAdvisorRequest;
+import org.apache.ambari.server.registry.RegistryAdvisorRequest.RegistryAdvisorRequestBuilder;
+import org.apache.ambari.server.registry.RegistryAdvisorRequest.RegistryAdvisorRequestType;
+
+import com.google.inject.Inject;
+
+/**
+ * Abstract superclass for registry recommendations and validations.
+ */
+public abstract class RegistryAdvisorResourceProvider extends AbstractControllerResourceProvider {
+
+ public static final String REGISTRY_ID = PropertyHelper.getPropertyId("RegistryInfo", "registry_id");
+ protected static final String SELECTED_SCENARIOS_PROPERTY_ID = "selected_scenarios";
+ protected static final String SELECTED_MPACKS_PROPERTY_ID = "selected_mpacks";
+
+ protected static RegistryAdvisor registryAdvisor;
+
+ @Inject
+ public static void init(RegistryAdvisor instance) {
+ registryAdvisor = instance;
+ }
+
+ /**
+ * Constructor
+ * @param propertyIds Property ids
+ * @param keyPropertyIds Key property ids
+ * @param managementController Ambari management controller instance
+ */
+ protected RegistryAdvisorResourceProvider(Set<String> propertyIds, Map<Resource.Type, String> keyPropertyIds,
+ AmbariManagementController managementController) {
+ super(propertyIds, keyPropertyIds, managementController);
+ }
+
+ /**
+ * Get property containing {@link RegistryAdvisorRequestType}
+ * @return Property id
+ */
+ protected abstract String getRequestTypePropertyId();
+
+ /**
+ * Create registry advisor request instance
+ * @param request {@link Request} input
+ * @return {@link RegistryAdvisorRequest} instance
+ */
+ protected RegistryAdvisorRequest createRegistryAdvisorRequest(Request request) {
+ try {
+ Long registryId = Long.valueOf((String) getRequestProperty(request, REGISTRY_ID));
+ RegistryAdvisorRequestType requestType = RegistryAdvisorRequestType.fromString(
+ (String) getRequestProperty(request, getRequestTypePropertyId()));
+ List<String> selectedScenarios = (List<String>) getRequestProperty(request, SELECTED_SCENARIOS_PROPERTY_ID);
+ List<MpackEntry> selectedMpacks = parseSelectedMpacksProperty(request);
+ return RegistryAdvisorRequestBuilder.forRegistry(registryId)
+ .ofType(requestType)
+ .forScenarios(selectedScenarios)
+ .forMpacks(selectedMpacks)
+ .build();
+ } catch (Exception e) {
+ LOG.warn("Error occurred during preparation of registry advisor request", e);
+ Response response = Response.status(Response.Status.BAD_REQUEST)
+ .entity(String.format("Request body is not correct, error: %s", e.getMessage())).build();
+ // TODO: Hosts and services must not be empty
+ throw new WebApplicationException(response);
+ }
+ }
+
+ /**
+ * Parse selected mpacks property from the reuqest
+ * @param request {@link Request} input
+ * @return List of selected mpacks
+ */
+ private List<MpackEntry> parseSelectedMpacksProperty(Request request) {
+ List<MpackEntry> selectedMpacks = new LinkedList<>();request.getProperties();
+ Set<Map<String, String>> selectedMpacksProperties =
+ (Set<Map<String, String>>) getRequestProperty(request, SELECTED_MPACKS_PROPERTY_ID);
+ if(selectedMpacksProperties != null) {
+ for (Map<String, String> properties : selectedMpacksProperties) {
+ String mpackName = properties.get("mpack_name");
+ String mpackVersion = properties.get("mpack_version");
+ MpackEntry mpackEntry = new MpackEntry(mpackName, mpackVersion);
+ selectedMpacks.add(mpackEntry);
+ }
+ }
+ return selectedMpacks;
+ }
+
+ /**
+ * Get value of property in the request
+ * @param request {@link Request} input
+ * @param propertyName Property name
+ * @return Property value
+ */
+ protected Object getRequestProperty(Request request, String propertyName) {
+ for (Map<String, Object> propertyMap : request.getProperties()) {
+ if (propertyMap.containsKey(propertyName)) {
+ return propertyMap.get(propertyName);
+ }
+ }
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryRecommendationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryRecommendationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryRecommendationResourceProvider.java
new file mode 100644
index 0000000..e2b8ea6
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryRecommendationResourceProvider.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.controller.internal;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.registry.RegistryAdvisorRequest;
+import org.apache.ambari.server.registry.RegistryRecommendationResponse;
+
+
+/**
+ * Registry recommendation resource provider
+ */
+public class RegistryRecommendationResourceProvider extends RegistryAdvisorResourceProvider {
+
+ protected static final String RECOMMEND_PROPERTY_ID = "recommend";
+ protected static final String RECOMMENDATION_ID_PROPERTY_ID = PropertyHelper.getPropertyId(
+ "RegistryRecommendation", "id");
+ protected static final String RECOMMEND_MPACK_BUNDLES_PROPERTY_ID = PropertyHelper
+ .getPropertyId("recommendations", "mpack_bundles");
+
+ private static Set<String> pkPropertyIds = new HashSet<>(
+ Arrays.asList(REGISTRY_ID, RECOMMENDATION_ID_PROPERTY_ID));
+
+ /**
+ * The property ids for a software registry resource.
+ */
+ private static final Set<String> PROPERTY_IDS = new HashSet<>();
+
+ /**
+ * The key property ids for a software registry resource.
+ */
+ private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new HashMap<>();
+
+ static {
+ // properties
+ PROPERTY_IDS.add(REGISTRY_ID);
+ PROPERTY_IDS.add(RECOMMENDATION_ID_PROPERTY_ID);
+ PROPERTY_IDS.add(RECOMMEND_PROPERTY_ID);
+ PROPERTY_IDS.add(SELECTED_SCENARIOS_PROPERTY_ID);
+ PROPERTY_IDS.add(RECOMMEND_MPACK_BUNDLES_PROPERTY_ID);
+
+ // keys
+ KEY_PROPERTY_IDS.put(Resource.Type.Registry, REGISTRY_ID);
+ KEY_PROPERTY_IDS.put(Resource.Type.RegistryRecommendation, RECOMMENDATION_ID_PROPERTY_ID);
+
+ }
+
+ /**
+ * Constructor
+ * @param managementController Ambari management controller instance
+ */
+ protected RegistryRecommendationResourceProvider(
+ final AmbariManagementController managementController) {
+ super(PROPERTY_IDS, KEY_PROPERTY_IDS, managementController);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return pkPropertyIds;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public RequestStatus createResourcesAuthorized(Request request)
+ throws NoSuchParentResourceException, ResourceAlreadyExistsException, SystemException {
+ RegistryAdvisorRequest registryAdvisorRequest = createRegistryAdvisorRequest(request);
+ RegistryRecommendationResponse response = createResources(new Command<RegistryRecommendationResponse>() {
+ @Override
+ public RegistryRecommendationResponse invoke() throws AmbariException {
+ return registryAdvisor.recommend(registryAdvisorRequest);
+ }
+ });
+ Resource resource = new ResourceImpl(Resource.Type.RegistryRecommendation);
+ resource.setProperty(REGISTRY_ID, response.getRegistryId());
+ resource.setProperty(RECOMMENDATION_ID_PROPERTY_ID, response.getId());
+ resource.setProperty(RECOMMEND_PROPERTY_ID, response.getRequestType().toString());
+ resource.setProperty(SELECTED_SCENARIOS_PROPERTY_ID, response.getSelectedScenarios());
+ resource.setProperty(RECOMMEND_MPACK_BUNDLES_PROPERTY_ID, response.getRecommendations().getMpackBundles());
+
+ Set<Resource> associatedResources = new HashSet<>(Arrays.asList(resource));
+ return getRequestStatus(null, associatedResources);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getRequestTypePropertyId() {
+ return RECOMMEND_PROPERTY_ID;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryValidationResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryValidationResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryValidationResourceProvider.java
new file mode 100644
index 0000000..bedbb04
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/RegistryValidationResourceProvider.java
@@ -0,0 +1,122 @@
+/*
+ * 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.controller.internal;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.RequestStatus;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceAlreadyExistsException;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.registry.RegistryAdvisorRequest;
+import org.apache.ambari.server.registry.RegistryValidationResponse;
+
+
+/**
+ * Registry validation resource provider
+ */
+public class RegistryValidationResourceProvider extends RegistryAdvisorResourceProvider {
+
+ protected static final String VALIDATE_PROPERTY_ID = "validate";
+ protected static final String VALIDATION_ID_PROPERTY_ID = PropertyHelper.getPropertyId(
+ "RegistryValidation", "id");
+ protected static final String ITEMS_PROPERTY_ID = "items";
+
+ private static Set<String> pkPropertyIds = new HashSet<>(
+ Arrays.asList(REGISTRY_ID, VALIDATION_ID_PROPERTY_ID));
+
+ /**
+ * The property ids for a software registry resource.
+ */
+ private static final Set<String> PROPERTY_IDS = new HashSet<>();
+
+ /**
+ * The key property ids for a software registry resource.
+ */
+ private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new HashMap<>();
+
+ static {
+ // properties
+ PROPERTY_IDS.add(REGISTRY_ID);
+ PROPERTY_IDS.add(VALIDATION_ID_PROPERTY_ID);
+ PROPERTY_IDS.add(VALIDATE_PROPERTY_ID);
+ PROPERTY_IDS.add(SELECTED_SCENARIOS_PROPERTY_ID);
+ PROPERTY_IDS.add(SELECTED_MPACKS_PROPERTY_ID);
+ PROPERTY_IDS.add(ITEMS_PROPERTY_ID);
+
+ // keys
+ KEY_PROPERTY_IDS.put(Resource.Type.Registry, REGISTRY_ID);
+ KEY_PROPERTY_IDS.put(Resource.Type.RegistryValidation, VALIDATION_ID_PROPERTY_ID);
+
+ }
+
+ protected RegistryValidationResourceProvider(
+ final AmbariManagementController managementController) {
+ super(PROPERTY_IDS, KEY_PROPERTY_IDS, managementController);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected Set<String> getPKPropertyIds() {
+ return pkPropertyIds;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public RequestStatus createResourcesAuthorized(Request request)
+ throws NoSuchParentResourceException, ResourceAlreadyExistsException, SystemException {
+ RegistryAdvisorRequest registryAdvisorRequest = createRegistryAdvisorRequest(request);
+ RegistryValidationResponse response = createResources(new Command<RegistryValidationResponse>() {
+ @Override
+ public RegistryValidationResponse invoke() throws AmbariException {
+ return registryAdvisor.validate(registryAdvisorRequest);
+ }
+ });
+ Resource resource = new ResourceImpl(Resource.Type.RegistryValidation);
+ setResourceProperty(resource, REGISTRY_ID, response.getRegistryId(), getPropertyIds());
+ setResourceProperty(resource, VALIDATION_ID_PROPERTY_ID, response.getId(), getPropertyIds());
+ setResourceProperty(resource, VALIDATE_PROPERTY_ID, response.getRequestType().toString(), getPropertyIds());
+ setResourceProperty(resource, SELECTED_SCENARIOS_PROPERTY_ID, response.getSelectedScenarios(), getPropertyIds());
+ setResourceProperty(resource, SELECTED_MPACKS_PROPERTY_ID, response.getSelectedMpacks(), getPropertyIds());
+ setResourceProperty(resource, ITEMS_PROPERTY_ID, response.getItems(), getPropertyIds());
+
+ Set<Resource> associatedResources = new HashSet<>(Arrays.asList(resource));
+ return getRequestStatus(null, associatedResources);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String getRequestTypePropertyId() {
+ return VALIDATE_PROPERTY_ID;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
index f07ca79..1994501 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/spi/Resource.java
@@ -91,6 +91,8 @@ public interface Resource {
Group,
Member,
Registry,
+ RegistryRecommendation,
+ RegistryValidation,
RegistryScenario,
RegistryMpack,
RegistryMpackVersion,
@@ -217,6 +219,8 @@ public interface Resource {
public static final Type Group = InternalType.Group.getType();
public static final Type Member = InternalType.Member.getType();
public static final Type Registry = InternalType.Registry.getType();
+ public static final Type RegistryRecommendation = InternalType.RegistryRecommendation.getType();
+ public static final Type RegistryValidation = InternalType.RegistryValidation.getType();
public static final Type RegistryScenario = InternalType.RegistryScenario.getType();
public static final Type RegistryMpack = InternalType.RegistryMpack.getType();
public static final Type RegistryMpackVersion = InternalType.RegistryMpackVersion.getType();
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/exceptions/RegistryAdvisorException.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/exceptions/RegistryAdvisorException.java b/ambari-server/src/main/java/org/apache/ambari/server/exceptions/RegistryAdvisorException.java
new file mode 100644
index 0000000..c90300f
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/exceptions/RegistryAdvisorException.java
@@ -0,0 +1,41 @@
+/*
+ * 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.exceptions;
+
+/**
+ * Registry advisor exception
+ */
+public class RegistryAdvisorException extends Exception {
+
+ /**
+ * Constructor
+ * @param message Exception message
+ */
+ public RegistryAdvisorException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructor
+ * @param message Exception message
+ * @param cause Exception cause
+ */
+ public RegistryAdvisorException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/registry/MpackEntry.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/MpackEntry.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/MpackEntry.java
new file mode 100644
index 0000000..c1029af
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/MpackEntry.java
@@ -0,0 +1,71 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.registry;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Mpack version recommenation
+ */
+public class MpackEntry {
+ private String mpackName;
+ private String mpackVersion;
+ private RegistryMpackVersion registryMpackVersion;
+
+ public MpackEntry(String mpackName, String mpackVersion) {
+ this.mpackName = mpackName;
+ this.mpackVersion = mpackVersion;
+ this.registryMpackVersion = registryMpackVersion;
+ }
+
+ /**
+ * Get mpack name
+ * @return
+ */
+ @JsonProperty("mpack_name")
+ public String getMpackName() {
+ return mpackName;
+ }
+
+ /**
+ * Get version
+ * @return
+ */
+ @JsonProperty("mpack_version")
+ public String getMpackVersion() {
+ return mpackVersion;
+ }
+
+ /**
+ * Set registry mpack version
+ * @param registryMpackVersion
+ */
+ public void setRegistryMpackVersion(RegistryMpackVersion registryMpackVersion) {
+ this.registryMpackVersion = registryMpackVersion;
+ }
+
+ /**
+ * Get registry mpack version
+ * @return
+ */
+ @JsonIgnore
+ public RegistryMpackVersion getRegistryMpackVersion() {
+ return registryMpackVersion;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisor.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisor.java
new file mode 100644
index 0000000..025338d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisor.java
@@ -0,0 +1,341 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.registry;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.ObjectNotFoundException;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.registry.RegistryRecommendationResponse.RegistryRecommendationResponseBuilder;
+import org.apache.ambari.server.registry.RegistryRecommendationResponse.RegistryRecommendations;
+import org.apache.ambari.server.registry.RegistryValidationResponse.RegistryValidationItem;
+import org.apache.ambari.server.registry.RegistryValidationResponse.RegistryValidationResponseBuilder;
+import org.apache.ambari.server.utils.SetUtils;
+import org.apache.ambari.server.utils.VersionUtils;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+
+/**
+ * Registry Advisor
+ */
+@Singleton
+public class RegistryAdvisor {
+
+ private AmbariManagementController managementController;
+ private long requestId = 0;
+
+ /**
+ * Given list of all possible mpack bundles, check compatibility and return compatible mpack bundles.
+ * @param mpackBundles all possible mpack bundles
+ * @return filtered compatible mpack bundles
+ */
+ private List<Collection<MpackEntry>> filterCompatibleMpackBundles(List<Collection<MpackEntry>> mpackBundles) {
+ List<Collection<MpackEntry>> compatibleMpackBundles = new LinkedList<>();
+ for(Collection<MpackEntry> mpackBundle : mpackBundles) {
+ if(isCompatibleMpackBundle(mpackBundle)) {
+ compatibleMpackBundles.add(mpackBundle);
+ }
+ }
+ return compatibleMpackBundles;
+ }
+
+ /**
+ * Check if the mpack bundle is compatible.
+ * @param mpackBundle mpack bundle to check
+ * @return True if the mpack bundle is compatible, else False
+ */
+ private boolean isCompatibleMpackBundle(Collection<MpackEntry> mpackBundle) {
+ Map<String, MpackEntry> mpackMap = new HashMap<>();
+ for(MpackEntry mvr : mpackBundle) {
+ mpackMap.put(mvr.getMpackName(), mvr);
+ }
+ for(MpackEntry mvr: mpackMap.values()) {
+ RegistryMpackVersion rmv = mvr.getRegistryMpackVersion();
+ List<RegistryMpackCompatiblity> compatiblities = (List<RegistryMpackCompatiblity>) rmv.getCompatibleMpacks();
+ if(compatiblities != null && !compatiblities.isEmpty()) {
+ for(RegistryMpackCompatiblity compatiblity : compatiblities) {
+ if(mpackMap.containsKey(compatiblity.getName())) {
+ String selectedVersion = mpackMap.get(compatiblity.getName()).getMpackVersion();
+ String minVersion = compatiblity.getMinVersion();
+ String maxVersion = compatiblity.getMaxVersion();
+ if(minVersion != null && !minVersion.isEmpty()
+ && VersionUtils.compareVersions(selectedVersion, minVersion) < 0) {
+ return false;
+ }
+ if(maxVersion != null && !maxVersion.isEmpty()
+ && VersionUtils.compareVersions(selectedVersion, maxVersion) > 0) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Get merged list of mpacks that support the selected scenarios.
+ * @param registry registry to use for getting list of mpacks for selected scenarios
+ * @param scenarioNames selected scenario names
+ * @return merged list of scenario mpacks
+ * @throws AmbariException
+ */
+ private Collection<String> getScenarioMpacks(Registry registry, Collection<String> scenarioNames)
+ throws AmbariException {
+ Set<String> scenarioMpackNames = new HashSet<>();
+ for(String selectedScenario : scenarioNames) {
+ RegistryScenario registryScenario = registry.getRegistryScenario(selectedScenario);
+ for(RegistryScenarioMpack scenarioMpack : registryScenario.getScenarioMpacks()) {
+ if(!scenarioMpackNames.contains(scenarioMpack.getName())) {
+ scenarioMpackNames.add(scenarioMpack.getName());
+ }
+ }
+ }
+ return scenarioMpackNames;
+ }
+
+ /**
+ * Given a list of mpacks, find all mpack versions for each mpack
+ * @param registry registry to use for getting list of mpack versions
+ * @param mpackNames list of mpack names
+ * @return all mpack versions group by mpack
+ * @throws AmbariException
+ */
+ private List<Collection<MpackEntry>> getAllMpackEntries(Registry registry, Collection<String> mpackNames)
+ throws AmbariException {
+ List<Collection<MpackEntry>> allMpackEntries = new LinkedList<>();
+ for(String mpackName : mpackNames) {
+ RegistryMpack registryMpack = registry.getRegistryMpack(mpackName);
+ List<MpackEntry> mpackEntries = new LinkedList<>();
+ for(RegistryMpackVersion registryMpackVersion : registryMpack.getMpackVersions()) {
+ MpackEntry mpackEntry = new MpackEntry(
+ registryMpack.getMpackName(), registryMpackVersion.getMpackVersion());
+ mpackEntry.setRegistryMpackVersion(registryMpackVersion);
+ mpackEntries.add(mpackEntry);
+ }
+ allMpackEntries.add(mpackEntries);
+ }
+ return allMpackEntries;
+ }
+
+ /**
+ * Create a mpacks hash map with key [mpack_name]-[mpack_version]
+ * @param mpackEntries collection of mpacks
+ * @return hash map of mpacks
+ */
+ private HashMap<String, MpackEntry> convertToMpackVersionsMap(Collection<MpackEntry> mpackEntries) {
+ HashMap<String, MpackEntry> mpacksMap = new HashMap<>();
+ for(MpackEntry mpackEntry : mpackEntries) {
+ String key = mpackEntry.getMpackName() + "-" + mpackEntry.getMpackVersion();
+ mpacksMap.put(key, mpackEntry);
+ }
+ return mpacksMap;
+ }
+
+ /**
+ * Create a mpacks map with key [mpack_name]
+ * @param mpackEntries collection of mpacks
+ * @return hash map of mpacks
+ */
+ private HashMap<String, MpackEntry> convertToMpacksMap(Collection<MpackEntry> mpackEntries) {
+ HashMap<String, MpackEntry> mpacksMap = new HashMap<>();
+ for(MpackEntry mpackEntry : mpackEntries) {
+ String key = mpackEntry.getMpackName();
+ mpacksMap.put(key, mpackEntry);
+ }
+ return mpacksMap;
+ }
+
+ /**
+ * Find a compatible mpack bundle that matches the selected list of mpacks.
+ * @param compatibleMpackBundles all compatible mpack bundles
+ * @param selectedMpacks selected mpacks
+ * @return compatible mpack bundle
+ */
+ private Collection<MpackEntry> findCompatibleMpackBundle(
+ List<Collection<MpackEntry>> compatibleMpackBundles, Collection<MpackEntry> selectedMpacks) {
+
+ HashMap<String, MpackEntry> selectedMpacksMap = convertToMpackVersionsMap(selectedMpacks);
+ for(Collection<MpackEntry> compatibleMpackBundle : compatibleMpackBundles) {
+ boolean isCompatible = true;
+ for(MpackEntry mpackEntry: compatibleMpackBundle) {
+ String key = mpackEntry.getMpackName() + "-" + mpackEntry.getMpackVersion();
+ if(!selectedMpacksMap.containsKey(key)) {
+ isCompatible = false;
+ break;
+ }
+ }
+ if(isCompatible) {
+ return compatibleMpackBundle;
+ }
+ }
+ return null;
+ }
+
+ @Inject
+ public RegistryAdvisor(AmbariManagementController managementController) {
+ this.managementController = managementController;
+ }
+
+ /**
+ * Returns registry recommendation response based on the request [scenario-mpacks]
+ * @param request the recommendation request
+ * @return {@link RegistryRecommendationResponse} for the request
+ * @throws AmbariException
+ */
+ public synchronized RegistryRecommendationResponse recommend(RegistryAdvisorRequest request) throws AmbariException {
+ // Get registry
+ Registry registry = managementController.getRegistry(request.getRegistryId());
+ // Get all scenario mpacks
+ Collection<String> scenarioMpackNames = getScenarioMpacks(registry, request.getSelectedScenarios());
+ // Get all mpack versions for each scenario mpack
+ List<Collection<MpackEntry>> allMpackEntries = getAllMpackEntries(registry, scenarioMpackNames);
+ // Get all possible mpack bundles
+ List<Collection<MpackEntry>> allMpackBundles = SetUtils.permutations(allMpackEntries);
+ // Filter down to compatible mpack bundles
+ List<Collection<MpackEntry>> compatibleMpackBundles = filterCompatibleMpackBundles(allMpackBundles);
+ // Order recommentations by versions with latest at pole position.
+ compatibleMpackBundles.sort(new Comparator<Collection<MpackEntry>>() {
+ @Override
+ public int compare(final Collection<MpackEntry> o1, final Collection<MpackEntry> o2) {
+ int o1Wins = 0;
+ int o2Wins = 0;
+ HashMap<String, MpackEntry> o1Map = convertToMpacksMap(o1);
+ HashMap<String, MpackEntry> o2Map = convertToMpacksMap(o2);
+ for(Map.Entry<String, MpackEntry> mapEntry : o1Map.entrySet()) {
+ MpackEntry o1Entry = mapEntry.getValue();
+ MpackEntry o2Entry = o2Map.get(mapEntry.getKey());
+ int compareResult = VersionUtils.compareVersions(o1Entry.getMpackVersion(), o2Entry.getMpackVersion());
+ if(compareResult > 0) {
+ o1Wins++;
+ } else if(compareResult < 0) {
+ o2Wins++;
+ }
+ }
+ // Order in reverse order
+ return o2Wins - o1Wins;
+ }
+ });
+ // Create recommendations
+ RegistryRecommendations recommendations = new RegistryRecommendations();
+ recommendations.setMpackBundles(compatibleMpackBundles);
+ return RegistryRecommendationResponseBuilder.forRegistry(request.getRegistryId())
+ .ofType(request.getRequestType())
+ .forScenarios(request.getSelectedScenarios())
+ .forMpacks(request.getSelectedMpacks())
+ .withId(generateRequestId())
+ .withRecommendations(recommendations).build();
+ }
+
+ /**
+ * Returns registry validation response based on the request [scenario-mpacks]
+ * @param request the validation request
+ * @return {@link RegistryValidationResponse} for the request
+ * @throws AmbariException
+ */
+ public synchronized RegistryValidationResponse validate(RegistryAdvisorRequest request) throws AmbariException {
+ Registry registry = managementController.getRegistry(request.getRegistryId());
+ List<RegistryValidationItem> validationItems = new LinkedList<>();
+
+ // Get all mpacks required for the selected scenarios
+ Collection<String> scenarioMpackNames = getScenarioMpacks(registry, request.getSelectedScenarios());
+
+ // Validate that all mpacks required for the selected scenarios have been selected
+ for(String mpackName : scenarioMpackNames) {
+ boolean isSelected = false;
+ for(MpackEntry mpackEntry : request.getSelectedMpacks()) {
+ if(mpackName.equals(mpackEntry.getMpackName())) {
+ isSelected = true;
+ break;
+ }
+ }
+ if(!isSelected) {
+ // Validation failure
+ String type = "ScenarioMpackValidation";
+ String level = "FATAL";
+ String message = "Selected mpacks does not contain " + mpackName +
+ " mpack which is required for supporting the selected scenarios.";
+ RegistryValidationItem validationItem = new RegistryValidationItem(type, level, message);
+ validationItems.add(validationItem);
+ }
+ }
+
+ // Validate if any selected mpack is not in the registry
+ List<String> knownSelectedMpackNames = new LinkedList<>();
+ for(MpackEntry mpackEntry : request.getSelectedMpacks()) {
+ try {
+ RegistryMpack registryMpack = registry.getRegistryMpack(mpackEntry.getMpackName());
+ RegistryMpackVersion registryMpackVersion = registryMpack.getMpackVersion(mpackEntry.getMpackVersion());
+ knownSelectedMpackNames.add(registryMpack.getMpackName());
+ } catch (ObjectNotFoundException ex) {
+ String type = "UnknownMpackValidation";
+ String level = "WARN";
+ String mpackFullName = mpackEntry.getMpackName() + "-" + mpackEntry.getMpackVersion();
+ String message = "Mpack " + mpackFullName + " not found in the registry. "
+ + "Cannot validate compatility with other mpacks.";
+ RegistryValidationItem validationItem = new RegistryValidationItem(type, level, message);
+ validationItems.add(validationItem);
+ }
+ }
+
+ // Get all mpack versions for each known selected mpack
+ List<Collection<MpackEntry>> allMpackEntries = getAllMpackEntries(registry, knownSelectedMpackNames);
+ // Get all possible permutations
+ List<Collection<MpackEntry>> allMpackBundles = SetUtils.permutations(allMpackEntries);
+ // Filter down to compatible permutations
+ List<Collection<MpackEntry>> compatibleMpackBundles = filterCompatibleMpackBundles(allMpackBundles);
+
+ // Validate that the selected mpacks is present in a compatible mpack bundle
+ Collection<MpackEntry> compatibleMpackBundle = findCompatibleMpackBundle(compatibleMpackBundles, request.getSelectedMpacks());
+ if(compatibleMpackBundle == null) {
+ // Selected mpacks are not compatible
+ String type = "CompatibleMpackValidation";
+ String level = "FATAL";
+ String message = "Selected mpacks are not compatible and can cause issues during cluster installation.";
+ RegistryValidationItem validationItem = new RegistryValidationItem(type, level, message);
+ validationItems.add(validationItem);
+ }
+
+ return RegistryValidationResponseBuilder.forRegistry(request.getRegistryId())
+ .ofType(request.getRequestType())
+ .forScenarios(request.getSelectedScenarios())
+ .forMpacks(request.getSelectedMpacks())
+ .withId(generateRequestId())
+ .withValidations(validationItems).build();
+ }
+
+ /**
+ * Generate registry advisor request id
+ * TODO: Store registry advisor requests in database.
+ * @return
+ */
+ public long generateRequestId() {
+ requestId += 1;
+ return requestId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorRequest.java
new file mode 100644
index 0000000..72e9279
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorRequest.java
@@ -0,0 +1,131 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.registry;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.ambari.server.exceptions.RegistryAdvisorException;
+
+/**
+ * Represents a registry advisor request
+ */
+public class RegistryAdvisorRequest {
+ private Long registryId;
+ private RegistryAdvisorRequestType requestType;
+ private List<String> selectedScenarios;
+ private List<MpackEntry> selectedMpacks;
+
+ /**
+ * Constructor
+ * @param registryId ID of software registry
+ */
+ public RegistryAdvisorRequest(Long registryId) {
+ this.registryId = registryId;
+ }
+
+ public Long getRegistryId() {
+ return registryId;
+ }
+
+ public RegistryAdvisorRequestType getRequestType() {
+ return requestType;
+ }
+
+ public List<String> getSelectedScenarios() {
+ return selectedScenarios;
+ }
+
+ public List<MpackEntry> getSelectedMpacks() {
+ return selectedMpacks;
+ }
+
+ /**
+ * Registry advisor request builder
+ */
+ public static class RegistryAdvisorRequestBuilder {
+ RegistryAdvisorRequest instance;
+
+ private RegistryAdvisorRequestBuilder(Long registryId) {
+ this.instance = new RegistryAdvisorRequest(registryId);
+ }
+
+ public static RegistryAdvisorRequestBuilder forRegistry(Long registryId) {
+ return new RegistryAdvisorRequestBuilder(registryId);
+ }
+
+ public RegistryAdvisorRequestBuilder ofType(RegistryAdvisorRequestType requestType) {
+ this.instance.requestType = requestType;
+ return this;
+ }
+
+ public RegistryAdvisorRequestBuilder forScenarios(List<String> selectedScenarios) {
+ this.instance.selectedScenarios = selectedScenarios;
+ return this;
+ }
+
+ public RegistryAdvisorRequestBuilder forMpacks(List<MpackEntry> selectedMpacks) {
+ this.instance.selectedMpacks = selectedMpacks;
+ return this;
+ }
+
+ public RegistryAdvisorRequest build() {
+ return this.instance;
+ }
+ }
+
+ /**
+ *
+ */
+ public enum RegistryAdvisorRequestType {
+ SCENARIO_MPACKS("scenario-mpacks");
+
+ private String type;
+
+ RegistryAdvisorRequestType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return type;
+ }
+
+ /**
+ * Get registry advisor request type from string
+ * @param text string input
+ * @return {@link RegistryAdvisorRequestType}
+ * @throws RegistryAdvisorException
+ */
+ public static RegistryAdvisorRequestType fromString(String text) throws RegistryAdvisorException {
+ if (text != null) {
+ for (RegistryAdvisorRequestType next : RegistryAdvisorRequestType.values()) {
+ if (text.equalsIgnoreCase(next.type)) {
+ return next;
+ }
+ }
+ }
+ throw new RegistryAdvisorException(String.format(
+ "Unknown request type: %s, possible values: %s", text,
+ Arrays.toString(RegistryAdvisorRequestType.values())));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorResponse.java
new file mode 100644
index 0000000..38db4c3
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryAdvisorResponse.java
@@ -0,0 +1,121 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.registry;
+
+import java.util.List;
+
+import org.apache.ambari.server.registry.RegistryAdvisorRequest.RegistryAdvisorRequestType;
+
+/**
+ * Abstract registry advisor response POJO
+ */
+public abstract class RegistryAdvisorResponse {
+ private Long id;
+ private Long registryId;
+ private RegistryAdvisorRequest.RegistryAdvisorRequestType requestType;
+ private List<String> selectedScenarios;
+ private List<MpackEntry> selectedMpacks;
+
+ /**
+ * Set registry advisor request id
+ * @param id
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * Get registry advisor request id
+ * @return
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * Set registry id
+ * @param registryId
+ */
+ public void setRegistryId(Long registryId) {
+ this.registryId = registryId;
+ }
+
+ /**
+ * Get registry id
+ * @return
+ */
+ public Long getRegistryId() {
+ return registryId;
+ }
+
+ /**
+ * Set request type
+ * @param requestType
+ */
+ public void setRequestType(RegistryAdvisorRequestType requestType) {
+ this.requestType = requestType;
+ }
+
+ /**
+ * Get request type
+ * @return
+ */
+ public RegistryAdvisorRequestType getRequestType() {
+ return requestType;
+ }
+
+ /**
+ * Set selected scenarios
+ * @param selectedScenarios
+ */
+ public void setSelectedScenarios(List<String> selectedScenarios) {
+ this.selectedScenarios = selectedScenarios;
+ }
+
+ /**
+ * Get selected scenarios
+ * @return
+ */
+ public List<String> getSelectedScenarios() {
+ return selectedScenarios;
+ }
+
+ /**
+ * Set selected mpacks
+ * @param selectedMpacks
+ */
+ public void setSelectedMpacks(List<MpackEntry> selectedMpacks) {
+ this.selectedMpacks = selectedMpacks;
+ }
+
+ /**
+ * Get selected mpacks
+ * @return
+ */
+ public List<MpackEntry> getSelectedMpacks() {
+ return selectedMpacks;
+ }
+
+ /**
+ * Constructor
+ * @param registryId ID of software registry
+ */
+ public RegistryAdvisorResponse(Long registryId) {
+ this.registryId = registryId;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryRecommendationResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryRecommendationResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryRecommendationResponse.java
new file mode 100644
index 0000000..923b409
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryRecommendationResponse.java
@@ -0,0 +1,115 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.registry;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.ambari.server.registry.RegistryAdvisorRequest.RegistryAdvisorRequestType;
+
+/**
+ * Registry recommendation response
+ */
+public class RegistryRecommendationResponse extends RegistryAdvisorResponse {
+
+
+ private RegistryRecommendations recommendations;
+
+ /**
+ * Constructor
+ * @param registryId ID of software registry
+ */
+ public RegistryRecommendationResponse(Long registryId) {
+ super(registryId);
+ }
+
+ /**
+ * Set recommendations
+ * @param recommendations
+ */
+ public void setRecommendations(RegistryRecommendations recommendations) {
+ this.recommendations = recommendations;
+ }
+
+ /**
+ * Get recommentations
+ * @return
+ */
+ public RegistryRecommendations getRecommendations() {
+ return recommendations;
+ }
+
+ /**
+ * Registry advisor request builder
+ */
+ public static class RegistryRecommendationResponseBuilder {
+ RegistryRecommendationResponse instance;
+
+ private RegistryRecommendationResponseBuilder(Long registryId) {
+ this.instance = new RegistryRecommendationResponse(registryId);
+ }
+
+ public static RegistryRecommendationResponseBuilder forRegistry(Long registryId) {
+ return new RegistryRecommendationResponseBuilder(registryId);
+ }
+
+ public RegistryRecommendationResponseBuilder ofType(RegistryAdvisorRequestType requestType) {
+ this.instance.setRequestType(requestType);
+ return this;
+ }
+
+ public RegistryRecommendationResponseBuilder forScenarios(List<String> selectedScenarios) {
+ this.instance.setSelectedScenarios(selectedScenarios);
+ return this;
+ }
+
+ public RegistryRecommendationResponseBuilder forMpacks(List<MpackEntry> selectedMpacks) {
+ this.instance.setSelectedMpacks(selectedMpacks);
+ return this;
+ }
+
+ public RegistryRecommendationResponseBuilder withId(Long id) {
+ this.instance.setId(id);
+ return this;
+ }
+
+ public RegistryRecommendationResponseBuilder withRecommendations(RegistryRecommendations recommendations) {
+ this.instance.recommendations = recommendations;
+ return this;
+ }
+
+ public RegistryRecommendationResponse build() {
+ return this.instance;
+ }
+ }
+
+ /**
+ * Registry recommendations
+ */
+ public static class RegistryRecommendations {
+ public List<Collection<MpackEntry>> mpackBundles;
+
+ public void setMpackBundles(List<Collection<MpackEntry>> mpackBundles) {
+ this.mpackBundles = mpackBundles;
+ }
+
+ public List<Collection<MpackEntry>> getMpackBundles() {
+ return mpackBundles;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryValidationResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryValidationResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryValidationResponse.java
new file mode 100644
index 0000000..ed3b137
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/registry/RegistryValidationResponse.java
@@ -0,0 +1,124 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.registry;
+
+import java.util.List;
+
+import org.apache.ambari.server.registry.RegistryAdvisorRequest.RegistryAdvisorRequestType;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+/**
+ * Registry validation response
+ */
+public class RegistryValidationResponse extends RegistryAdvisorResponse {
+
+ @JsonProperty
+ private List<RegistryValidationItem> items;
+
+ public List<RegistryValidationItem> getItems() {
+ return items;
+ }
+
+ public void setItems(List<RegistryValidationItem> items) {
+ this.items = items;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param registryId ID of software registry
+ */
+ public RegistryValidationResponse(final Long registryId) {
+ super(registryId);
+ }
+
+ /**
+ * Registry advisor request builder
+ */
+ public static class RegistryValidationResponseBuilder {
+ RegistryValidationResponse instance;
+
+ private RegistryValidationResponseBuilder(Long registryId) {
+ this.instance = new RegistryValidationResponse(registryId);
+ }
+
+ public static RegistryValidationResponseBuilder forRegistry(Long registryId) {
+ return new RegistryValidationResponseBuilder(registryId);
+ }
+
+ public RegistryValidationResponseBuilder ofType(RegistryAdvisorRequestType requestType) {
+ this.instance.setRequestType(requestType);
+ return this;
+ }
+
+ public RegistryValidationResponseBuilder forScenarios(List<String> selectedScenarios) {
+ this.instance.setSelectedScenarios(selectedScenarios);
+ return this;
+ }
+
+ public RegistryValidationResponseBuilder forMpacks(List<MpackEntry> selectedMpacks) {
+ this.instance.setSelectedMpacks(selectedMpacks);
+ return this;
+ }
+
+ public RegistryValidationResponseBuilder withId(Long id) {
+ this.instance.setId(id);
+ return this;
+ }
+
+ public RegistryValidationResponseBuilder withValidations(List<RegistryValidationItem> items) {
+ this.instance.items = items;
+ return this;
+ }
+
+ public RegistryValidationResponse build() {
+ return this.instance;
+ }
+ }
+
+ /**
+ * Registry validation item
+ */
+ public static class RegistryValidationItem {
+ @JsonProperty
+ private String type;
+
+ @JsonProperty
+ private String level;
+
+ @JsonProperty
+ private String message;
+
+ public RegistryValidationItem(String type, String level, String message) {
+ this.type = type;
+ this.level = level;
+ this.message = message;
+ }
+ public String getType() {
+ return type;
+ }
+ public String getLevel() {
+ return level;
+ }
+ public String getMessage() {
+ return message;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/332053bc/ambari-server/src/main/java/org/apache/ambari/server/utils/SetUtils.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/utils/SetUtils.java b/ambari-server/src/main/java/org/apache/ambari/server/utils/SetUtils.java
index 5aeb02d..7748a11 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/utils/SetUtils.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/utils/SetUtils.java
@@ -18,9 +18,11 @@
package org.apache.ambari.server.utils;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@@ -59,4 +61,42 @@ public class SetUtils {
}
return subsets;
}
+
+ /**
+ * Create all possible permutations of a list of collections.
+ * @param collections List of collections
+ * @param <T>
+ * @return Permutations between the collections
+ */
+ public static <T> List<Collection<T>> permutations(List<Collection<T>> collections) {
+ if(collections == null || collections.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ List<Collection<T>> results = new LinkedList<>();
+ permutationsImpl(collections, results, 0, new LinkedList<T>());
+ return results;
+ }
+ }
+
+ /**
+ * Permutations implementation
+ * @param original
+ * @param results
+ * @param depth
+ * @param current
+ * @param <T>
+ */
+ private static <T> void permutationsImpl(List<Collection<T>> original,
+ List<Collection<T>> results, int depth, Collection<T> current) {
+ if(depth == original.size()) {
+ results.add(current);
+ return;
+ }
+ Collection<T> currentList = original.get(depth);
+ for(T element : currentList) {
+ List<T> copyList = new LinkedList<T>(current);
+ copyList.add(element);
+ permutationsImpl(original, results, depth + 1, copyList);
+ }
+ }
}