AMBARI-22249. Add service group dependencies.(vbrodetskyi)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/16913b20 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/16913b20 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/16913b20 Branch: refs/heads/branch-feature-AMBARI-14714 Commit: 16913b201706c416cea6cf441f4800dd600568f1 Parents: eaeed81 Author: Vitaly Brodetskyi <[email protected]> Authored: Thu Nov 2 17:59:14 2017 +0200 Committer: Vitaly Brodetskyi <[email protected]> Committed: Thu Nov 2 17:59:14 2017 +0200 ---------------------------------------------------------------------- .../resources/ResourceInstanceFactoryImpl.java | 4 + ...erviceGroupDependencyResourceDefinition.java | 41 ++ .../ServiceGroupResourceDefinition.java | 1 + .../server/api/services/ServiceGroupKey.java | 89 ++++ .../api/services/ServiceGroupService.java | 151 +++++- .../server/controller/ControllerModule.java | 2 + .../controller/ResourceProviderFactory.java | 5 +- .../ServiceGroupDependencyRequest.java | 75 +++ .../ServiceGroupDependencyResponse.java | 166 +++++++ .../AbstractControllerResourceProvider.java | 2 + .../internal/DefaultProviderModule.java | 2 + .../ServiceGroupDependencyResourceProvider.java | 484 +++++++++++++++++++ .../ambari/server/controller/spi/Resource.java | 2 + .../server/orm/entities/ServiceGroupEntity.java | 29 +- .../org/apache/ambari/server/state/Cluster.java | 4 + .../ambari/server/state/ServiceGroup.java | 15 +- .../server/state/ServiceGroupFactory.java | 6 +- .../ambari/server/state/ServiceGroupImpl.java | 121 ++++- .../server/state/cluster/ClusterImpl.java | 62 ++- .../ambari/server/topology/AmbariContext.java | 12 +- .../main/resources/Ambari-DDL-Derby-CREATE.sql | 9 + .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 9 + .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 9 + .../resources/Ambari-DDL-Postgres-CREATE.sql | 9 + .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 9 + .../resources/Ambari-DDL-SQLServer-CREATE.sql | 9 + 26 files changed, 1317 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/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 2c5edb7..c009cbb 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 @@ -112,6 +112,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory { resourceDefinition = new ServiceGroupResourceDefinition(); break; + case ServiceGroupDependency: + resourceDefinition = new ServiceGroupDependencyResourceDefinition(); + break; + case Service: resourceDefinition = new ServiceResourceDefinition(); break; http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupDependencyResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupDependencyResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupDependencyResourceDefinition.java new file mode 100644 index 0000000..5c99161 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupDependencyResourceDefinition.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 + * <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.api.resources; + + +import org.apache.ambari.server.controller.spi.Resource; + +public class ServiceGroupDependencyResourceDefinition extends BaseResourceDefinition { + + /** + * Constructor. + */ + public ServiceGroupDependencyResourceDefinition() { + super(Resource.Type.ServiceGroupDependency); + } + + @Override + public String getPluralName() { + return "dependencies"; + } + + @Override + public String getSingularName() { + return "dependency"; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupResourceDefinition.java index 13bdd7b..1d123d8 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupResourceDefinition.java @@ -49,6 +49,7 @@ public class ServiceGroupResourceDefinition extends BaseResourceDefinition { public Set<SubResourceDefinition> getSubResourceDefinitions() { Set<SubResourceDefinition> subs = new HashSet<SubResourceDefinition>(); subs.add(new SubResourceDefinition(Resource.Type.Service)); + subs.add(new SubResourceDefinition(Resource.Type.ServiceGroupDependency)); return subs; } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupKey.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupKey.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupKey.java new file mode 100644 index 0000000..9389f0c --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupKey.java @@ -0,0 +1,89 @@ +/** + * 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.api.services; + + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ServiceGroupKey { + + private Long clusterId; + private Long serviceGroupId; + private String clusterName; + private String serviceGroupName; + + @JsonProperty("cluster_name") + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + @JsonProperty("service_group_name") + public String getServiceGroupName() { + return serviceGroupName; + } + + public void setServiceGroupName(String serviceGroupName) { + this.serviceGroupName = serviceGroupName; + } + + public Long getClusterId() { + return clusterId; + } + + public void setClusterId(Long clusterId) { + this.clusterId = clusterId; + } + + public Long getServiceGroupId() { + return serviceGroupId; + } + + public void setServiceGroupId(Long serviceGroupId) { + this.serviceGroupId = serviceGroupId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ServiceGroupKey)) return false; + + ServiceGroupKey that = (ServiceGroupKey) o; + + if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false; + if (clusterName != null ? !clusterName.equals(that.clusterName) : that.clusterName != null) return false; + if (serviceGroupId != null ? !serviceGroupId.equals(that.serviceGroupId) : that.serviceGroupId != null) + return false; + if (serviceGroupName != null ? !serviceGroupName.equals(that.serviceGroupName) : that.serviceGroupName != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = clusterId != null ? clusterId.hashCode() : 0; + result = 31 * result + (serviceGroupId != null ? serviceGroupId.hashCode() : 0); + result = 31 * result + (clusterName != null ? clusterName.hashCode() : 0); + result = 31 * result + (serviceGroupName != null ? serviceGroupName.hashCode() : 0); + return result; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java index 1e2eaf4..0638a06 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java @@ -35,6 +35,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.apache.ambari.server.api.resources.ResourceInstance; +import org.apache.ambari.server.controller.ServiceGroupDependencyResponse; import org.apache.ambari.server.controller.ServiceGroupResponse; import org.apache.ambari.server.controller.spi.Resource; import org.apache.http.HttpStatus; @@ -47,13 +48,14 @@ import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; - /** * Service responsible for servicegroups resource requests. */ @Api(value = "Service Groups", description = "Endpoint for servicegroup specific operations") public class ServiceGroupService extends BaseService { private static final String SERVICE_GROUP_REQUEST_TYPE = "org.apache.ambari.server.controller.ServiceGroupRequestSwagger"; + private static final String SERVICE_GROUP_DEPENDENCY_REQUEST_TYPE = "org.apache.ambari.server.controller.ServiceGroupDependencyRequestSwagger"; + /** * Parent cluster Name. @@ -279,6 +281,143 @@ public class ServiceGroupService extends BaseService { } /** + * Handles URL: /clusters/{clusterName}/servicegroups/{serviceGroupName}/dependencies + * Get all servicegroupdependencies for a cluster. + * + * @param headers http headers + * @param ui uri info + * @return service group dependencies collection resource representation + */ + @GET + @Path("{serviceGroupName}/dependencies") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Get all servicegroupdependencies", + nickname = "ServiceGroupService#getServiceGroupDependencies", + notes = "Returns all servicegroupdependencies.", + response = ServiceGroupDependencyResponse.ServiceGroupDependencyResponseSwagger.class, + responseContainer = RESPONSE_CONTAINER_LIST) + @ApiImplicitParams({ + @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, + defaultValue = "ServiceGroupInfo/service_group_name, ServiceGroupInfo/cluster_name", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_SORT, value = QUERY_SORT_DESCRIPTION, + defaultValue = "ServiceGroupInfo/service_group_name.asc, ServiceGroupInfo/cluster_name.asc", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_PAGE_SIZE, value = QUERY_PAGE_SIZE_DESCRIPTION, defaultValue = DEFAULT_PAGE_SIZE, dataType = DATA_TYPE_INT, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_FROM, value = QUERY_FROM_DESCRIPTION, defaultValue = DEFAULT_FROM, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY), + @ApiImplicitParam(name = QUERY_TO, value = QUERY_TO_DESCRIPTION, dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR) + }) + public Response getServiceGroupDependencies(String body, @Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("serviceGroupName") String serviceGroupName) { + + return handleRequest(headers, body, ui, Request.Type.GET, + createServiceGroupDependencyResource(m_clusterName, serviceGroupName, null)); + } + + /** + * Handles URL: /clusters/{clusterName}/servicegroups/{serviceGroupName}/dependencies/{serviceGroupDependency} + * Get a specific servicegroupdependency. + * + * @param headers http headers + * @param ui uri info + * @param serviceGroupName service group name + * @param serviceGroupDependency service group dependency name + * @return servicegroupdependency resource representation + */ + @GET + @Path("{serviceGroupName}/dependencies/{serviceGroupDependency}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Get the details of a servicegroupdependency", + nickname = "ServiceGroupService#getServiceGroupDependency", + notes = "Returns the details of a servicegroupdependency", + response = ServiceGroupResponse.ServiceGroupResponseSwagger.class, + responseContainer = RESPONSE_CONTAINER_LIST) + @ApiImplicitParams({ + @ApiImplicitParam(name = QUERY_FIELDS, value = QUERY_FILTER_DESCRIPTION, defaultValue = "ServiceGroupInfo/*", + dataType = DATA_TYPE_STRING, paramType = PARAM_TYPE_QUERY) + }) + @ApiResponses(value = { + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR) + }) + public Response getServiceGroupDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("serviceGroupName") String serviceGroupName, + @PathParam("serviceGroupDependency") String serviceGroupDependency) { + + return handleRequest(headers, body, ui, Request.Type.GET, + createServiceGroupDependencyResource(m_clusterName, serviceGroupName, serviceGroupDependency)); + } + + /** + * Handles: POST /clusters/{clusterName}/servicegroups/{serviceGroupName}/dependencies + * Create multiple servicegroupdependencies. + * + * @param body http body + * @param headers http headers + * @param ui uri info + * @return information regarding the created servicegroupdependencies + */ + @POST + @Path("{serviceGroupName}/dependencies") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Creates a servicegroupdependency", + nickname = "ServiceGroupService#addServiceGroupDependency" + ) + @ApiImplicitParams({ + @ApiImplicitParam(dataType = SERVICE_GROUP_DEPENDENCY_REQUEST_TYPE, paramType = PARAM_TYPE_BODY) + }) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_CREATED, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_ACCEPTED, message = MSG_REQUEST_ACCEPTED), + @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = MSG_INVALID_ARGUMENTS), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_CONFLICT, message = MSG_RESOURCE_ALREADY_EXISTS), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response addServiceGroupDependency(String body, @Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("serviceGroupName") String serviceGroupName) { + + return handleRequest(headers, body, ui, Request.Type.POST, + createServiceGroupDependencyResource(m_clusterName, serviceGroupName, null)); + } + + /** + * Handles: DELETE /clusters/{clusterName}/servicegroups/{serviceGroupName}/dependencies/{serviceGroupDependency} + * Delete a specific servicegroupdependency. + + * @param headers http headers + * @param ui uri info + * @param serviceGroupName service group name + * @param serviceGroupDependency service group dependency name + * @return information regarding the deleted servicegroupdependency + */ + @DELETE + @Path("{serviceGroupName}/dependencies/{serviceGroupDependency}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Deletes a servicegroupdependency", + nickname = "ServiceGroupService#deleteServiceGroupDependency" + ) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_OK, message = MSG_SUCCESSFUL_OPERATION), + @ApiResponse(code = HttpStatus.SC_NOT_FOUND, message = MSG_RESOURCE_NOT_FOUND), + @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = MSG_NOT_AUTHENTICATED), + @ApiResponse(code = HttpStatus.SC_FORBIDDEN, message = MSG_PERMISSION_DENIED), + @ApiResponse(code = HttpStatus.SC_INTERNAL_SERVER_ERROR, message = MSG_SERVER_ERROR), + }) + public Response deleteServiceGroupDependency(@Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("serviceGroupName") String serviceGroupName, + @PathParam("serviceGroupDependency") String serviceGroupDependency) { + + return handleRequest(headers, null, ui, Request.Type.DELETE, createServiceGroupDependencyResource(m_clusterName, serviceGroupName, serviceGroupDependency)); + } + /** * Create a service resource instance. * * @param clusterName cluster Name @@ -294,4 +433,14 @@ public class ServiceGroupService extends BaseService { return createResource(Resource.Type.ServiceGroup, mapIds); } + + ResourceInstance createServiceGroupDependencyResource(String clusterName, String serviceGroupName, String serviceGroupDependency) { + Map<Resource.Type, String> mapIds = new HashMap<>(); + mapIds.put(Resource.Type.Cluster, clusterName); + mapIds.put(Resource.Type.ServiceGroup, serviceGroupName); + mapIds.put(Resource.Type.ServiceGroupDependency, serviceGroupDependency); + + + return createResource(Resource.Type.ServiceGroupDependency, mapIds); + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java index ee805b1..cb19099 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java @@ -73,6 +73,7 @@ import org.apache.ambari.server.controller.internal.HostResourceProvider; import org.apache.ambari.server.controller.internal.KerberosDescriptorResourceProvider; import org.apache.ambari.server.controller.internal.MemberResourceProvider; import org.apache.ambari.server.controller.internal.RepositoryVersionResourceProvider; +import org.apache.ambari.server.controller.internal.ServiceGroupDependencyResourceProvider; import org.apache.ambari.server.controller.internal.ServiceGroupResourceProvider; import org.apache.ambari.server.controller.internal.ServiceResourceProvider; import org.apache.ambari.server.controller.internal.UpgradeResourceProvider; @@ -477,6 +478,7 @@ public class ControllerModule extends AbstractModule { .implement(ResourceProvider.class, Names.named("hostComponent"), HostComponentResourceProvider.class) .implement(ResourceProvider.class, Names.named("service"), ServiceResourceProvider.class) .implement(ResourceProvider.class, Names.named("servicegroup"), ServiceGroupResourceProvider.class) + .implement(ResourceProvider.class, Names.named("servicegroupdependency"), ServiceGroupDependencyResourceProvider.class) .implement(ResourceProvider.class, Names.named("component"), ComponentResourceProvider.class) .implement(ResourceProvider.class, Names.named("member"), MemberResourceProvider.class) .implement(ResourceProvider.class, Names.named("repositoryVersion"), RepositoryVersionResourceProvider.class) http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java index b5a6547..20f4864 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ResourceProviderFactory.java @@ -48,6 +48,9 @@ public interface ResourceProviderFactory { @Named("servicegroup") ResourceProvider getServiceGroupResourceProvider(AmbariManagementController managementController); + @Named("servicegroupdependency") + ResourceProvider getServiceGroupDependencyResourceProvider(AmbariManagementController managementController); + @Named("component") ResourceProvider getComponentResourceProvider(AmbariManagementController managementController); @@ -83,4 +86,4 @@ public interface ResourceProviderFactory { @Named("viewInstance") ViewInstanceResourceProvider getViewInstanceResourceProvider(); -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java new file mode 100644 index 0000000..e9cf937 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyRequest.java @@ -0,0 +1,75 @@ +/** + * 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; + + +public class ServiceGroupDependencyRequest { + + private String clusterName; // REF + private String serviceGroupName; // GET/CREATE/UPDATE/DELETE + private String dependencyServiceGroupName; + + public ServiceGroupDependencyRequest(String clusterName, String serviceGroupName, String dependencyServiceGroupName) { + this.clusterName = clusterName; + this.serviceGroupName = serviceGroupName; + this.dependencyServiceGroupName = dependencyServiceGroupName; + } + + /** + * @return the clusterName + */ + public String getClusterName() { + return clusterName; + } + + /** + * @param clusterName the clusterName to set + */ + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + /** + * @return the serviceGroupName + */ + public String getServiceGroupName() { + return serviceGroupName; + } + + /** + * @param serviceGroupName the service group name to set + */ + public void setServiceGroupName(String serviceGroupName) { + this.serviceGroupName = serviceGroupName; + } + + public String getDependencyServiceGroupName() { + return dependencyServiceGroupName; + } + + public void setDependencyServiceGroupName(String dependencyServiceGroupName) { + this.dependencyServiceGroupName = dependencyServiceGroupName; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("clusterName=" + clusterName + + ", serviceGroupName=" + serviceGroupName); + return sb.toString(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyResponse.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyResponse.java new file mode 100644 index 0000000..1a4b4ed --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupDependencyResponse.java @@ -0,0 +1,166 @@ +/** + * 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; + +import io.swagger.annotations.ApiModelProperty; + +public class ServiceGroupDependencyResponse { + + private Long clusterId; + private Long serviceGroupId; + private Long dependencyClusterId; + private Long dependencyGroupId; + private String clusterName; + private String serviceGroupName; + private String dependencyGroupName; + private String dependencyClusterName; + + public ServiceGroupDependencyResponse(Long clusterId, String clusterName, Long serviceGroupId, String serviceGroupName, + Long dependencyClusterId, String dependencyClusterName, + Long dependencyGroupId, String dependencyGroupName) { + this.clusterId = clusterId; + this.serviceGroupId = serviceGroupId; + this.clusterName = clusterName; + this.serviceGroupName = serviceGroupName; + this.dependencyGroupId = dependencyGroupId; + this.dependencyGroupName = dependencyGroupName; + this.dependencyClusterId = dependencyClusterId; + this.dependencyClusterName = dependencyClusterName; + } + + /** + * @return the clusterId + */ + public Long getClusterId() { + return clusterId; + } + + /** + * @param clusterId the clusterId to set + */ + public void setClusterId(Long clusterId) { + this.clusterId = clusterId; + } + + /** + * @return the clusterName + */ + public String getClusterName() { + return clusterName; + } + + /** + * @param clusterName the clusterName to set + */ + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + /** + * @return the service group Id + */ + public Long getServiceGroupId() { + return serviceGroupId; + } + + /** + * @param serviceGroupId the service group Id + */ + public void setServiceGroupId(Long serviceGroupId) { + this.serviceGroupId = serviceGroupId; + } + + /** + * @return the service group name + */ + public String getServiceGroupName() { + return serviceGroupName; + } + + /** + * @param serviceGroupName the service group name + */ + public void setServiceGroupName(String serviceGroupName) { + this.serviceGroupName = serviceGroupName; + } + + public Long getDependencyGroupId() { + return dependencyGroupId; + } + + public void setDependencyGroupId(Long dependencyGroupId) { + this.dependencyGroupId = dependencyGroupId; + } + + public String getDependencyGroupName() { + return dependencyGroupName; + } + + public void setDependencyGroupName(String dependencyGroupName) { + this.dependencyGroupName = dependencyGroupName; + } + + public Long getDependencyClusterId() { + return dependencyClusterId; + } + + public void setDependencyClusterId(Long dependencyClusterId) { + this.dependencyClusterId = dependencyClusterId; + } + + public String getDependencyClusterName() { + return dependencyClusterName; + } + + public void setDependencyClusterName(String dependencyClusterName) { + this.dependencyClusterName = dependencyClusterName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ServiceGroupResponse that = (ServiceGroupResponse) o; + + if (clusterId != null ? + !clusterId.equals(this.clusterId) : this.clusterId != null) { + return false; + } + if (clusterName != null ? + !clusterName.equals(this.clusterName) : this.clusterName != null) { + return false; + } + if (serviceGroupName != null ? + !serviceGroupName.equals(this.serviceGroupName) : this.serviceGroupName != null) { + return false; + } + + return true; + } + + /** + * Interface to help correct Swagger documentation generation + */ + public interface ServiceGroupDependencyResponseSwagger extends ApiModel { + @ApiModelProperty(name = "ServiceGroupDependencyInfo") + ServiceResponse getServiceGroupDependencyResponse(); + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/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 60a845d..123f2fe 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 @@ -156,6 +156,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori return resourceProviderFactory.getServiceResourceProvider(managementController); case ServiceGroup: return resourceProviderFactory.getServiceGroupResourceProvider(managementController); + case ServiceGroupDependency: + return resourceProviderFactory.getServiceGroupDependencyResourceProvider(managementController); case Component: return resourceProviderFactory.getComponentResourceProvider(managementController); case Host: http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/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 c3293af..c219d23 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 @@ -88,6 +88,8 @@ public class DefaultProviderModule extends AbstractProviderModule { return new AlertResourceProvider(managementController); case ServiceGroup: return new ServiceGroupResourceProvider(managementController); + case ServiceGroupDependency: + return new ServiceGroupDependencyResourceProvider(managementController); case Registry: return new RegistryResourceProvider(managementController); case RegistryRecommendation: http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java new file mode 100644 index 0000000..78610d2 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupDependencyResourceProvider.java @@ -0,0 +1,484 @@ +/** + * 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.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.ClusterNotFoundException; +import org.apache.ambari.server.ObjectNotFoundException; +import org.apache.ambari.server.ParentObjectNotFoundException; +import org.apache.ambari.server.ServiceGroupNotFoundException; +import org.apache.ambari.server.api.services.ServiceGroupKey; +import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.KerberosHelper; +import org.apache.ambari.server.controller.RequestStatusResponse; +import org.apache.ambari.server.controller.ServiceGroupDependencyRequest; +import org.apache.ambari.server.controller.ServiceGroupDependencyResponse; +import org.apache.ambari.server.controller.spi.NoSuchParentResourceException; +import org.apache.ambari.server.controller.spi.NoSuchResourceException; +import org.apache.ambari.server.controller.spi.Predicate; +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.spi.UnsupportedPropertyException; +import org.apache.ambari.server.controller.utilities.PropertyHelper; +import org.apache.ambari.server.security.authorization.AuthorizationException; +import org.apache.ambari.server.security.authorization.AuthorizationHelper; +import org.apache.ambari.server.security.authorization.ResourceType; +import org.apache.ambari.server.security.authorization.RoleAuthorization; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Clusters; +import org.apache.ambari.server.state.ServiceGroup; +import org.apache.ambari.server.utils.StageUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.Validate; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; + +public class ServiceGroupDependencyResourceProvider extends AbstractControllerResourceProvider { + + + // ----- Property ID constants --------------------------------------------- + + public static final String RESPONSE_KEY = "ServiceGroupDependencyInfo"; + public static final String ALL_PROPERTIES = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "*"; + public static final String SERVICE_GROUP_DEPENDENCY_CLUSTER_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_id"; + public static final String SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_name"; + public static final String SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_group_id"; + public static final String SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_group_name"; + public static final String SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_cluster_id"; + public static final String SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_cluster_name"; + public static final String SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_service_group_id"; + public static final String SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "dependency_service_group_name"; + + protected ObjectMapper mapper = new ObjectMapper();; + + private static Set<String> pkPropertyIds = + new HashSet<String>(Arrays.asList(new String[]{ + SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID, + SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID, + SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID})); + + private static Gson gson = StageUtils.getGson(); + + /** + * The property ids for an service group resource. + */ + private static final Set<String> PROPERTY_IDS = new HashSet<>(); + + /** + * The key property ids for an service group resource. + */ + private static final Map<Resource.Type, String> KEY_PROPERTY_IDS = new HashMap<>(); + + static { + // properties + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_CLUSTER_ID_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID); + + // keys + KEY_PROPERTY_IDS.put(Resource.Type.Cluster, SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID); + KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroup, SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID); + KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroupDependency, SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID); + } + + private Clusters clusters; + + /** + * kerberos helper + */ + @Inject + private KerberosHelper kerberosHelper; + + // ----- Constructors ---------------------------------------------------- + + /** + * Create a new resource provider for the given management controller. + * + * @param managementController the management controller + */ + @AssistedInject + public ServiceGroupDependencyResourceProvider(@Assisted AmbariManagementController managementController) { + super(Resource.Type.ServiceGroupDependency, PROPERTY_IDS, KEY_PROPERTY_IDS, managementController); + } + + // ----- ResourceProvider ------------------------------------------------ + + @Override + protected RequestStatus createResourcesAuthorized(Request request) + throws SystemException, + UnsupportedPropertyException, + ResourceAlreadyExistsException, + NoSuchParentResourceException { + + final Set<ServiceGroupDependencyRequest> requests = new HashSet<>(); + for (Map<String, Object> propertyMap : request.getProperties()) { + requests.add(getRequest(propertyMap)); + } + Set<ServiceGroupDependencyResponse> createServiceGroups = null; + createServiceGroups = createResources(new Command<Set<ServiceGroupDependencyResponse>>() { + @Override + public Set<ServiceGroupDependencyResponse> invoke() throws AmbariException, AuthorizationException { + return createServiceGroupDependencies(requests); + } + }); + Set<Resource> associatedResources = new HashSet<>(); + if (createServiceGroups != null) { + Iterator<ServiceGroupDependencyResponse> itr = createServiceGroups.iterator(); + while (itr.hasNext()) { + ServiceGroupDependencyResponse response = itr.next(); + notifyCreate(Resource.Type.ServiceGroupDependency, request); + Resource resource = new ResourceImpl(Resource.Type.ServiceGroupDependency); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_CLUSTER_ID_PROPERTY_ID, response.getClusterId()); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID, response.getClusterName()); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID, response.getServiceGroupId()); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID, response.getServiceGroupName()); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID, response.getDependencyClusterId()); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID, response.getDependencyClusterName()); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID, response.getDependencyGroupId()); + resource.setProperty(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID, response.getDependencyGroupName()); + + associatedResources.add(resource); + } + return getRequestStatus(null, associatedResources); + } + + return getRequestStatus(null); + } + + @Override + protected Set<Resource> getResourcesAuthorized(Request request, Predicate predicate) throws + SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { + + final Set<ServiceGroupDependencyRequest> requests = new HashSet<>(); + + for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) { + requests.add(getRequest(propertyMap)); + } + + Set<ServiceGroupDependencyResponse> responses = getResources(new Command<Set<ServiceGroupDependencyResponse>>() { + @Override + public Set<ServiceGroupDependencyResponse> invoke() throws AmbariException { + return getServiceGroupDependencies(requests); + } + }); + + Set<String> requestedIds = getRequestPropertyIds(request, predicate); + Set<Resource> resources = new HashSet<Resource>(); + + for (ServiceGroupDependencyResponse response : responses) { + Resource resource = new ResourceImpl(Resource.Type.ServiceGroupDependency); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_CLUSTER_ID_PROPERTY_ID, + response.getClusterId(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID, + response.getClusterName(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID, + response.getServiceGroupId(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID, + response.getServiceGroupName(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_ID_PROPERTY_ID, + response.getDependencyClusterId(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID, + response.getDependencyClusterName(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_ID_PROPERTY_ID, + response.getDependencyGroupId(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID, + response.getDependencyGroupName(), requestedIds); + resources.add(resource); + } + return resources; + } + + @Override + protected RequestStatus updateResourcesAuthorized(final Request request, Predicate predicate) + throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { + + // TODO : Add functionality for updating SG : RENAME, START ALL, STOP ALL services. + RequestStatusResponse response = null; + return getRequestStatus(response); + } + + @Override + protected RequestStatus deleteResourcesAuthorized(Request request, Predicate predicate) + throws SystemException, UnsupportedPropertyException, NoSuchResourceException, NoSuchParentResourceException { + + final Set<ServiceGroupDependencyRequest> requests = new HashSet<>(); + DeleteStatusMetaData deleteStatusMetaData = null; + + for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) { + requests.add(getRequest(propertyMap)); + } + deleteStatusMetaData = modifyResources(new Command<DeleteStatusMetaData>() { + @Override + public DeleteStatusMetaData invoke() throws AmbariException, AuthorizationException { + deleteServiceGroupDependencies(requests); + return new DeleteStatusMetaData(); + } + }); + + notifyDelete(Resource.Type.ServiceGroupDependency, predicate); + for(ServiceGroupDependencyRequest svgReq : requests) { + deleteStatusMetaData.addDeletedKey("cluster_name: " + svgReq.getClusterName() + ", " + " service_group_name: " + svgReq.getServiceGroupName() + + "dependency_service_group_name: " + svgReq.getDependencyServiceGroupName()); + } + return getRequestStatus(null, null, deleteStatusMetaData); + } + + @Override + public Set<String> checkPropertyIds(Set<String> propertyIds) { + propertyIds = super.checkPropertyIds(propertyIds); + + if (propertyIds.isEmpty()) { + return propertyIds; + } + Set<String> unsupportedProperties = new HashSet<String>(); + return unsupportedProperties; + } + + + // ----- AbstractResourceProvider ---------------------------------------- + + @Override + protected Set<String> getPKPropertyIds() { + return pkPropertyIds; + } + + // ----- utility methods ------------------------------------------------- + + /** + * Get a service group request object from a map of property values. + * + * @param properties the predicate + * @return the service request object + */ + private ServiceGroupDependencyRequest getRequest(Map<String, Object> properties) { + String clusterName = (String) properties.get(SERVICE_GROUP_DEPENDENCY_CLUSTER_NAME_PROPERTY_ID); + String serviceGroupName = (String) properties.get(SERVICE_GROUP_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID); + String dependencyServiceGroupName = (String) properties.get(SERVICE_GROUP_DEPENDENCY_DEPENDENCY_SERVICE_GROUP_NAME_PROPERTY_ID); + ServiceGroupDependencyRequest svcRequest = new ServiceGroupDependencyRequest(clusterName, serviceGroupName, dependencyServiceGroupName); + return svcRequest; + } + + protected Set<ServiceGroupKey> getServiceGroupDependenciesSet(Set<Map<String, String>> serviceGroupDependencies) { + Set<ServiceGroupKey> serviceGroupKeys = new HashSet<>(); + if (serviceGroupDependencies != null) { + for (Map<String, String> dependencyProperties : serviceGroupDependencies) { + ServiceGroupKey serviceGroupKey = mapper.convertValue(dependencyProperties, ServiceGroupKey.class); + serviceGroupKeys.add(serviceGroupKey); + } + } + return serviceGroupKeys; + } + + // Create services from the given request. + public synchronized Set<ServiceGroupDependencyResponse> createServiceGroupDependencies(Set<ServiceGroupDependencyRequest> requests) + throws AmbariException, AuthorizationException { + + if (requests.isEmpty()) { + LOG.warn("Received an empty requests set"); + return null; + } + AmbariManagementController controller = getManagementController(); + Clusters clusters = controller.getClusters(); + + // do all validation checks + validateCreateRequests(requests, clusters); + + Set<ServiceGroupDependencyResponse> createdServiceGroupDependencies = new HashSet<>(); + for (ServiceGroupDependencyRequest request : requests) { + Cluster cluster = clusters.getCluster(request.getClusterName()); + + // Already checked that service group does not exist + ServiceGroup sg = cluster.addServiceGroupDependency(request.getServiceGroupName(), request.getDependencyServiceGroupName()); + createdServiceGroupDependencies.addAll(sg.getServiceGroupDependencyResponses()); + } + return createdServiceGroupDependencies; + } + + // Get services from the given set of requests. + protected Set<ServiceGroupDependencyResponse> getServiceGroupDependencies(Set<ServiceGroupDependencyRequest> requests) + throws AmbariException { + Set<ServiceGroupDependencyResponse> response = new HashSet<ServiceGroupDependencyResponse>(); + for (ServiceGroupDependencyRequest request : requests) { + try { + response.addAll(getServiceGroupDependencies(request)); + } catch (ServiceGroupNotFoundException e) { + if (requests.size() == 1) { + // only throw exception if 1 request. + // there will be > 1 request in case of OR predicate + throw e; + } + } + } + return response; + } + + // Get services from the given request. + private Set<ServiceGroupDependencyResponse> getServiceGroupDependencies(ServiceGroupDependencyRequest request) + throws AmbariException { + if (request.getClusterName() == null) { + throw new AmbariException("Invalid arguments, cluster id" + + " cannot be null"); + } + AmbariManagementController controller = getManagementController(); + Clusters clusters = controller.getClusters(); + String clusterName = request.getClusterName(); + + final Cluster cluster; + try { + cluster = clusters.getCluster(clusterName); + } catch (ObjectNotFoundException e) { + throw new ParentObjectNotFoundException("Parent Cluster resource doesn't exist", e); + } + + Set<ServiceGroupDependencyResponse> responses = new HashSet<>(); + if (request.getServiceGroupName() != null) { + ServiceGroup sg = cluster.getServiceGroup(request.getServiceGroupName()); + responses.addAll(sg.getServiceGroupDependencyResponses()); + return responses; + } + return responses; + } + + + // Delete services based on the given set of requests + protected void deleteServiceGroupDependencies(Set<ServiceGroupDependencyRequest> request) + throws AmbariException, AuthorizationException { + + Clusters clusters = getManagementController().getClusters(); + + Set<ServiceGroupDependencyRequest> removable = new HashSet<>(); + + for (ServiceGroupDependencyRequest serviceGroupDependencyRequest : request) { + if (null == serviceGroupDependencyRequest.getClusterName() + || StringUtils.isEmpty(serviceGroupDependencyRequest.getServiceGroupName())) { + throw new AmbariException("invalid arguments"); + } else { + + if (!AuthorizationHelper.isAuthorized( + ResourceType.CLUSTER, getClusterResourceId(serviceGroupDependencyRequest.getClusterName()), + RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) { + throw new AuthorizationException("The user is not authorized to delete service groups"); + } + + Cluster cluster = clusters.getCluster(serviceGroupDependencyRequest.getClusterName()); + ServiceGroup serviceGroup = cluster.getServiceGroup(serviceGroupDependencyRequest.getServiceGroupName()); + Set<ServiceGroupKey> serviceGroupKeys = serviceGroup.getServiceGroupDependencies(); + if (serviceGroupKeys == null || serviceGroupKeys.isEmpty()) { + throw new AmbariException("Servcie group name " + serviceGroupDependencyRequest.getServiceGroupName() + " has no" + + "dependencies, so nothing to remove."); + } else { + boolean dependencyAvailable = false; + for (ServiceGroupKey serviceGroupKey : serviceGroupKeys) { + if (serviceGroupKey.getServiceGroupName().equals(serviceGroupDependencyRequest.getDependencyServiceGroupName())) { + dependencyAvailable = true; + } + } + if (!dependencyAvailable) { + throw new AmbariException("Servcie group name " + serviceGroupDependencyRequest.getServiceGroupName() + " has no" + + "dependency " + serviceGroupDependencyRequest.getDependencyServiceGroupName() + ", so nothing to remove."); + } + + serviceGroup.getCluster().deleteServiceGroupDependency(serviceGroupDependencyRequest.getServiceGroupName(), + serviceGroupDependencyRequest.getDependencyServiceGroupName()); + } + } + } + } + + + private void validateCreateRequests(Set<ServiceGroupDependencyRequest> requests, Clusters clusters) + throws AuthorizationException, AmbariException { + + Map<String, Set<String>> serviceGroupNames = new HashMap<>(); + Set<String> duplicates = new HashSet<>(); + for (ServiceGroupDependencyRequest request : requests) { + final String clusterName = request.getClusterName(); + final String serviceGroupName = request.getServiceGroupName(); + final String dependencyServiceGroupName = request.getDependencyServiceGroupName(); + + Validate.notNull(clusterName, "Cluster name should be provided when creating a service group"); + + // validating service group dependencies + if (StringUtils.isEmpty(dependencyServiceGroupName)) { + throw new AmbariException("Service group name is empty or null!"); + } else { + Cluster cluster = clusters.getCluster(clusterName); + //throws service group not found exception + ServiceGroup serviceGroup = cluster.getServiceGroup(dependencyServiceGroupName); + + } + + Validate.notEmpty(serviceGroupName, "Service group name should be provided when adding a service group dependency"); + + if (LOG.isDebugEnabled()) { + LOG.debug("Received a createServiceGroupDependency request" + + ", clusterName=" + clusterName + ", serviceGroupName=" + serviceGroupName + ", request=" + request); + } + + if (!AuthorizationHelper.isAuthorized(ResourceType.CLUSTER, + getClusterResourceId(clusterName), RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) { + throw new AuthorizationException("The user is not authorized to create service groups"); + } + + + Cluster cluster; + try { + cluster = clusters.getCluster(clusterName); + } catch (ClusterNotFoundException e) { + throw new ParentObjectNotFoundException("Attempted to add a service group to a cluster which doesn't exist", e); + } + + // throws service group not found exception if theere is no such SG + ServiceGroup sg = cluster.getServiceGroup(serviceGroupName); + Set<ServiceGroupKey> dependencies = sg.getServiceGroupDependencies(); + if (dependencies != null) { + for (ServiceGroupKey serviceGroupKey : dependencies) { + if (serviceGroupKey.getServiceGroupName().equals(dependencyServiceGroupName)) { + throw new AmbariException("Service group " + serviceGroupName + " already have dependency for service group " + + dependencyServiceGroupName); + } + } + } + + } + } +} + + + + http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/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 ebf0e9f..3699cd0 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 @@ -78,6 +78,7 @@ public interface Resource { RootClusterSetting, Service, ServiceGroup, + ServiceGroupDependency, Setting, Host, Component, @@ -208,6 +209,7 @@ public interface Resource { public static final Type Cluster = InternalType.Cluster.getType(); public static final Type RootClusterSetting = InternalType.RootClusterSetting.getType(); public static final Type ServiceGroup = InternalType.ServiceGroup.getType(); + public static final Type ServiceGroupDependency = InternalType.ServiceGroupDependency.getType(); public static final Type Service = InternalType.Service.getType(); public static final Type Setting = InternalType.Setting.getType(); public static final Type Host = InternalType.Host.getType(); http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java index 7f8facb..1bcdd80 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java @@ -18,6 +18,9 @@ package org.apache.ambari.server.orm.entities; +import java.util.ArrayList; +import java.util.List; + import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -25,6 +28,8 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; @@ -32,7 +37,6 @@ import javax.persistence.Table; import javax.persistence.TableGenerator; - @IdClass(ServiceGroupEntityPK.class) @Table(name = "servicegroups") @NamedQueries({ @@ -66,6 +70,19 @@ public class ServiceGroupEntity { @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false) private ClusterEntity clusterEntity; + @ManyToMany + @JoinTable( + name = "servicegroupdependencies", + joinColumns = {@JoinColumn(name = "service_group_id", referencedColumnName = "id", nullable = false), + @JoinColumn(name = "service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false)}, + inverseJoinColumns = {@JoinColumn(name = "dependent_service_group_id", referencedColumnName = "id", nullable = false), + @JoinColumn(name = "dependent_service_group_cluster_id", referencedColumnName = "cluster_id", nullable = false)} + ) + private List<ServiceGroupEntity> serviceGroupDependencies = new ArrayList<>(); + + @ManyToMany(mappedBy="serviceGroupDependencies") + private List<ServiceGroupEntity> dependencies = new ArrayList<>(); + public Long getClusterId() { return clusterId; } @@ -91,6 +108,14 @@ public class ServiceGroupEntity { this.serviceGroupName = serviceGroupName; } + public List<ServiceGroupEntity> getServiceGroupDependencies() { + return serviceGroupDependencies; + } + + public void setServiceGroupDependencies(List<ServiceGroupEntity> serviceGroupDependencies) { + this.serviceGroupDependencies = serviceGroupDependencies; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -120,4 +145,4 @@ public class ServiceGroupEntity { this.clusterEntity = clusterEntity; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java index 8fd878e..5ba61b7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Cluster.java @@ -90,6 +90,8 @@ public interface Cluster { */ ServiceGroup addServiceGroup(String serviceGroupName) throws AmbariException; + ServiceGroup addServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException; + /** * Get a service * @@ -510,6 +512,8 @@ public interface Cluster { */ void deleteServiceGroup(String serviceGroupName) throws AmbariException; + void deleteServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException; + /** * Gets if the cluster can be deleted * http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java index 9850462..3d59c96 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroup.java @@ -18,8 +18,13 @@ package org.apache.ambari.server.state; +import java.util.Set; + import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.api.services.ServiceGroupKey; +import org.apache.ambari.server.controller.ServiceGroupDependencyResponse; import org.apache.ambari.server.controller.ServiceGroupResponse; +import org.apache.ambari.server.orm.entities.ServiceGroupEntity; public interface ServiceGroup { @@ -33,8 +38,14 @@ public interface ServiceGroup { Cluster getCluster(); + Set<ServiceGroupKey> getServiceGroupDependencies(); + + void setServiceGroupDependencies(Set<ServiceGroupKey> serviceGroupDependencies); + ServiceGroupResponse convertToResponse(); + Set<ServiceGroupDependencyResponse> getServiceGroupDependencyResponses(); + void debugDump(StringBuilder sb); void refresh(); @@ -47,4 +58,6 @@ public interface ServiceGroup { boolean canBeRemoved(); void delete() throws AmbariException; -} \ No newline at end of file + + ServiceGroupEntity deleteDependency(String dependencyServiceGroupName) throws AmbariException; +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupFactory.java index 7146bdf..3c5e956 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupFactory.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupFactory.java @@ -18,6 +18,9 @@ package org.apache.ambari.server.state; +import java.util.Set; + +import org.apache.ambari.server.api.services.ServiceGroupKey; import org.apache.ambari.server.orm.entities.ServiceGroupEntity; import com.google.inject.assistedinject.Assisted; @@ -25,7 +28,8 @@ import com.google.inject.assistedinject.Assisted; public interface ServiceGroupFactory { ServiceGroup createNew(Cluster cluster, - @Assisted("serviceGroupName") String serviceGroupName); + @Assisted("serviceGroupName") String serviceGroupName, + @Assisted("serviceGroupDependencies") Set<ServiceGroupKey> serviceGroupDependencies); ServiceGroup createExisting(Cluster cluster, ServiceGroupEntity serviceGroupEntity); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java index 735a946..7737c0d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceGroupImpl.java @@ -18,7 +18,15 @@ package org.apache.ambari.server.state; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.api.services.ServiceGroupKey; +import org.apache.ambari.server.controller.AmbariManagementController; +import org.apache.ambari.server.controller.ServiceGroupDependencyResponse; import org.apache.ambari.server.controller.ServiceGroupResponse; import org.apache.ambari.server.events.ServiceGroupInstalledEvent; import org.apache.ambari.server.events.ServiceGroupRemovedEvent; @@ -50,13 +58,16 @@ public class ServiceGroupImpl implements ServiceGroup { private Long serviceGroupId; private String serviceGroupName; + private Set<ServiceGroupKey> serviceGroupDependencies = new HashSet<>(); @AssistedInject public ServiceGroupImpl(@Assisted Cluster cluster, @Assisted("serviceGroupName") String serviceGroupName, + @Assisted("serviceGroupDependencies") Set<ServiceGroupKey> serviceGroupDependencies, ClusterDAO clusterDAO, ServiceGroupDAO serviceGroupDAO, - AmbariEventPublisher eventPublisher) throws AmbariException { + AmbariEventPublisher eventPublisher, + AmbariManagementController controller) throws AmbariException { this.cluster = cluster; this.clusterDAO = clusterDAO; @@ -70,6 +81,27 @@ public class ServiceGroupImpl implements ServiceGroup { serviceGroupEntity.setServiceGroupId(serviceGroupId); serviceGroupEntity.setServiceGroupName(serviceGroupName); + List<ServiceGroupEntity> serviceGroupEntities = new ArrayList<>(); + if (serviceGroupDependencies != null) { + this.serviceGroupDependencies = serviceGroupDependencies; + for (ServiceGroupKey serviceGroupKey : serviceGroupDependencies) { + Clusters clusters = controller.getClusters(); + Cluster dependencyCluster = serviceGroupKey.getClusterName() == null ? cluster : + clusters.getCluster(serviceGroupKey.getClusterName()); + serviceGroupKey.setClusterName(dependencyCluster.getClusterName()); + ServiceGroup dependencyServiceGroup = dependencyCluster.getServiceGroup(serviceGroupKey.getServiceGroupName()); + + ServiceGroupEntityPK serviceGroupEntityPK = new ServiceGroupEntityPK(); + serviceGroupEntityPK.setServiceGroupId(dependencyServiceGroup.getServiceGroupId()); + serviceGroupEntityPK.setClusterId(dependencyServiceGroup.getClusterId()); + ServiceGroupEntity dependentServiceGroupEntity = serviceGroupDAO.findByPK(serviceGroupEntityPK); + serviceGroupEntities.add(dependentServiceGroupEntity); + } + } else { + this.serviceGroupDependencies = new HashSet<>(); + } + serviceGroupEntity.setServiceGroupDependencies(serviceGroupEntities); + this.serviceGroupEntityPK = getServiceGroupEntityPK(serviceGroupEntity); persist(serviceGroupEntity); } @@ -87,6 +119,7 @@ public class ServiceGroupImpl implements ServiceGroup { this.serviceGroupId = serviceGroupEntity.getServiceGroupId(); this.serviceGroupName = serviceGroupEntity.getServiceGroupName(); + this.serviceGroupDependencies = getServiceGroupDependencies(serviceGroupEntity.getServiceGroupDependencies()); this.serviceGroupEntityPK = getServiceGroupEntityPK(serviceGroupEntity); } @@ -115,6 +148,16 @@ public class ServiceGroupImpl implements ServiceGroup { } @Override + public Set<ServiceGroupKey> getServiceGroupDependencies() { + return serviceGroupDependencies; + } + + @Override + public void setServiceGroupDependencies(Set<ServiceGroupKey> serviceGroupDependencies) { + this.serviceGroupDependencies = serviceGroupDependencies; + } + + @Override public ServiceGroupResponse convertToResponse() { ServiceGroupResponse r = new ServiceGroupResponse(cluster.getClusterId(), cluster.getClusterName(), getServiceGroupId(), getServiceGroupName()); @@ -122,6 +165,61 @@ public class ServiceGroupImpl implements ServiceGroup { } @Override + public Set<ServiceGroupDependencyResponse> getServiceGroupDependencyResponses() { + Set<ServiceGroupDependencyResponse> responses = new HashSet<>(); + if (getServiceGroupDependencies() != null) { + for (ServiceGroupKey sgk : getServiceGroupDependencies()) { + responses.add(new ServiceGroupDependencyResponse(cluster.getClusterId(), cluster.getClusterName(), + serviceGroupId, serviceGroupName, sgk.getClusterId(), sgk.getClusterName(), sgk.getServiceGroupId(), sgk.getServiceGroupName())); + } + } + return responses; + } + + public Set<ServiceGroupKey> getServiceGroupDependencies(List<ServiceGroupEntity> serviceGroupDependencies) { + Set<ServiceGroupKey> serviceGroupDependenciesList = new HashSet<>(); + if (serviceGroupDependencies != null) { + for (ServiceGroupEntity sge : serviceGroupDependencies) { + ServiceGroupKey serviceGroupKey = new ServiceGroupKey(); + String clusterName = ""; + Long clusterId = null; + if (sge.getClusterId() == cluster.getClusterId()) { + clusterName = cluster.getClusterName(); + clusterId = cluster.getClusterId(); + } else { + ClusterEntity clusterEntity = clusterDAO.findById(sge.getClusterId()); + if (clusterEntity != null) { + clusterName = clusterEntity.getClusterName(); + clusterId = clusterEntity.getClusterId(); + } else { + LOG.error("Unable to get cluster id for service group " + sge.getServiceGroupName()); + } + } + + ServiceGroupEntityPK serviceGroupEntityPK = new ServiceGroupEntityPK(); + serviceGroupEntityPK.setClusterId(sge.getClusterId()); + serviceGroupEntityPK.setServiceGroupId(sge.getServiceGroupId()); + ServiceGroupEntity serviceGroupEntity = serviceGroupDAO.findByPK(serviceGroupEntityPK); + String serviceGroupDependencyName = ""; + Long serviceGroupDependencId = null; + if (serviceGroupEntity != null) { + serviceGroupDependencyName = serviceGroupEntity.getServiceGroupName(); + serviceGroupDependencId = serviceGroupEntity.getServiceGroupId(); + } else { + LOG.error("Unable to get service group entity for service group " + sge.getServiceGroupName()); + } + + serviceGroupKey.setServiceGroupName(serviceGroupDependencyName); + serviceGroupKey.setServiceGroupId(serviceGroupDependencId); + serviceGroupKey.setClusterName(clusterName); + serviceGroupKey.setClusterId(clusterId); + serviceGroupDependenciesList.add(serviceGroupKey); + } + } + return serviceGroupDependenciesList; + } + + @Override public Cluster getCluster() { return cluster; } @@ -190,6 +288,25 @@ public class ServiceGroupImpl implements ServiceGroup { eventPublisher.publish(event); } + @Override + @Transactional + public ServiceGroupEntity deleteDependency(String dependencyServiceGroupName) throws AmbariException { + ServiceGroupEntityPK pk = new ServiceGroupEntityPK(); + pk.setClusterId(getClusterId()); + pk.setServiceGroupId(getServiceGroupId()); + ServiceGroupEntity serviceGroupEntity = serviceGroupDAO.findByPK(pk); + ServiceGroupEntity dependencyToRemove = null; + for (ServiceGroupEntity dependency : serviceGroupEntity.getServiceGroupDependencies()) { + if (dependency.getServiceGroupName().equals(dependencyServiceGroupName)) { + dependencyToRemove = dependency; + break; + } + } + serviceGroupEntity.getServiceGroupDependencies().remove(dependencyToRemove); + serviceGroupEntity = serviceGroupDAO.merge(serviceGroupEntity); + return serviceGroupEntity; + } + @Transactional protected void removeEntities() throws AmbariException { @@ -210,4 +327,4 @@ public class ServiceGroupImpl implements ServiceGroup { pk.setServiceGroupId(serviceGroupEntity.getServiceGroupId()); return pk; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java index 1e4d81f..e896d0e 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/ClusterImpl.java @@ -54,6 +54,7 @@ import org.apache.ambari.server.ServiceGroupNotFoundException; import org.apache.ambari.server.ServiceNotFoundException; import org.apache.ambari.server.agent.ExecutionCommand.KeyNames; import org.apache.ambari.server.api.services.AmbariMetaInfo; +import org.apache.ambari.server.api.services.ServiceGroupKey; import org.apache.ambari.server.controller.AmbariSessionManager; import org.apache.ambari.server.controller.ClusterResponse; import org.apache.ambari.server.controller.ConfigurationResponse; @@ -81,6 +82,7 @@ import org.apache.ambari.server.orm.dao.HostConfigMappingDAO; import org.apache.ambari.server.orm.dao.HostDAO; import org.apache.ambari.server.orm.dao.HostVersionDAO; import org.apache.ambari.server.orm.dao.ServiceConfigDAO; +import org.apache.ambari.server.orm.dao.ServiceGroupDAO; import org.apache.ambari.server.orm.dao.StackDAO; import org.apache.ambari.server.orm.dao.TopologyRequestDAO; import org.apache.ambari.server.orm.dao.UpgradeDAO; @@ -99,6 +101,7 @@ import org.apache.ambari.server.orm.entities.ResourceEntity; import org.apache.ambari.server.orm.entities.ServiceConfigEntity; import org.apache.ambari.server.orm.entities.ServiceDesiredStateEntity; import org.apache.ambari.server.orm.entities.ServiceGroupEntity; +import org.apache.ambari.server.orm.entities.ServiceGroupEntityPK; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.orm.entities.TopologyRequestEntity; import org.apache.ambari.server.orm.entities.UpgradeEntity; @@ -273,6 +276,9 @@ public class ClusterImpl implements Cluster { @Inject private TopologyRequestDAO topologyRequestDAO; + @Inject + private ServiceGroupDAO serviceGroupDAO; + /** * Data access object used for looking up stacks from the database. */ @@ -905,7 +911,43 @@ public class ClusterImpl implements Cluster { + ", clusterId=" + getClusterId() + ", serviceGroupName=" + serviceGroupName); } - ServiceGroup serviceGroup = serviceGroupFactory.createNew(this, serviceGroupName); + ServiceGroup serviceGroup = serviceGroupFactory.createNew(this, serviceGroupName, new HashSet<ServiceGroupKey>()); + addServiceGroup(serviceGroup); + return serviceGroup; + } + + @Override + public ServiceGroup addServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException { + if (!serviceGroups.containsKey(serviceGroupName)) { + throw new AmbariException("Service group doesn't exist" + ", clusterName=" + getClusterName() + + ", clusterId=" + getClusterId() + ", serviceGroupName=" + serviceGroupName); + } + + if (!serviceGroups.containsKey(dependencyServiceGroupName)) { + throw new AmbariException("Dependent service group doesn't exist" + ", clusterName=" + getClusterName() + + ", clusterId=" + getClusterId() + ", serviceGroupName=" + serviceGroupName); + } + + ServiceGroupEntity serviceGroupEntity = null; + clusterGlobalLock.writeLock().lock(); + try { + ServiceGroupEntityPK serviceGroupEntityPK = new ServiceGroupEntityPK(); + serviceGroupEntityPK.setClusterId(getClusterId()); + serviceGroupEntityPK.setServiceGroupId(serviceGroups.get(serviceGroupName).getServiceGroupId()); + serviceGroupEntity = serviceGroupDAO.findByPK(serviceGroupEntityPK); + + ServiceGroupEntityPK dependencyServiceGroupEntityPK = new ServiceGroupEntityPK(); + dependencyServiceGroupEntityPK.setClusterId(getClusterId()); + dependencyServiceGroupEntityPK.setServiceGroupId(serviceGroups.get(dependencyServiceGroupName).getServiceGroupId()); + ServiceGroupEntity dependencyServiceGroupEntity = serviceGroupDAO.findByPK(dependencyServiceGroupEntityPK); + + serviceGroupEntity.getServiceGroupDependencies().add(dependencyServiceGroupEntity); + serviceGroupEntity = serviceGroupDAO.merge(serviceGroupEntity); + } finally { + clusterGlobalLock.writeLock().unlock(); + } + + ServiceGroup serviceGroup = serviceGroupFactory.createExisting(this, serviceGroupEntity); addServiceGroup(serviceGroup); return serviceGroup; } @@ -1409,6 +1451,24 @@ public class ClusterImpl implements Cluster { } } + @Override + public void deleteServiceGroupDependency(String serviceGroupName, String dependencyServiceGroupName) throws AmbariException { + clusterGlobalLock.writeLock().lock(); + try { + ServiceGroup serviceGroup = getServiceGroup(serviceGroupName); + LOG.info("Deleting service group dependency, dependencyServiceGroupName=" + dependencyServiceGroupName + " in cluster" + ", clusterName=" + + getClusterName() + ", serviceGroupName=" + serviceGroup.getServiceGroupName()); + + Long serviceGroupId = serviceGroup.getServiceGroupId(); + ServiceGroupEntity serviceGroupEntity = serviceGroup.deleteDependency(dependencyServiceGroupName); + ServiceGroup updatedServiceGroup = serviceGroupFactory.createExisting(this, serviceGroupEntity); + serviceGroups.put(updatedServiceGroup.getServiceGroupName(), updatedServiceGroup); + serviceGroupsById.put(updatedServiceGroup.getServiceGroupId(), updatedServiceGroup); + } finally { + clusterGlobalLock.writeLock().unlock(); + } + } + /** * Deletes the specified service also removes references to it from {@link this.serviceComponentHosts} * and references to ServiceComponentHost objects that belong to the service from {@link this.serviceComponentHostsByHost} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java index 9270e7d..fda0566 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java @@ -61,6 +61,7 @@ import org.apache.ambari.server.controller.internal.HostComponentResourceProvide import org.apache.ambari.server.controller.internal.HostResourceProvider; import org.apache.ambari.server.controller.internal.ProvisionClusterRequest; import org.apache.ambari.server.controller.internal.RequestImpl; +import org.apache.ambari.server.controller.internal.ServiceGroupDependencyResourceProvider; import org.apache.ambari.server.controller.internal.ServiceGroupResourceProvider; import org.apache.ambari.server.controller.internal.ServiceResourceProvider; import org.apache.ambari.server.controller.internal.VersionDefinitionResourceProvider; @@ -128,6 +129,7 @@ public class AmbariContext { private static HostRoleCommandFactory hostRoleCommandFactory; private static HostResourceProvider hostResourceProvider; private static ServiceGroupResourceProvider serviceGroupResourceProvider; + private static ServiceGroupDependencyResourceProvider serviceGroupDependencyResourceProvider; private static ServiceResourceProvider serviceResourceProvider; private static ComponentResourceProvider componentResourceProvider; private static HostComponentResourceProvider hostComponentResourceProvider; @@ -771,6 +773,14 @@ public class AmbariContext { return serviceGroupResourceProvider; } + private synchronized ServiceGroupDependencyResourceProvider getServiceGroupDependencyResourceProvider() { + if (serviceGroupDependencyResourceProvider == null) { + serviceGroupResourceProvider = (ServiceGroupResourceProvider) ClusterControllerHelper. + getClusterController().ensureResourceProvider(Resource.Type.ServiceGroupDependency); + } + return serviceGroupDependencyResourceProvider; + } + private synchronized ServiceResourceProvider getServiceResourceProvider() { if (serviceResourceProvider == null) { serviceResourceProvider = (ServiceResourceProvider) ClusterControllerHelper. @@ -796,4 +806,4 @@ public class AmbariContext { } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql index ce201e4..19e23c5 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -177,6 +177,15 @@ CREATE TABLE servicegroups ( CONSTRAINT PK_servicegroups PRIMARY KEY (id, cluster_id), CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id)); +CREATE TABLE servicegroupdependencies ( + service_group_id BIGINT NOT NULL, + service_group_cluster_id BIGINT NOT NULL, + dependent_service_group_id BIGINT NOT NULL, + dependent_service_group_cluster_id BIGINT NOT NULL, + CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id), + CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id)); + CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id)); + CREATE TABLE clusterservices ( id BIGINT NOT NULL, service_name VARCHAR(255) NOT NULL, http://git-wip-us.apache.org/repos/asf/ambari/blob/16913b20/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index f4d9554..b1990df 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -196,6 +196,15 @@ CREATE TABLE servicegroups ( CONSTRAINT PK_servicegroups PRIMARY KEY (id, cluster_id), CONSTRAINT FK_servicegroups_cluster_id FOREIGN KEY (cluster_id) REFERENCES clusters (cluster_id)); +CREATE TABLE servicegroupdependencies ( + service_group_id BIGINT NOT NULL, + service_group_cluster_id BIGINT NOT NULL, + dependent_service_group_id BIGINT NOT NULL, + dependent_service_group_cluster_id BIGINT NOT NULL, + CONSTRAINT PK_servicegroupdependencies PRIMARY KEY (service_group_id, service_group_cluster_id, dependent_service_group_id, dependent_service_group_cluster_id), + CONSTRAINT FK_servicegroupdependencies_service_group_cluster_id FOREIGN KEY (service_group_id, service_group_cluster_id) REFERENCES servicegroups (id, cluster_id)); + CONSTRAINT FK_servicegroupdependencies_dependent_service_group_cluster_id FOREIGN KEY (dependent_service_group_id, dependent_service_group_cluster_id) REFERENCES servicegroups (id, cluster_id)); + CREATE TABLE clusterservices ( id BIGINT NOT NULL, service_name VARCHAR(255) NOT NULL,
