AMBARI-21594. MultiEverything : Add Servicegroup as a subresource of Cluster.
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2f1f96ef Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2f1f96ef Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2f1f96ef Branch: refs/heads/branch-feature-AMBARI-14714 Commit: 2f1f96ef5b705172775d15925d24a97b14960212 Parents: e8c0954 Author: Swapan Shridhar <[email protected]> Authored: Fri Jul 28 16:15:24 2017 -0700 Committer: Swapan Shridhar <[email protected]> Committed: Wed Aug 2 01:29:22 2017 -0700 ---------------------------------------------------------------------- .../server/ServiceGroupNotFoundException.java | 35 ++ .../resources/ClusterResourceDefinition.java | 1 + .../resources/ResourceInstanceFactoryImpl.java | 4 + .../ServiceGroupResourceDefinition.java | 54 +++ .../server/api/services/ClusterService.java | 12 + .../api/services/ServiceGroupService.java | 283 ++++++++++++ .../controller/AmbariManagementController.java | 8 + .../AmbariManagementControllerImpl.java | 9 +- .../server/controller/ControllerModule.java | 7 + .../controller/ResourceProviderFactory.java | 3 + .../server/controller/ServiceGroupRequest.java | 65 +++ .../server/controller/ServiceGroupResponse.java | 124 +++++ .../AbstractControllerResourceProvider.java | 2 + .../internal/DefaultProviderModule.java | 2 + .../internal/ServiceGroupResourceProvider.java | 456 +++++++++++++++++++ .../ambari/server/controller/spi/Resource.java | 2 + .../ambari/server/events/AmbariEvent.java | 10 + .../ambari/server/events/ServiceGroupEvent.java | 49 ++ .../events/ServiceGroupInstalledEvent.java | 46 ++ .../server/events/ServiceGroupRemovedEvent.java | 46 ++ .../ambari/server/orm/dao/ServiceGroupDAO.java | 93 ++++ .../server/orm/entities/ClusterEntity.java | 61 ++- .../server/orm/entities/ServiceGroupEntity.java | 123 +++++ .../orm/entities/ServiceGroupEntityPK.java | 71 +++ .../servicegroup/ServiceGroupServerAction.java | 92 ++++ .../org/apache/ambari/server/state/Cluster.java | 239 ++++++---- .../ambari/server/state/ServiceGroup.java | 50 ++ .../server/state/ServiceGroupFactory.java | 31 ++ .../ambari/server/state/ServiceGroupImpl.java | 213 +++++++++ .../server/state/cluster/ClusterImpl.java | 413 ++++++++++------- .../main/resources/Ambari-DDL-Derby-CREATE.sql | 9 + .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 8 + .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 8 + .../resources/Ambari-DDL-Postgres-CREATE.sql | 8 + .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 8 + .../resources/Ambari-DDL-SQLServer-CREATE.sql | 8 + .../src/main/resources/META-INF/persistence.xml | 1 + .../ambari/server/agent/AgentResourceTest.java | 5 + .../ClusterResourceDefinitionTest.java | 3 +- .../ActiveWidgetLayoutResourceProviderTest.java | 2 + .../UserAuthorizationResourceProviderTest.java | 2 + .../internal/UserResourceProviderTest.java | 2 + 42 files changed, 2403 insertions(+), 265 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/ServiceGroupNotFoundException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/ServiceGroupNotFoundException.java b/ambari-server/src/main/java/org/apache/ambari/server/ServiceGroupNotFoundException.java new file mode 100644 index 0000000..39378ef --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/ServiceGroupNotFoundException.java @@ -0,0 +1,35 @@ +/** + * 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; + +@SuppressWarnings("serial") +public class ServiceGroupNotFoundException extends ObjectNotFoundException { + + public ServiceGroupNotFoundException(String clusterName, String serviceGroupName) { + super("ServiceGroup not found" + + ", clusterName=" + clusterName + + ", serviceGroupName=" + serviceGroupName); + } + + public ServiceGroupNotFoundException(String clusterName, Long serviceGroupId) { + super("ServiceGroup not found" + + ", clusterName=" + clusterName + + ", serviceGroupId=" + serviceGroupId); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java index f689841..24c2810 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ClusterResourceDefinition.java @@ -62,6 +62,7 @@ public class ClusterResourceDefinition extends BaseResourceDefinition { public Set<SubResourceDefinition> getSubResourceDefinitions() { Set<SubResourceDefinition> setChildren = new HashSet<>(); setChildren.add(new SubResourceDefinition(Resource.Type.Service)); + setChildren.add(new SubResourceDefinition(Resource.Type.ServiceGroup)); setChildren.add(new SubResourceDefinition(Resource.Type.Host)); setChildren.add(new SubResourceDefinition(Resource.Type.Configuration)); setChildren.add(new SubResourceDefinition(Resource.Type.ServiceConfigVersion)); http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 73963df..f43c5d9 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 @@ -104,6 +104,10 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory { resourceDefinition = new ClusterResourceDefinition(); break; + case ServiceGroup: + resourceDefinition = new ServiceGroupResourceDefinition(); + break; + case Service: resourceDefinition = new ServiceResourceDefinition(); break; http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 new file mode 100644 index 0000000..f686851 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ServiceGroupResourceDefinition.java @@ -0,0 +1,54 @@ +/** + * 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; + +/** + * Service group resource definition. + */ +public class ServiceGroupResourceDefinition extends BaseResourceDefinition { + + /** + * Constructor. + * + */ + public ServiceGroupResourceDefinition() { + super(Resource.Type.ServiceGroup); + } + + @Override + public String getPluralName() { + return "servicegroups"; + } + + @Override + public String getSingularName() { + return "servicegroup"; + } + + /* TODO: To be called when Services become sub-resource of ServiceGroup. + @Override + public Set<SubResourceDefinition> getSubResourceDefinitions() { + Set<SubResourceDefinition> subs = new HashSet<SubResourceDefinition>(); + subs.add(new SubResourceDefinition(Resource.Type.Service)); + return subs; + } + */ +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java index 44d50731..c38489d 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java @@ -510,6 +510,18 @@ public class ClusterService extends BaseService { } /** + * Get the servicegroups sub-resource + * + * @param request the request + * @param clusterName cluster Name + * @return the service groups service + */ + @Path("{clusterName}/servicegroups") + public ServiceGroupService getServiceGroupHandler(@Context javax.ws.rs.core.Request request, @ApiParam @PathParam("clusterName") String clusterName) { + return new ServiceGroupService(clusterName); + } + + /** * Gets the configurations sub-resource. * * @param request the request http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 new file mode 100644 index 0000000..aa1270a --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ServiceGroupService.java @@ -0,0 +1,283 @@ +/** + * 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 java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +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.server.api.resources.ResourceInstance; +import org.apache.ambari.server.controller.ServiceGroupResponse; +import org.apache.ambari.server.controller.spi.Resource; +import org.apache.http.HttpStatus; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +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"; + + /** + * Parent cluster Name. + */ + private String m_clusterName; + + /** + * Constructor. + * + * @param clusterName cluster Name + */ + public ServiceGroupService(String clusterName) { + super(); + m_clusterName = clusterName; + } + + /** + * Handles: POST /clusters/{clusterName}/servicegroups + * Create multiple servicegroups. + * + * @param body http body + * @param headers http headers + * @param ui uri info + * @return information regarding the created servicegroups + */ + @POST + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Creates a servicegroup", + nickname = "ServiceGroupService#createServiceGroups" + ) + @ApiImplicitParams({ + @ApiImplicitParam(dataType = SERVICE_GROUP_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 createServiceGroups(String body, @Context HttpHeaders headers, @Context UriInfo ui) { + + return handleRequest(headers, body, ui, Request.Type.POST, + createServiceGroupResource(m_clusterName, null)); + } + + /** + * Handles URL: /clusters/{clusterName}/servicegroups + * Get all servicegroups for a cluster. + * + * @param headers http headers + * @param ui uri info + * @return service collection resource representation + */ + @GET + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Get all servicegroups", + nickname = "ServiceGroupService#getServiceGroups", + notes = "Returns all servicegroups.", + response = ServiceGroupResponse.ServiceGroupResponseSwagger.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 getServiceGroups(String body, @Context HttpHeaders headers, @Context UriInfo ui) { + return handleRequest(headers, body, ui, Request.Type.GET, + createServiceGroupResource(m_clusterName, null)); + } + + /** + * Handles URL: /clusters/{clusterName}/servicegroups/{serviceGroupName} + * Get a specific servicegroup. + * + * @param headers http headers + * @param ui uri info + * @param serviceGroupName service group name + * @return servicegroup resource representation + */ + @GET + @Path("{serviceGroupName}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Get the details of a servicegroup", + nickname = "ServiceGroupService#getServiceGroup", + notes = "Returns the details of a servicegroup", + 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 getServiceGroup(String body, @Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("serviceGroupName") String serviceGroupName) { + + return handleRequest(headers, body, ui, Request.Type.GET, + createServiceGroupResource(m_clusterName, serviceGroupName)); + } + + /** + * Handles: PUT /clusters/{clusterName}/servicegroups + * Update multiple servicegroups. + * + * @param body http body + * @param headers http headers + * @param ui uri info + * @return information regarding the updated servicegroups + */ + @PUT + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Updates multiple servicegroups", + nickname = "ServiceGroupService#updateServiceGroups" + ) + @ApiImplicitParams({ + @ApiImplicitParam(dataType = SERVICE_GROUP_REQUEST_TYPE, paramType = PARAM_TYPE_BODY) + }) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_OK, 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_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 updateServiceGroups(String body, @Context HttpHeaders headers, @Context UriInfo ui) { + + return handleRequest(headers, body, ui, Request.Type.PUT, createServiceGroupResource(m_clusterName, null)); + } + + /** + * Handles: PUT /clusters/{clusterName}/servicegroups/{serviceGroupName} + * Update a specific servicegroup. + * + * @param body http body + * @param headers http headers + * @param ui uri info + * @param serviceGroupName service group name + * @return information regarding the updated servicegroup + */ + @PUT + @Path("{serviceGroupName}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Updates a servicegroup", + nickname = "ServiceGroupService#updateServiceGroup" + ) + @ApiImplicitParams({ + @ApiImplicitParam(dataType = SERVICE_GROUP_REQUEST_TYPE, paramType = PARAM_TYPE_BODY) + }) + @ApiResponses({ + @ApiResponse(code = HttpStatus.SC_OK, 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_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 updateServiceGroup(String body, @Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("serviceGroupName") String serviceGroupName) { + + return handleRequest(headers, body, ui, Request.Type.PUT, createServiceGroupResource(m_clusterName, serviceGroupName)); + } + + /** + * Handles: DELETE /clusters/{clusterName}/servicegroups/{serviceGroupName} + * Delete a specific servicegroup. + + * @param headers http headers + * @param ui uri info + * @param serviceGroupName service group name + * @return information regarding the deleted servicegroup + */ + @DELETE + @Path("{serviceGroupName}") + @Produces(MediaType.TEXT_PLAIN) + @ApiOperation(value = "Deletes a servicegroup", + nickname = "ServiceGroupService#deleteServiceGroup" + ) + @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 deleteServiceGroup(@Context HttpHeaders headers, @Context UriInfo ui, + @PathParam("serviceGroupName") String serviceGroupName) { + + return handleRequest(headers, null, ui, Request.Type.DELETE, createServiceGroupResource(m_clusterName, serviceGroupName)); + } + + /** + * Create a service resource instance. + * + * @param clusterName cluster Name + * @param serviceGroupName servicegroup Name + * + * @return a service resource instance + */ + ResourceInstance createServiceGroupResource(String clusterName, String serviceGroupName) { + Map<Resource.Type, String> mapIds = new HashMap<>(); + mapIds.put(Resource.Type.Cluster, clusterName); + mapIds.put(Resource.Type.ServiceGroup, serviceGroupName); + + + return createResource(Resource.Type.ServiceGroup, mapIds); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java index d792717..663d857 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java @@ -62,6 +62,7 @@ import org.apache.ambari.server.state.Service; import org.apache.ambari.server.state.ServiceComponent; import org.apache.ambari.server.state.ServiceComponentFactory; import org.apache.ambari.server.state.ServiceComponentHost; +import org.apache.ambari.server.state.ServiceGroupFactory; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.ServiceOsSpecific; import org.apache.ambari.server.state.StackId; @@ -566,6 +567,13 @@ public interface AmbariManagementController { AmbariMetaInfo getAmbariMetaInfo(); /** + * Get the service groups factory for this management controller. + * + * @return the service factory + */ + ServiceGroupFactory getServiceGroupFactory(); + + /** * Get the service component factory for this management controller. * * @return the service component factory http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java index 12e4a08..0f45270 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java @@ -182,6 +182,7 @@ import org.apache.ambari.server.state.ServiceComponentFactory; import org.apache.ambari.server.state.ServiceComponentHost; import org.apache.ambari.server.state.ServiceComponentHostEvent; import org.apache.ambari.server.state.ServiceComponentHostFactory; +import org.apache.ambari.server.state.ServiceGroupFactory; import org.apache.ambari.server.state.ServiceInfo; import org.apache.ambari.server.state.ServiceOsSpecific; import org.apache.ambari.server.state.StackId; @@ -266,7 +267,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle @Inject private RoleCommandOrderProvider roleCommandOrderProvider; - + @Inject + private ServiceGroupFactory serviceGroupFactory; @Inject private ServiceComponentFactory serviceComponentFactory; @Inject @@ -5139,6 +5141,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle } @Override + public ServiceGroupFactory getServiceGroupFactory() { + return serviceGroupFactory; + } + + @Override public ServiceComponentFactory getServiceComponentFactory() { return serviceComponentFactory; } http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 28c0d10..e09f433 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 @@ -70,6 +70,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.ServiceGroupResourceProvider; import org.apache.ambari.server.controller.internal.ServiceResourceProvider; import org.apache.ambari.server.controller.internal.UpgradeResourceProvider; import org.apache.ambari.server.controller.logging.LoggingRequestHelperFactory; @@ -133,6 +134,9 @@ import org.apache.ambari.server.state.ServiceComponentHost; import org.apache.ambari.server.state.ServiceComponentHostFactory; import org.apache.ambari.server.state.ServiceComponentImpl; import org.apache.ambari.server.state.ServiceFactory; +import org.apache.ambari.server.state.ServiceGroup; +import org.apache.ambari.server.state.ServiceGroupFactory; +import org.apache.ambari.server.state.ServiceGroupImpl; import org.apache.ambari.server.state.ServiceImpl; import org.apache.ambari.server.state.UpgradeContextFactory; import org.apache.ambari.server.state.cluster.ClusterFactory; @@ -461,11 +465,14 @@ public class ControllerModule extends AbstractModule { Host.class, HostImpl.class).build(HostFactory.class)); install(new FactoryModuleBuilder().implement( Service.class, ServiceImpl.class).build(ServiceFactory.class)); + install(new FactoryModuleBuilder().implement( + ServiceGroup.class, ServiceGroupImpl.class).build(ServiceGroupFactory.class)); install(new FactoryModuleBuilder() .implement(ResourceProvider.class, Names.named("host"), HostResourceProvider.class) .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("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/2f1f96ef/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 3912138..d88d2ff 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 @@ -43,6 +43,9 @@ public interface ResourceProviderFactory { @Named("service") ResourceProvider getServiceResourceProvider(AmbariManagementController managementController); + @Named("servicegroup") + ResourceProvider getServiceGroupResourceProvider(AmbariManagementController managementController); + @Named("component") ResourceProvider getComponentResourceProvider(AmbariManagementController managementController); http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java new file mode 100644 index 0000000..53c3d1e --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupRequest.java @@ -0,0 +1,65 @@ +/** + * 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 ServiceGroupRequest { + + private String clusterName; // REF + private String serviceGroupName; // GET/CREATE/UPDATE/DELETE + + public ServiceGroupRequest(String clusterName, String serviceGroupName) { + this.clusterName = clusterName; + this.serviceGroupName = serviceGroupName; + } + + /** + * @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 toString() { + StringBuilder sb = new StringBuilder(); + sb.append("clusterName=" + clusterName + + ", serviceGroupName=" + serviceGroupName); + return sb.toString(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.java new file mode 100644 index 0000000..147650c --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceGroupResponse.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.controller; + +import io.swagger.annotations.ApiModelProperty; + +public class ServiceGroupResponse { + + private Long clusterId; + private Long serviceGroupId; + private String clusterName; + private String serviceGroupName; + + public ServiceGroupResponse(Long clusterId, String clusterName, Long serviceGroupId, String serviceGroupName) { + this.clusterId = clusterId; + this.serviceGroupId = serviceGroupId; + this.clusterName = clusterName; + this.serviceGroupName = serviceGroupName; + } + + /** + * @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; + } + + @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(that.clusterId) : that.clusterId != null) { + return false; + } + if (clusterName != null ? + !clusterName.equals(that.clusterName) : that.clusterName != null) { + return false; + } + if (serviceGroupName != null ? + !serviceGroupName.equals(that.serviceGroupName) : that.serviceGroupName != null) { + return false; + } + + return true; + } + + /** + * Interface to help correct Swagger documentation generation + */ + public interface ServiceGroupResponseSwagger extends ApiModel { + @ApiModelProperty(name = "ServiceGroupInfo") + ServiceResponse getServiceGroupResponse(); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 3228a7f..e8876fb 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 @@ -154,6 +154,8 @@ public abstract class AbstractControllerResourceProvider extends AbstractAuthori return new ClusterResourceProvider(managementController); case Service: return resourceProviderFactory.getServiceResourceProvider(managementController); + case ServiceGroup: + return resourceProviderFactory.getServiceGroupResourceProvider(managementController); case Component: return resourceProviderFactory.getComponentResourceProvider(managementController); case Host: http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 248abad..05e79f4 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 @@ -90,6 +90,8 @@ public class DefaultProviderModule extends AbstractProviderModule { return new GroupPrivilegeResourceProvider(); case Alert: return new AlertResourceProvider(managementController); + case ServiceGroup: + return new ServiceGroupResourceProvider(managementController); case Registry: return new RegistryResourceProvider(managementController); case RegistryRecommendation: http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java new file mode 100644 index 0000000..2e935af --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceGroupResourceProvider.java @@ -0,0 +1,456 @@ +/** + * 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.DuplicateResourceException; +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.AmbariMetaInfo; +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.ServiceGroupRequest; +import org.apache.ambari.server.controller.ServiceGroupResponse; +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.google.gson.Gson; +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; +import com.google.inject.assistedinject.AssistedInject; + +/** + * Resource provider for service resources. + **/ + +public class ServiceGroupResourceProvider extends AbstractControllerResourceProvider { + + + // ----- Property ID constants --------------------------------------------- + + public static final String RESPONSE_KEY = "ServiceGroupInfo"; + public static final String ALL_PROPERTIES = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "*"; + public static final String SERVICE_GROUP_CLUSTER_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_id"; + public static final String SERVICE_GROUP_CLUSTER_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "cluster_name"; + public static final String SERVICE_GROUP_SERVICE_GROUP_ID_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_group_id"; + public static final String SERVICE_GROUP_SERVICE_GROUP_NAME_PROPERTY_ID = RESPONSE_KEY + PropertyHelper.EXTERNAL_PATH_SEP + "service_group_name"; + + private static Set<String> pkPropertyIds = + new HashSet<String>(Arrays.asList(new String[]{ + SERVICE_GROUP_CLUSTER_NAME_PROPERTY_ID, + SERVICE_GROUP_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_CLUSTER_ID_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_CLUSTER_NAME_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_SERVICE_GROUP_ID_PROPERTY_ID); + PROPERTY_IDS.add(SERVICE_GROUP_SERVICE_GROUP_NAME_PROPERTY_ID); + + // keys + KEY_PROPERTY_IDS.put(Resource.Type.Cluster, SERVICE_GROUP_CLUSTER_NAME_PROPERTY_ID); + KEY_PROPERTY_IDS.put(Resource.Type.ServiceGroup, SERVICE_GROUP_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 ServiceGroupResourceProvider(@Assisted AmbariManagementController managementController) { + super(Resource.Type.ServiceGroup, PROPERTY_IDS, KEY_PROPERTY_IDS, managementController); + } + + // ----- ResourceProvider ------------------------------------------------ + + @Override + protected RequestStatus createResourcesAuthorized(Request request) + throws SystemException, + UnsupportedPropertyException, + ResourceAlreadyExistsException, + NoSuchParentResourceException { + + final Set<ServiceGroupRequest> requests = new HashSet<>(); + for (Map<String, Object> propertyMap : request.getProperties()) { + requests.add(getRequest(propertyMap)); + } + Set<ServiceGroupResponse> createServiceGroups = null; + createServiceGroups = createResources(new Command<Set<ServiceGroupResponse>>() { + @Override + public Set<ServiceGroupResponse> invoke() throws AmbariException, AuthorizationException { + return createServiceGroups(requests); + } + }); + Set<Resource> associatedResources = new HashSet<>(); + if (createServiceGroups != null) { + Iterator<ServiceGroupResponse> itr = createServiceGroups.iterator(); + while (itr.hasNext()) { + ServiceGroupResponse response = itr.next(); + notifyCreate(Resource.Type.ServiceGroup, request); + Resource resource = new ResourceImpl(Resource.Type.ServiceGroup); + resource.setProperty(SERVICE_GROUP_CLUSTER_ID_PROPERTY_ID, response.getClusterId()); + resource.setProperty(SERVICE_GROUP_CLUSTER_NAME_PROPERTY_ID, response.getClusterName()); + resource.setProperty(SERVICE_GROUP_SERVICE_GROUP_ID_PROPERTY_ID, response.getServiceGroupId()); + resource.setProperty(SERVICE_GROUP_SERVICE_GROUP_NAME_PROPERTY_ID, response.getServiceGroupName()); + + 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<ServiceGroupRequest> requests = new HashSet<>(); + + for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) { + requests.add(getRequest(propertyMap)); + } + + Set<ServiceGroupResponse> responses = getResources(new Command<Set<ServiceGroupResponse>>() { + @Override + public Set<ServiceGroupResponse> invoke() throws AmbariException { + return getServiceGroups(requests); + } + }); + + Set<String> requestedIds = getRequestPropertyIds(request, predicate); + Set<Resource> resources = new HashSet<Resource>(); + + for (ServiceGroupResponse response : responses) { + Resource resource = new ResourceImpl(Resource.Type.ServiceGroup); + setResourceProperty(resource, SERVICE_GROUP_CLUSTER_ID_PROPERTY_ID, + response.getClusterId(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_CLUSTER_NAME_PROPERTY_ID, + response.getClusterName(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_SERVICE_GROUP_ID_PROPERTY_ID, + response.getServiceGroupId(), requestedIds); + setResourceProperty(resource, SERVICE_GROUP_SERVICE_GROUP_NAME_PROPERTY_ID, + response.getServiceGroupName(), 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<ServiceGroupRequest> 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 { + deleteServiceGroups(requests); + return new DeleteStatusMetaData(); + } + }); + + notifyDelete(Resource.Type.ServiceGroup, predicate); + for(ServiceGroupRequest svgReq : requests) { + deleteStatusMetaData.addDeletedKey("cluster_name: "+svgReq.getClusterName() + ", " + "service_group_name: "+svgReq.getServiceGroupName()); + } + 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 ServiceGroupRequest getRequest(Map<String, Object> properties) { + String clusterName = (String) properties.get(SERVICE_GROUP_CLUSTER_NAME_PROPERTY_ID); + String serviceGroupName = (String) properties.get(SERVICE_GROUP_SERVICE_GROUP_NAME_PROPERTY_ID); + ServiceGroupRequest svcRequest = new ServiceGroupRequest(clusterName, serviceGroupName); + return svcRequest; + } + + // Create services from the given request. + public synchronized Set<ServiceGroupResponse> createServiceGroups(Set<ServiceGroupRequest> 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<ServiceGroupResponse> createdSvcGrps = new HashSet<>(); + for (ServiceGroupRequest request : requests) { + Cluster cluster = clusters.getCluster(request.getClusterName()); + + // Already checked that service group does not exist + ServiceGroup sg = cluster.addServiceGroup(request.getServiceGroupName()); + createdSvcGrps.add(sg.convertToResponse()); + } + return createdSvcGrps; + } + + // Get services from the given set of requests. + protected Set<ServiceGroupResponse> getServiceGroups(Set<ServiceGroupRequest> requests) + throws AmbariException { + Set<ServiceGroupResponse> response = new HashSet<ServiceGroupResponse>(); + for (ServiceGroupRequest request : requests) { + try { + response.addAll(getServiceGroups(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<ServiceGroupResponse> getServiceGroups(ServiceGroupRequest 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<ServiceGroupResponse> response = new HashSet<>(); + if (request.getServiceGroupName() != null) { + ServiceGroup sg = cluster.getServiceGroup(request.getServiceGroupName()); + ServiceGroupResponse serviceGroupResponse = sg.convertToResponse(); + + response.add(serviceGroupResponse); + return response; + } + + for (ServiceGroup sg : cluster.getServiceGroups().values()) { + ServiceGroupResponse serviceGroupResponse = sg.convertToResponse(); + response.add(serviceGroupResponse); + } + return response; + } + + + // Delete services based on the given set of requests + protected void deleteServiceGroups(Set<ServiceGroupRequest> request) + throws AmbariException, AuthorizationException { + + Clusters clusters = getManagementController().getClusters(); + + Set<ServiceGroup> removable = new HashSet<>(); + + for (ServiceGroupRequest serviceGroupRequest : request) { + if (null == serviceGroupRequest.getClusterName() + || StringUtils.isEmpty(serviceGroupRequest.getServiceGroupName())) { + // FIXME throw correct error + throw new AmbariException("invalid arguments"); + } else { + + if (!AuthorizationHelper.isAuthorized( + ResourceType.CLUSTER, getClusterResourceId(serviceGroupRequest.getClusterName()), + RoleAuthorization.SERVICE_ADD_DELETE_SERVICES)) { + throw new AuthorizationException("The user is not authorized to delete service groups"); + } + + ServiceGroup serviceGroup = clusters.getCluster( + serviceGroupRequest.getClusterName()).getServiceGroup( + serviceGroupRequest.getServiceGroupName()); + + // TODO: Add check to validate there are no services in the service group + removable.add(serviceGroup); + } + } + + for (ServiceGroup serviceGroup : removable) { + serviceGroup.getCluster().deleteServiceGroup(serviceGroup.getServiceGroupName()); + } + + return; + } + + + private void validateCreateRequests(Set<ServiceGroupRequest> requests, Clusters clusters) + throws AuthorizationException, AmbariException { + + AmbariMetaInfo ambariMetaInfo = getManagementController().getAmbariMetaInfo(); + Map<String, Set<String>> serviceGroupNames = new HashMap<>(); + Set<String> duplicates = new HashSet<>(); + for (ServiceGroupRequest request : requests) { + final String clusterName = request.getClusterName(); + final String serviceGroupName = request.getServiceGroupName(); + + Validate.notNull(clusterName, "Cluster name should be provided when creating a service group"); + Validate.notEmpty(serviceGroupName, "Service group name should be provided when creating a service group"); + + if (LOG.isDebugEnabled()) { + LOG.debug("Received a createServiceGroup 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"); + } + + if (!serviceGroupNames.containsKey(clusterName)) { + serviceGroupNames.put(clusterName, new HashSet<String>()); + } + + if (serviceGroupNames.get(clusterName).contains(serviceGroupName)) { + // throw error later for dup + duplicates.add(serviceGroupName); + continue; + } + serviceGroupNames.get(clusterName).add(serviceGroupName); + + 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); + } + try { + ServiceGroup sg = cluster.getServiceGroup(serviceGroupName); + if (sg != null) { + // throw error later for dup + duplicates.add(serviceGroupName); + continue; + } + } catch (ServiceGroupNotFoundException e) { + // Expected + } + } + // ensure only a single cluster update + if (serviceGroupNames.size() != 1) { + throw new IllegalArgumentException("Invalid arguments, updates allowed" + + "on only one cluster at a time"); + } + + // Validate dups + if (!duplicates.isEmpty()) { + String clusterName = requests.iterator().next().getClusterName(); + String msg = "Attempted to create a service group which already exists: " + + ", clusterName=" + clusterName + " serviceGroupName=" + StringUtils.join(duplicates, ","); + + throw new DuplicateResourceException(msg); + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 1994501..a364c4c 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 @@ -76,6 +76,7 @@ public interface Resource { enum InternalType { Cluster, Service, + ServiceGroup, Setting, Host, Component, @@ -203,6 +204,7 @@ public interface Resource { * Internal types. See {@link InternalType}. */ public static final Type Cluster = InternalType.Cluster.getType(); + public static final Type ServiceGroup = InternalType.ServiceGroup.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/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java index 9a5ee79..07b70b6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AmbariEvent.java @@ -38,6 +38,16 @@ public abstract class AmbariEvent { SERVICE_REMOVED_SUCCESS, /** + * A service group was successfully installed. + */ + SERVICE_GROUP_INSTALL_SUCCESS, + + /** + * A service group was successfully removed. + */ + SERVICE_GROUP_REMOVED_SUCCESS, + + /** * A service component was successfully installed. */ SERVICE_COMPONENT_INSTALL_SUCCESS, http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupEvent.java new file mode 100644 index 0000000..92b739b --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupEvent.java @@ -0,0 +1,49 @@ +/** + * 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.events; + + +/** + * The {@link ServiceEvent} class is the base for all service events in Ambari. + */ +public abstract class ServiceGroupEvent extends ClusterEvent { + + /** + * The name of the service group. + */ + protected final String m_serviceGroupName; + + /** + * Constructor. + * + * @param eventType + * @param clusterId + */ + public ServiceGroupEvent(AmbariEventType eventType, long clusterId, String serviceGroupName) { + super(eventType, clusterId); + m_serviceGroupName = serviceGroupName; + } + + /** + * @return the service group name (never {@code null}). + */ + public String getServiceGroupName() { + return m_serviceGroupName; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupInstalledEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupInstalledEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupInstalledEvent.java new file mode 100644 index 0000000..e66d8a0 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupInstalledEvent.java @@ -0,0 +1,46 @@ +/** + * 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.events; + +/** + * The {@link ServiceGroupInstalledEvent} class is fired when a service group is + * successfully installed. + */ +public class ServiceGroupInstalledEvent extends ServiceGroupEvent { + /** + * Constructor. + * + * @param clusterId + * @param serviceGroupName + */ + public ServiceGroupInstalledEvent(long clusterId, String serviceGroupName) { + super(AmbariEventType.SERVICE_GROUP_INSTALL_SUCCESS, clusterId, serviceGroupName); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder("ServiceGroupInstalledEvent{"); + buffer.append("cluserId=").append(m_clusterId); + buffer.append(", serviceGroupName=").append(m_serviceGroupName); + buffer.append("}"); + return buffer.toString(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupRemovedEvent.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupRemovedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupRemovedEvent.java new file mode 100644 index 0000000..b29a9a4 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/events/ServiceGroupRemovedEvent.java @@ -0,0 +1,46 @@ +/** + * 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.events; + +/** + * The {@link ServiceRemovedEvent} class is fired when a service is successfully + * removed. + */ +public class ServiceGroupRemovedEvent extends ServiceGroupEvent { + /** + * Constructor. + * + * @param clusterId + * @param serviceGroupName + */ + public ServiceGroupRemovedEvent(long clusterId, String serviceGroupName) { + super(AmbariEventType.SERVICE_GROUP_REMOVED_SUCCESS, clusterId, serviceGroupName); + } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + StringBuilder buffer = new StringBuilder("ServiceGroupRemovedEvent{"); + buffer.append("cluserId=").append(m_clusterId); + buffer.append(", serviceGroupName=").append(m_serviceGroupName); + buffer.append("}"); + return buffer.toString(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java new file mode 100644 index 0000000..dc997b0 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/ServiceGroupDAO.java @@ -0,0 +1,93 @@ +/** + * 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.orm.dao; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; + +import org.apache.ambari.server.orm.RequiresSession; +import org.apache.ambari.server.orm.entities.ServiceGroupEntity; +import org.apache.ambari.server.orm.entities.ServiceGroupEntityPK; + +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import com.google.inject.persist.Transactional; + +@Singleton +public class ServiceGroupDAO { + @Inject + Provider<EntityManager> entityManagerProvider; + @Inject + DaoUtils daoUtils; + + @RequiresSession + public ServiceGroupEntity findByPK(ServiceGroupEntityPK clusterServiceGroupEntityPK) { + return entityManagerProvider.get().find(ServiceGroupEntity.class, clusterServiceGroupEntityPK); + } + + @RequiresSession + public ServiceGroupEntity findByClusterAndServiceGroupNames(String clusterName, String serviceGroupName) { + TypedQuery<ServiceGroupEntity> query = entityManagerProvider.get() + .createNamedQuery("serviceGroupByClusterAndServiceGroupNames", ServiceGroupEntity.class); + query.setParameter("clusterName", clusterName); + query.setParameter("serviceGroupName", serviceGroupName); + + try { + return query.getSingleResult(); + } catch (NoResultException ignored) { + return null; + } + } + + @RequiresSession + public List<ServiceGroupEntity> findAll() { + return daoUtils.selectAll(entityManagerProvider.get(), ServiceGroupEntity.class); + } + + @Transactional + public void refresh(ServiceGroupEntity clusterServiceGroupEntity) { + entityManagerProvider.get().refresh(clusterServiceGroupEntity); + } + + @Transactional + public void create(ServiceGroupEntity clusterServiceGroupEntity) { + entityManagerProvider.get().persist(clusterServiceGroupEntity); + } + + @Transactional + public ServiceGroupEntity merge(ServiceGroupEntity clusterServiceGroupEntity) { + return entityManagerProvider.get().merge(clusterServiceGroupEntity); + } + + @Transactional + public void remove(ServiceGroupEntity clusterServiceGroupEntity) { + entityManagerProvider.get().remove(merge(clusterServiceGroupEntity)); + } + + @Transactional + public void removeByPK(ServiceGroupEntityPK clusterServiceGroupEntityPK) { + ServiceGroupEntity entity = findByPK(clusterServiceGroupEntityPK); + entityManagerProvider.get().remove(entity); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java index c22449c..abbf709 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ClusterEntity.java @@ -47,23 +47,23 @@ import org.apache.ambari.server.state.State; @Table(name = "clusters") @NamedQueries({ - @NamedQuery(name = "clusterByName", query = - "SELECT cluster " + - "FROM ClusterEntity cluster " + - "WHERE cluster.clusterName=:clusterName"), - @NamedQuery(name = "allClusters", query = - "SELECT clusters " + - "FROM ClusterEntity clusters"), - @NamedQuery(name = "clusterByResourceId", query = - "SELECT cluster " + - "FROM ClusterEntity cluster " + - "WHERE cluster.resource.id=:resourceId") + @NamedQuery(name = "clusterByName", query = + "SELECT cluster " + + "FROM ClusterEntity cluster " + + "WHERE cluster.clusterName=:clusterName"), + @NamedQuery(name = "allClusters", query = + "SELECT clusters " + + "FROM ClusterEntity clusters"), + @NamedQuery(name = "clusterByResourceId", query = + "SELECT cluster " + + "FROM ClusterEntity cluster " + + "WHERE cluster.resource.id=:resourceId") }) @Entity @TableGenerator(name = "cluster_id_generator", - table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value" - , pkColumnValue = "cluster_id_seq" - , initialValue = 1 + table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value" + , pkColumnValue = "cluster_id_seq" + , initialValue = 1 ) public class ClusterEntity { @@ -74,7 +74,7 @@ public class ClusterEntity { @Basic @Column(name = "cluster_name", nullable = false, insertable = true, - updatable = true, unique = true, length = 100) + updatable = true, unique = true, length = 100) private String clusterName; @Basic @@ -105,6 +105,9 @@ public class ClusterEntity { @OneToMany(mappedBy = "clusterEntity") private Collection<ClusterServiceEntity> clusterServiceEntities; + @OneToMany(mappedBy = "clusterEntity") + private Collection<ServiceGroupEntity> serviceGroupEntities; + @OneToOne(mappedBy = "clusterEntity", cascade = CascadeType.REMOVE) private ClusterStateEntity clusterStateEntity; @@ -134,7 +137,7 @@ public class ClusterEntity { @OneToOne(cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "resource_id", referencedColumnName = "resource_id", nullable = false) + @JoinColumn(name = "resource_id", referencedColumnName = "resource_id", nullable = false) }) private ResourceEntity resource; @@ -147,11 +150,11 @@ public class ClusterEntity { */ @OneToOne(cascade = CascadeType.REMOVE) @JoinColumn( - name = "upgrade_id", - referencedColumnName = "upgrade_id", - nullable = true, - insertable = false, - updatable = true) + name = "upgrade_id", + referencedColumnName = "upgrade_id", + nullable = true, + insertable = false, + updatable = true) private UpgradeEntity upgradeEntity = null; public Long getClusterId() { @@ -201,7 +204,7 @@ public class ClusterEntity { * @return either {@link State#INIT} or {@link State#INSTALLED}, * never {@code null}. */ - public State getProvisioningState(){ + public State getProvisioningState() { return provisioningState; } @@ -210,9 +213,9 @@ public class ClusterEntity { * deployment requests. * * @param provisioningState either {@link State#INIT} or - * {@link State#INSTALLED}, never {@code null}. + * {@link State#INSTALLED}, never {@code null}. */ - public void setProvisioningState(State provisioningState){ + public void setProvisioningState(State provisioningState) { this.provisioningState = provisioningState; } @@ -270,6 +273,14 @@ public class ClusterEntity { this.clusterServiceEntities = clusterServiceEntities; } + public Collection<ServiceGroupEntity> getServiceGroupEntities() { + return serviceGroupEntities; + } + + public void setServiceGroupEntities(Collection<ServiceGroupEntity> serviceGroupEntities) { + this.serviceGroupEntities = serviceGroupEntities; + } + public ClusterStateEntity getClusterStateEntity() { return clusterStateEntity; } @@ -334,7 +345,7 @@ public class ClusterEntity { /** * Set the admin resource entity. * - * @param resource the resource entity + * @param resource the resource entity */ public void setResource(ResourceEntity resource) { this.resource = resource; http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/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 new file mode 100644 index 0000000..cd9d2c8 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntity.java @@ -0,0 +1,123 @@ +/** + * 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.orm.entities; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.TableGenerator; + + + +@IdClass(ServiceGroupEntityPK.class) +@Table(name = "servicegroups") +@NamedQueries({ + @NamedQuery(name = "serviceGroupByClusterAndServiceGroupNames", query = + "SELECT serviceGroup " + + "FROM ServiceGroupEntity serviceGroup " + + "JOIN serviceGroup.clusterEntity cluster " + + "WHERE serviceGroup.serviceGroupName=:serviceGroupName AND cluster.clusterName=:clusterName") +}) +@Entity +@TableGenerator(name = "service_group_id_generator", + table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value" + , pkColumnValue = "service_group_id_seq" + , initialValue = 1 +) +public class ServiceGroupEntity { + + @Id + @Column(name = "cluster_id", nullable = false, insertable = false, updatable = false, length = 10) + private Long clusterId; + + @Id + @Column(name = "id", nullable = false, insertable = true, updatable = true) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "service_group_id_generator") + private Long serviceGroupId; + + @Column(name = "service_group_name", nullable = false, insertable = true, updatable = true) + private String serviceGroupName; + + @ManyToOne + @JoinColumn(name = "cluster_id", referencedColumnName = "cluster_id", nullable = false) + private ClusterEntity clusterEntity; + + 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; + } + + + public String getServiceGroupName() { + return serviceGroupName; + } + + public void setServiceGroupName(String serviceGroupName) { + this.serviceGroupName = serviceGroupName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ServiceGroupEntity that = (ServiceGroupEntity) o; + + if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != 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.intValue() : 0; + result = 31 * result + (serviceGroupName != null ? serviceGroupName.hashCode() : 0); + return result; + } + + public ClusterEntity getClusterEntity() { + return clusterEntity; + } + + public void setClusterEntity(ClusterEntity clusterEntity) { + this.clusterEntity = clusterEntity; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntityPK.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntityPK.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntityPK.java new file mode 100644 index 0000000..c993442 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ServiceGroupEntityPK.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.orm.entities; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Id; + +@SuppressWarnings("serial") +public class ServiceGroupEntityPK implements Serializable { + private Long clusterId; + + @Id + @Column(name = "cluster_id", nullable = false, insertable = true, updatable = true, length = 10) + public Long getClusterId() { + return clusterId; + } + + public void setClusterId(Long clusterId) { + this.clusterId = clusterId; + } + + private Long serviceGroupId; + + @Id + @Column(name = "id", nullable = false, insertable = true, updatable = true, length = 10) + public Long getServiceGroupId() { + return this.serviceGroupId; + } + + public void setServiceGroupId(Long serviceGroupId) { + this.serviceGroupId = serviceGroupId; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ServiceGroupEntityPK that = (ServiceGroupEntityPK) o; + + if (clusterId != null ? !clusterId.equals(that.clusterId) : that.clusterId != null) return false; + if (serviceGroupId != null ? !serviceGroupId.equals(that.serviceGroupId) : that.serviceGroupId != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = clusterId != null ? clusterId.intValue() : 0; + result = 31 * result + (serviceGroupId != null ? serviceGroupId.hashCode() : 0); + return result; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/2f1f96ef/ambari-server/src/main/java/org/apache/ambari/server/serveraction/servicegroup/ServiceGroupServerAction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/servicegroup/ServiceGroupServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/servicegroup/ServiceGroupServerAction.java new file mode 100644 index 0000000..818957e --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/servicegroup/ServiceGroupServerAction.java @@ -0,0 +1,92 @@ +/* + * 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.serveraction.servicegroup; + +import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.agent.ExecutionCommand; +import org.apache.ambari.server.serveraction.AbstractServerAction; +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Clusters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.inject.Inject; + + +public abstract class ServiceGroupServerAction extends AbstractServerAction { + + protected final static Logger LOG = LoggerFactory.getLogger(ServiceGroupServerAction.class); + + /** + * Gson + */ + @Inject + protected Gson gson; + + /** + * The Cluster that this ServerAction implementation is executing on + */ + @Inject + private Clusters clusters = null; + + /** + * Returns the relevant Cluster object + * + * @return the relevant Cluster + * @throws AmbariException if the Cluster object cannot be retrieved + */ + protected Cluster getCluster() throws AmbariException { + Cluster cluster = clusters.getCluster(getClusterName()); + + if (cluster == null) { + throw new AmbariException(String.format("Failed to retrieve cluster for %s", getClusterName())); + } + + return cluster; + } + + /** + * The Clusters object for this KerberosServerAction + * + * @return a Clusters object + */ + protected Clusters getClusters() { + return clusters; + } + + /** + * Returns the relevant cluster's name + * <p/> + * Using the data from the execution command, retrieve the relevant cluster's name. + * + * @return a String declaring the relevant cluster's name + * @throws AmbariException if the cluster's name is not available + */ + protected String getClusterName() throws AmbariException { + ExecutionCommand executionCommand = getExecutionCommand(); + String clusterName = (executionCommand == null) ? null : executionCommand.getClusterName(); + + if ((clusterName == null) || clusterName.isEmpty()) { + throw new AmbariException("Failed to retrieve the cluster name from the execution command"); + } + + return clusterName; + } +} \ No newline at end of file
