Gilad Chaplik has uploaded a new change for review. Change subject: restapi: adding support for affinity groups ......................................................................
restapi: adding support for affinity groups * Adding a new affinity groups sub-collections for clusters: GET /clusters/{cluster_id}/affinitygroups * affinity groups action includes, add, update and remove affinity groups: POST /clusters/{cluster_id}/affinitygroups/ <affinity_group> <name> <positive> <enforcing> </..> GET/DELETE/PUT /clusters/{cluster_id}/affinitygroups/{affinity_group_id} * Adding VMs sub-collection for a single affinity group: allowing to add/remove VMs from an affinity group using post/delete: GET /clusters/{cluster_id}/affinitygroups/{affinity_group_id}/vms POST /clusters/{cluster_id}/affinitygroups/{affinity_group_id}/vms <vm id='{vm_id}'> </vm> DELETE /clusters/{cluster_id}/affinitygroups/{affinity_group_id}/vms/{vm_id} * include tests for added resources For more information please refer to: http://www.ovirt.org/Features/VM-Affinity Change-Id: Ie2daa18742eca73517ef739e70e972d74aad4244 Bug-Url: https://bugzilla.redhat.com/?????? Signed-off-by: Gilad Chaplik <gchap...@redhat.com> --- M backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java A backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupResource.java A backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupVmsResource.java A backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupsResource.java M backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java M backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd M backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml A backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResource.java A backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResource.java A backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResource.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java A backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResourceTest.java A backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResourceTest.java A backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResourceTest.java A backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapper.java A backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapperTest.java 17 files changed, 867 insertions(+), 1 deletion(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/52/23452/1 diff --git a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java index bca9d01..378a122 100644 --- a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java +++ b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java @@ -29,6 +29,7 @@ import org.ovirt.engine.api.model.ActionableResource; import org.ovirt.engine.api.model.ActionsBuilder; +import org.ovirt.engine.api.model.AffinityGroup; import org.ovirt.engine.api.model.Application; import org.ovirt.engine.api.model.BaseResource; import org.ovirt.engine.api.model.CdRom; @@ -76,6 +77,8 @@ import org.ovirt.engine.api.model.VmPool; import org.ovirt.engine.api.model.VnicProfile; import org.ovirt.engine.api.model.WatchDog; +import org.ovirt.engine.api.resource.AffinityGroupResource; +import org.ovirt.engine.api.resource.AffinityGroupsResource; import org.ovirt.engine.api.resource.AssignedNetworkResource; import org.ovirt.engine.api.resource.AssignedNetworksResource; import org.ovirt.engine.api.resource.AssignedPermissionsResource; @@ -371,6 +374,9 @@ map.add(LabelResource.class, LabelsResource.class, Network.class); map.add(LabelResource.class, LabelsResource.class, HostNIC.class); TYPES.put(Label.class, map); + + map = new ParentToCollectionMap(AffinityGroupResource.class, AffinityGroupsResource.class, Cluster.class); + TYPES.put(AffinityGroup.class, map); } /** diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupResource.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupResource.java new file mode 100644 index 0000000..5ac99b0 --- /dev/null +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupResource.java @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2010 Red Hat, Inc. +* +* Licensed 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.ovirt.engine.api.resource; + +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +import org.ovirt.engine.api.model.AffinityGroup; + +@Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML}) +public interface AffinityGroupResource extends UpdatableResource<AffinityGroup> { + + @Path("vms") + public AffinityGroupVmsResource getAffinityGroupVmsSubResource(); + +} diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupVmsResource.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupVmsResource.java new file mode 100644 index 0000000..1a81918 --- /dev/null +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupVmsResource.java @@ -0,0 +1,32 @@ +package org.ovirt.engine.api.resource; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +import org.jboss.resteasy.annotations.providers.jaxb.Formatted; +import org.ovirt.engine.api.model.VM; +import org.ovirt.engine.api.model.VMs; + +@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML }) +public interface AffinityGroupVmsResource { + + @GET + @Formatted + public VMs list(); + + @POST + @Formatted + @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML }) + public Response add(VM vm); + + @DELETE + @Path("{id}") + public Response remove(@PathParam("id") String id); + +} diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupsResource.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupsResource.java new file mode 100644 index 0000000..8deb335 --- /dev/null +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/AffinityGroupsResource.java @@ -0,0 +1,33 @@ +package org.ovirt.engine.api.resource; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; + +import org.jboss.resteasy.annotations.providers.jaxb.Formatted; +import org.ovirt.engine.api.model.AffinityGroup; +import org.ovirt.engine.api.model.AffinityGroups; + +@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML }) +public interface AffinityGroupsResource { + @GET + @Formatted + public AffinityGroups list(); + + @POST + @Formatted + @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML }) + public Response add(AffinityGroup affinityGroup); + + @DELETE + @Path("{id}") + public Response remove(@PathParam("id") String id); + + @Path("{id}") + public AffinityGroupResource getAffinityGroupResource(@PathParam("id") String id); +} diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java index 47d271d..66d47fe 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterResource.java @@ -38,4 +38,7 @@ @Path("glusterhooks") public GlusterHooksResource getGlusterHooksResource(); + + @Path("affinitygroups") + public AffinityGroupsResource getAffinityGroupsResource(); } diff --git a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd index 5cfdf2d..12ecd84 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd +++ b/backend/manager/modules/restapi/interface/definition/src/main/resources/api.xsd @@ -3848,4 +3848,35 @@ </xs:extension> </xs:complexContent> </xs:complexType> + + <xs:element name="affinity_group" type="AffinityGroup" /> + <xs:complexType name="AffinityGroup"> + <xs:complexContent> + <xs:extension base="BaseResource"> + <xs:sequence> + <xs:element ref="cluster" minOccurs="1" maxOccurs="1" /> + <xs:element name="positive" type="xs:boolean" minOccurs="1" + maxOccurs="1" /> + <xs:element name="enforcing" type="xs:boolean" + minOccurs="1" maxOccurs="1" /> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> + <xs:element name="affinity_groups" type="AffinityGroups" /> + <xs:complexType name="AffinityGroups"> + <xs:complexContent> + <xs:extension base="BaseResources"> + <xs:sequence> + <xs:annotation> + <xs:appinfo> + <jaxb:property name="AffinityGroups" /> + </xs:appinfo> + </xs:annotation> + <xs:element ref="affinity_group" minOccurs="0" + maxOccurs="unbounded" /> + </xs:sequence> + </xs:extension> + </xs:complexContent> + </xs:complexType> </xs:schema> diff --git a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml index 25ef2f3..1341335 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml +++ b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml @@ -4626,4 +4626,83 @@ Content-Type: {value: application/xml|json, required: true} Expect: {value: 201-created, required: false} Correlation-Id: {value: 'any string', required: false} +- name: /clusters/{cluster:id}/affinitygroups|rel=get + description: get the list of affinity groups in the cluster + request: + body: + parameterType: null + signatures: [] + urlparams: + max: {context: matrix, type: 'xs:int', value: 'max results', required: false} + headers: {} +- name: /clusters/{cluster:id}/affinitygroups/{affinitygroup:id}|rel=get + description: get the details of the specified affinity group in the cluster + request: + body: + parameterType: null + signatures: [] + urlparams: {} + headers: {} +- name: /clusters/{cluster:id}/affinitygroups/{affinitygroup:id}|rel=delete + description: delete the specified affinity groups in the cluster + request: + body: + parameterType: null + signatures: [] + urlparams: {} + headers: {} +- name: /clusters/{cluster:id}/affinitygroups/{affinitygroup:id}|rel=update + description: update the specified affinity group in the cluster + request: + body: + parameterType: affinitygroup + signatures: + - mandatoryArguments: {} + optionalArguments: {affinitygroup.name: 'xs:string', affinitygroup.positive: 'xs:boolean', affinitygroup.enforcing: 'xs:boolean'} + urlparams: {} + headers: + Content-Type: {value: application/xml|json, required: true} +- name: /clusters/{cluster:id}/affinitygroups|rel=add + description: add a new affinity group to the cluster + request: + body: + parameterType: affinitygroup + signatures: + - mandatoryArguments: {affinitygroup.name: 'xs:string', affinitygroup.positive: 'xs:boolean', affinitygroup.enforcing: 'xs:boolean'} + optionalArguments: {} + description: add a new affinity group to the cluster + urlparams: {} + headers: + Content-Type: {value: application/xml|json, required: true} + Expect: {value: 201-created, required: false} +- name: /clusters/{cluster:id}/affinitygroups/{affinitygroup:id}/vms|rel=get + description: get the list of vms per affinity group + request: + body: + parameterType: null + signatures: [] + urlparams: + max: {context: matrix, type: 'xs:int', value: 'max results', required: false} + headers: {} +- name: /clusters/{cluster:id}/affinitygroups/{affinitygroup:id}/vms/{vm:id}|rel=delete + description: remove the specified vm from the affinity groups + request: + body: + parameterType: null + signatures: [] + urlparams: {} + headers: {} +- name: /clusters/{cluster:id}/affinitygroups/{affinitygroup:id}/vms|rel=add + description: add a vm to the specified affinity group + request: + body: + parameterType: VM + signatures: + - mandatoryArguments: {vm.id|name: 'xs:string'} + optionalArguments: {} + description: add a vm to affinity group + urlparams: {} + headers: + Content-Type: {value: application/xml|json, required: true} + Expect: {value: 201-created, required: false} diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResource.java new file mode 100644 index 0000000..ce2a687 --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResource.java @@ -0,0 +1,52 @@ +package org.ovirt.engine.api.restapi.resource; + +import org.ovirt.engine.api.model.AffinityGroup; +import org.ovirt.engine.api.resource.AffinityGroupResource; +import org.ovirt.engine.api.resource.AffinityGroupVmsResource; +import org.ovirt.engine.core.common.action.VdcActionParametersBase; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.common.queries.VdcQueryType; +import org.ovirt.engine.core.common.scheduling.parameters.AffinityGroupCRUDParameters; +import org.ovirt.engine.core.compat.Guid; + +public class BackendAffinityGroupResource + extends AbstractBackendSubResource<AffinityGroup, org.ovirt.engine.core.common.scheduling.AffinityGroup> + implements AffinityGroupResource { + static final String[] SUB_COLLECTIONS = { "vms" }; + + public BackendAffinityGroupResource(String id) { + super(id, AffinityGroup.class, + org.ovirt.engine.core.common.scheduling.AffinityGroup.class, SUB_COLLECTIONS); + } + + @Override + public AffinityGroup get() { + return performGet(VdcQueryType.GetAffinityGroupById, new IdQueryParameters(guid)); + } + + @Override + public AffinityGroup update(final AffinityGroup incoming) { + return performUpdate(incoming, + new QueryIdResolver<Guid>(VdcQueryType.GetAffinityGroupById, IdQueryParameters.class), + VdcActionType.EditAffinityGroup, + new ParametersProvider<AffinityGroup, org.ovirt.engine.core.common.scheduling.AffinityGroup>() { + @Override + public VdcActionParametersBase getParameters(AffinityGroup model, + org.ovirt.engine.core.common.scheduling.AffinityGroup entity) { + return new AffinityGroupCRUDParameters(guid, map(incoming, entity)); + } + }); + } + + @Override + protected AffinityGroup doPopulate(AffinityGroup model, org.ovirt.engine.core.common.scheduling.AffinityGroup entity) { + return model; + } + + @Override + public AffinityGroupVmsResource getAffinityGroupVmsSubResource() { + return inject(new BackendAffinityGroupVmsResource(guid)); + } + +} diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResource.java new file mode 100644 index 0000000..19cea5a --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResource.java @@ -0,0 +1,80 @@ +package org.ovirt.engine.api.restapi.resource; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import org.ovirt.engine.api.model.VM; +import org.ovirt.engine.api.model.VMs; +import org.ovirt.engine.api.resource.AffinityGroupVmsResource; +import org.ovirt.engine.api.restapi.utils.GuidUtils; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.common.queries.VdcQueryType; +import org.ovirt.engine.core.common.scheduling.AffinityGroup; +import org.ovirt.engine.core.common.scheduling.parameters.AffinityGroupCRUDParameters; +import org.ovirt.engine.core.compat.Guid; + + +public class BackendAffinityGroupVmsResource extends AbstractBackendCollectionResource<VM, org.ovirt.engine.core.common.businessentities.VM> + implements AffinityGroupVmsResource { + private final Guid affinityGroupId; + + public BackendAffinityGroupVmsResource(Guid affinityGroupId) { + super(VM.class, org.ovirt.engine.core.common.businessentities.VM.class); + this.affinityGroupId = affinityGroupId; + } + + @Override + protected VM doPopulate(VM model, org.ovirt.engine.core.common.businessentities.VM entity) { + return model; + } + + @Override + public VMs list() { + VMs vms = new VMs(); + AffinityGroup affinityGroup = getEntity(); + + if (affinityGroup.getEntityIds() != null) { + for (int i = 0; i < affinityGroup.getEntityIds().size(); i++) { + VM vm = new VM(); + vm.setId(affinityGroup.getEntityIds().get(i).toString()); + vm.setName(affinityGroup.getEntityNames().get(i)); + vm = addLinks(populate(vm, null)); + // remove vm actions, not relevant to this context + vm.setActions(null); + vms.getVMs().add(vm); + } + } + + return vms; + } + + @Override + public Response add(VM vm) { + AffinityGroup affinityGroup = getEntity(); + + affinityGroup.getEntityIds().add(GuidUtils.asGuid(vm.getId())); + return performAction(VdcActionType.EditAffinityGroup, new AffinityGroupCRUDParameters(affinityGroup.getId(), + affinityGroup)); + } + + @Override + protected Response performRemove(String id) { + AffinityGroup affinityGroup = getEntity(); + + if (!affinityGroup.getEntityIds().remove(GuidUtils.asGuid(id))) { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + return performAction(VdcActionType.EditAffinityGroup, new AffinityGroupCRUDParameters(affinityGroup.getId(), + affinityGroup)); + } + + @Override + protected org.ovirt.engine.core.common.scheduling.AffinityGroup getEntity() { + return getEntity(org.ovirt.engine.core.common.scheduling.AffinityGroup.class, + VdcQueryType.GetAffinityGroupById, + new IdQueryParameters(affinityGroupId), + affinityGroupId.toString()); + } + +} diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResource.java new file mode 100644 index 0000000..87f5bfd --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResource.java @@ -0,0 +1,74 @@ +package org.ovirt.engine.api.restapi.resource; + +import java.util.List; + +import javax.ws.rs.core.Response; + +import org.ovirt.engine.api.model.AffinityGroup; +import org.ovirt.engine.api.model.AffinityGroups; +import org.ovirt.engine.api.resource.AffinityGroupResource; +import org.ovirt.engine.api.resource.AffinityGroupsResource; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.common.queries.VdcQueryType; +import org.ovirt.engine.core.common.scheduling.parameters.AffinityGroupCRUDParameters; +import org.ovirt.engine.core.compat.Guid; + +public class BackendAffinityGroupsResource + extends AbstractBackendCollectionResource<AffinityGroup, org.ovirt.engine.core.common.scheduling.AffinityGroup> + implements AffinityGroupsResource { + + private String clusterId; + + public BackendAffinityGroupsResource(String clusterId) { + super(AffinityGroup.class, org.ovirt.engine.core.common.scheduling.AffinityGroup.class); + this.clusterId = clusterId; + } + + @Override + public AffinityGroups list() { + List<org.ovirt.engine.core.common.scheduling.AffinityGroup> entities = + getBackendCollection(VdcQueryType.GetAffinityGroupsByClusterId, + new IdQueryParameters(asGuid(clusterId))); + return mapCollection(entities); + } + + private AffinityGroups mapCollection(List<org.ovirt.engine.core.common.scheduling.AffinityGroup> entities) { + AffinityGroups collection = new AffinityGroups(); + for (org.ovirt.engine.core.common.scheduling.AffinityGroup entity : entities) { + collection.getAffinityGroups().add(addLinks(populate(map(entity), entity))); + } + return collection; + } + + @Override + public Response add(AffinityGroup affinityGroup) { + org.ovirt.engine.core.common.scheduling.AffinityGroup backendEntity = + getMapper(AffinityGroup.class, org.ovirt.engine.core.common.scheduling.AffinityGroup.class).map(affinityGroup, + null); + backendEntity.setClusterId(asGuid(clusterId)); + + return performCreate(VdcActionType.AddAffinityGroup, + new AffinityGroupCRUDParameters(null, backendEntity), + new QueryIdResolver<Guid>(VdcQueryType.GetAffinityGroupById, IdQueryParameters.class), + true); + } + + @Override + protected Response performRemove(String id) { + AffinityGroupCRUDParameters params = new AffinityGroupCRUDParameters(); + params.setAffinityGroupId(asGuid(id)); + return performAction(VdcActionType.RemoveAffinityGroup, params); + } + + @Override + protected AffinityGroup doPopulate(AffinityGroup model, org.ovirt.engine.core.common.scheduling.AffinityGroup entity) { + return model; + } + + @Override + @SingleEntityResource + public AffinityGroupResource getAffinityGroupResource(String id) { + return inject(new BackendAffinityGroupResource(id)); + } +} diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java index 0614668..21d1122 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterResource.java @@ -4,6 +4,7 @@ import static org.ovirt.engine.api.restapi.resource.BackendClustersResource.SUB_COLLECTIONS; import org.ovirt.engine.api.model.Cluster; +import org.ovirt.engine.api.resource.AffinityGroupsResource; import org.ovirt.engine.api.resource.AssignedNetworksResource; import org.ovirt.engine.api.resource.AssignedPermissionsResource; import org.ovirt.engine.api.resource.ClusterResource; @@ -78,4 +79,9 @@ return inject(new BackendGlusterHooksResource(this)); } + @Override + public AffinityGroupsResource getAffinityGroupsResource() { + return inject(new BackendAffinityGroupsResource(id)); + } + } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java index 62e847b..fdbd402 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java @@ -25,7 +25,8 @@ public class BackendClustersResource extends AbstractBackendCollectionResource<Cluster, VDSGroup> implements ClustersResource { - static final String[] SUB_COLLECTIONS = { "networks", "permissions", "glustervolumes", "glusterhooks" }; + static final String[] SUB_COLLECTIONS = { "networks", "permissions", "glustervolumes", "glusterhooks", + "affinitygroups" }; static final String[] VIRT_ONLY_MODE_COLLECTIONS_TO_HIDE = {"glustervolumes", "glusterhooks" }; public BackendClustersResource() { super(Cluster.class, VDSGroup.class, SUB_COLLECTIONS); diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResourceTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResourceTest.java new file mode 100644 index 0000000..ec61ed2 --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupResourceTest.java @@ -0,0 +1,96 @@ +package org.ovirt.engine.api.restapi.resource; + +import static org.easymock.EasyMock.expect; + +import javax.ws.rs.WebApplicationException; + +import org.junit.Test; +import org.ovirt.engine.api.model.AffinityGroup; +import org.ovirt.engine.api.model.Cluster; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.common.queries.VdcQueryType; +import org.ovirt.engine.core.common.scheduling.parameters.AffinityGroupCRUDParameters; +import org.ovirt.engine.core.compat.Guid; + +public class BackendAffinityGroupResourceTest extends AbstractBackendSubResourceTest<AffinityGroup, org.ovirt.engine.core.common.scheduling.AffinityGroup, BackendAffinityGroupResource> { + + private static final Guid AFFINITY_GROUP_ID = GUIDS[0]; + private static final Guid CLUSTER_ID = GUIDS[0]; + + public BackendAffinityGroupResourceTest() { + super(new BackendAffinityGroupResource(AFFINITY_GROUP_ID.toString())); + } + + @Test + public void testGet() throws Exception { + setUriInfo(setUpBasicUriExpectations()); + setUpGetEntityExpectations(1, true); + control.replay(); + + verifyModel(resource.get(), 0); + } + + @Test + public void testGetNotFound() throws Exception { + setUriInfo(setUpBasicUriExpectations()); + setUpGetEntityExpectations(1, false); + control.replay(); + try { + resource.get(); + fail("expected WebApplicationException"); + } catch (WebApplicationException wae) { + verifyNotFoundException(wae); + } + } + + @Test + public void testUpdate() throws Exception { + setUpGetEntityExpectations(2, true); + + setUriInfo(setUpActionExpectations(VdcActionType.EditAffinityGroup, + AffinityGroupCRUDParameters.class, + new String[] {}, + new Object[] {}, + true, + true)); + + verifyModel(resource.update(getModel(0)), 0); + } + + private void setUpGetEntityExpectations(int times, boolean found) throws Exception { + while (times-- > 0) { + setUpGetEntityExpectations(VdcQueryType.GetAffinityGroupById, + IdQueryParameters.class, + new String[] { "Id" }, + new Object[] { AFFINITY_GROUP_ID }, + found ? getEntity(0) : null); + } + } + + @Override + protected org.ovirt.engine.core.common.scheduling.AffinityGroup getEntity(int index) { + org.ovirt.engine.core.common.scheduling.AffinityGroup entity = + control.createMock(org.ovirt.engine.core.common.scheduling.AffinityGroup.class); + expect(entity.getId()).andReturn(GUIDS[index]).anyTimes(); + expect(entity.getName()).andReturn(NAMES[index].toString()).anyTimes(); + expect(entity.getDescription()).andReturn(DESCRIPTIONS[index].toString()).anyTimes(); + expect(entity.getClusterId()).andReturn(CLUSTER_ID).anyTimes(); + expect(entity.isEnforcing()).andReturn(GUIDS[index].hashCode() % 2 == 0).anyTimes(); + expect(entity.isPositive()).andReturn(GUIDS[index].hashCode() % 2 == 1).anyTimes(); + return entity; + } + + static AffinityGroup getModel(int index) { + AffinityGroup model = new AffinityGroup(); + model.setId(GUIDS[0].toString()); + model.setName(NAMES[index]); + model.setDescription(DESCRIPTIONS[index]); + model.setCluster(new Cluster()); + model.getCluster().setId(CLUSTER_ID.toString()); + model.setEnforcing(GUIDS[index].hashCode() % 2 == 0); + model.setPositive(GUIDS[index].hashCode() % 2 == 1); + + return model; + } +} diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResourceTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResourceTest.java new file mode 100644 index 0000000..6d4a501 --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupVmsResourceTest.java @@ -0,0 +1,137 @@ +package org.ovirt.engine.api.restapi.resource; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.core.Response; + +import org.junit.Test; +import org.ovirt.engine.api.model.VM; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.common.queries.VdcQueryType; +import org.ovirt.engine.core.common.scheduling.parameters.AffinityGroupCRUDParameters; +import org.ovirt.engine.core.compat.Guid; + +public class BackendAffinityGroupVmsResourceTest + extends AbstractBackendCollectionResourceTest<VM, org.ovirt.engine.core.common.businessentities.VM, BackendAffinityGroupVmsResource> { + + private static final Guid AFFINITY_GROUP_ID = Guid.newGuid(); + + public BackendAffinityGroupVmsResourceTest() { + super(new BackendAffinityGroupVmsResource(AFFINITY_GROUP_ID), null, ""); + } + + @Override + protected void setUpQueryExpectations(String query) throws Exception { + assert (query.equals("")); + + setUpGetEntityExpectations(true); + control.replay(); + } + + /** + * Overriding this as the affinity groups collection doesn't support search queries + */ + @Override + @Test + public void testQuery() throws Exception { + testList(); + } + + @Test + public void testAddVMToAffinityGroup() throws Exception { + setUriInfo(setUpBasicUriExpectations()); + setUpGetEntityExpectations(false); + + setUriInfo(setUpActionExpectations(VdcActionType.EditAffinityGroup, + AffinityGroupCRUDParameters.class, + new String[] {}, + new Object[] {}, + true, + true)); + + VM vm = new VM(); + vm.setId(GUIDS[0].toString()); + Response response = collection.add(vm); + assertEquals(200, response.getStatus()); + } + + @Test + public void testRemoveVmFromAffinityGroup() throws Exception { + setUriInfo(setUpBasicUriExpectations()); + setUpGetEntityExpectations(true); + + setUriInfo(setUpActionExpectations(VdcActionType.EditAffinityGroup, + AffinityGroupCRUDParameters.class, + new String[] {}, + new Object[] {}, + true, + true)); + + VM vm = new VM(); + vm.setId(GUIDS[0].toString()); + Response response = collection.remove(GUIDS[0].toString()); + assertEquals(200, response.getStatus()); + } + + private void setUpGetEntityExpectations(boolean withVms) throws Exception { + setUpGetEntityExpectations(VdcQueryType.GetAffinityGroupById, + IdQueryParameters.class, + new String[] { "Id" }, + new Object[] { AFFINITY_GROUP_ID }, + getAffinityGroup(withVms)); + } + + private org.ovirt.engine.core.common.scheduling.AffinityGroup getAffinityGroup(boolean withVms) { + org.ovirt.engine.core.common.scheduling.AffinityGroup affinityGroup = new org.ovirt.engine.core.common.scheduling.AffinityGroup(); + affinityGroup.setEntityIds(new ArrayList<Guid>()); + affinityGroup.setEntityNames(new ArrayList<String>()); + if (withVms) { + for (int i = 0; i < NAMES.length; i++) { + org.ovirt.engine.core.common.businessentities.VM entity = getEntity(i); + affinityGroup.getEntityIds().add(entity.getId()); + affinityGroup.getEntityNames().add(entity.getName()); + } + } + + return affinityGroup; + } + + @Override + protected List<VM> getCollection() { + return collection.list().getVMs(); + } + + @Override + protected void setUpQueryExpectations(String query, Object failure) throws Exception { + setUpEntityQueryExpectations(VdcQueryType.GetAffinityGroupById, + IdQueryParameters.class, + new String[] {}, + new Object[] {}, + null, + failure); + + control.replay(); + } + + @Override + protected void verifyModel(VM model, int index) { + assertEquals(GUIDS[index].toString(), model.getId()); + assertEquals(NAMES[index], model.getName()); + // overriding since vm doesn't has description + //assertEquals(DESCRIPTIONS[index], model.getDescription()); + verifyLinks(model); + } + + @Override + protected org.ovirt.engine.core.common.businessentities.VM getEntity(int index) { + org.ovirt.engine.core.common.businessentities.VM vm = + new org.ovirt.engine.core.common.businessentities.VM(); + vm.setId(GUIDS[index]); + vm.setName(NAMES[index]); + + return vm; + } + +} diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResourceTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResourceTest.java new file mode 100644 index 0000000..d3687e8 --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendAffinityGroupsResourceTest.java @@ -0,0 +1,131 @@ +package org.ovirt.engine.api.restapi.resource; + +import static org.easymock.EasyMock.expect; + +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + +import org.junit.Test; +import org.ovirt.engine.api.model.AffinityGroup; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.queries.IdQueryParameters; +import org.ovirt.engine.core.common.queries.VdcQueryType; +import org.ovirt.engine.core.common.scheduling.parameters.AffinityGroupCRUDParameters; +import org.ovirt.engine.core.compat.Guid; + +public class BackendAffinityGroupsResourceTest extends AbstractBackendCollectionResourceTest<AffinityGroup, org.ovirt.engine.core.common.scheduling.AffinityGroup, BackendAffinityGroupsResource> { + private static final Guid CLUSTER_ID = GUIDS[0]; + + public BackendAffinityGroupsResourceTest() { + super(new BackendAffinityGroupsResource(CLUSTER_ID.toString()), null, ""); + } + + @Override + protected void setUpQueryExpectations(String query, Object failure) throws Exception { + assert (query.equals("")); + + setUpEntityQueryExpectations(VdcQueryType.GetAffinityGroupsByClusterId, + IdQueryParameters.class, + new String[] {}, + new Object[] {}, + setUpAffinityGroups(), + failure); + + control.replay(); + } + + + @Override + protected List<AffinityGroup> getCollection() { + return collection.list().getAffinityGroups(); + } + + @Override + protected org.ovirt.engine.core.common.scheduling.AffinityGroup getEntity(int index) { + org.ovirt.engine.core.common.scheduling.AffinityGroup entity = + control.createMock(org.ovirt.engine.core.common.scheduling.AffinityGroup.class); + expect(entity.getId()).andReturn(GUIDS[index]).anyTimes(); + expect(entity.getName()).andReturn(NAMES[index].toString()).anyTimes(); + expect(entity.getDescription()).andReturn(DESCRIPTIONS[index].toString()).anyTimes(); + expect(entity.getClusterId()).andReturn(CLUSTER_ID).anyTimes(); + expect(entity.isEnforcing()).andReturn(GUIDS[index].hashCode() % 2 == 0).anyTimes(); + expect(entity.isPositive()).andReturn(GUIDS[index].hashCode() % 2 == 1).anyTimes(); + return entity; + } + + /** + * Overriding this as the affinity groups collection doesn't support search queries + */ + @Override + @Test + public void testQuery() throws Exception { + testList(); + } + + @Test + public void testAdd() { + setUriInfo(setUpBasicUriExpectations()); + setUpCreationExpectations(VdcActionType.AddAffinityGroup, + AffinityGroupCRUDParameters.class, + new String[] {}, + new Object[] {}, + true, + true, + GUIDS[0], + VdcQueryType.GetAffinityGroupById, + IdQueryParameters.class, + new String[] { "Id" }, + new Object[] { GUIDS[0] }, + getEntity(0)); + Response response = collection.add(new AffinityGroup()); + assertEquals(201, response.getStatus()); + assertTrue(response.getEntity() instanceof AffinityGroup); + verifyModel((AffinityGroup) response.getEntity(), 0); + } + + @Test + public void testRemove() throws Exception { + setUriInfo(setUpBasicUriExpectations()); + setUpGetEntityExpectations(GUIDS[0], false); + setUpActionExpectations(VdcActionType.RemoveAffinityGroup, + AffinityGroupCRUDParameters.class, + new String[] { "AffinityGroupId" }, + new Object[] { GUIDS[0] }, + true, + true); + verifyRemove(collection.remove(GUIDS[0].toString())); + } + + @Test + public void testRemoveNonExistant() throws Exception { + setUpGetEntityExpectations(NON_EXISTANT_GUID, true); + control.replay(); + try { + collection.remove(NON_EXISTANT_GUID.toString()); + fail("expected WebApplicationException"); + } catch (WebApplicationException wae) { + assertNotNull(wae.getResponse()); + assertEquals(404, wae.getResponse().getStatus()); + } + } + + private void setUpGetEntityExpectations(Guid entityId, Boolean returnNull) throws Exception { + setUpGetEntityExpectations(VdcQueryType.GetAffinityGroupById, + IdQueryParameters.class, + new String[] { "Id" }, + new Object[] { entityId }, + returnNull ? null : getEntity(0)); + } + + private List<org.ovirt.engine.core.common.scheduling.AffinityGroup> setUpAffinityGroups() { + List<org.ovirt.engine.core.common.scheduling.AffinityGroup> list = new ArrayList<>(); + for (int i = 0; i < NAMES.length; i++) { + list.add(getEntity(i)); + } + + return list; + } +} diff --git a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapper.java b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapper.java new file mode 100644 index 0000000..008d97f --- /dev/null +++ b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapper.java @@ -0,0 +1,51 @@ +package org.ovirt.engine.api.restapi.types; + +import org.ovirt.engine.api.model.AffinityGroup; +import org.ovirt.engine.api.model.Cluster; +import org.ovirt.engine.api.restapi.utils.GuidUtils; + +public class AffinityGroupMapper { + + @Mapping(from = org.ovirt.engine.core.common.scheduling.AffinityGroup.class, to = AffinityGroup.class) + public static AffinityGroup map(org.ovirt.engine.core.common.scheduling.AffinityGroup entity, + AffinityGroup template) { + AffinityGroup model = template != null ? template : new AffinityGroup(); + model.setId(entity.getId().toString()); + model.setName(entity.getName()); + model.setDescription(entity.getDescription()); + model.setPositive(entity.isPositive()); + model.setEnforcing(entity.isEnforcing()); + Cluster cluster = new Cluster(); + cluster.setId(entity.getClusterId().toString()); + model.setCluster(cluster); + + return model; + } + + @Mapping(from = AffinityGroup.class, to = org.ovirt.engine.core.common.scheduling.AffinityGroup.class) + public static org.ovirt.engine.core.common.scheduling.AffinityGroup map(AffinityGroup model, + org.ovirt.engine.core.common.scheduling.AffinityGroup template) { + org.ovirt.engine.core.common.scheduling.AffinityGroup entity = + template != null ? template : new org.ovirt.engine.core.common.scheduling.AffinityGroup(); + if (model.isSetId()) { + entity.setId(GuidUtils.asGuid(model.getId())); + } + if (model.isSetName()) { + entity.setName(model.getName()); + } + if (model.isSetDescription()) { + entity.setDescription(model.getDescription()); + } + if (model.isSetCluster() && model.getCluster().isSetId()) { + entity.setClusterId(GuidUtils.asGuid(model.getCluster().getId())); + } + if (model.isSetPositive()) { + entity.setPositive(model.isPositive()); + } + if (model.isSetEnforcing()) { + entity.setEnforcing(model.isEnforcing()); + } + + return entity; + } +} diff --git a/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapperTest.java b/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapperTest.java new file mode 100644 index 0000000..38921187 --- /dev/null +++ b/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/AffinityGroupMapperTest.java @@ -0,0 +1,24 @@ +package org.ovirt.engine.api.restapi.types; + +import org.ovirt.engine.api.model.AffinityGroup; + +public class AffinityGroupMapperTest extends AbstractInvertibleMappingTest<AffinityGroup, org.ovirt.engine.core.common.scheduling.AffinityGroup, org.ovirt.engine.core.common.scheduling.AffinityGroup> { + + public AffinityGroupMapperTest() { + super(AffinityGroup.class, + org.ovirt.engine.core.common.scheduling.AffinityGroup.class, + org.ovirt.engine.core.common.scheduling.AffinityGroup.class); + } + + @Override + protected void verify(AffinityGroup model, AffinityGroup transform) { + assertNotNull(transform); + assertEquals(model.getName(), transform.getName()); + assertEquals(model.getId(), transform.getId()); + assertEquals(model.getDescription(), transform.getDescription()); + assertEquals(model.getCluster().getId(), transform.getCluster().getId()); + assertEquals(model.isPositive(), transform.isPositive()); + assertEquals(model.isEnforcing(), transform.isEnforcing()); + } + +} -- To view, visit http://gerrit.ovirt.org/23452 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie2daa18742eca73517ef739e70e972d74aad4244 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Gilad Chaplik <gchap...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches