Daniel Erez has uploaded a new change for review.

Change subject: restapi: openstack volume providers root collection
......................................................................

restapi: openstack volume providers root collection

Introducing openstack volume providers resources: /api/openstackvolumeproviders
* Support GET/POST/DELETE/UPDATE
* Added openstack_volume_provider(s) elements to api.xsd.
* Updated rsdl_metadata accordingly.
* Updated FeaturesHelper.

Feature Page: http://www.ovirt.org/Features/Cinder_Integration

Change-Id: I89d2e9d975750d2ec22599079603bd48cff2603e
Bug-Url: https://bugzilla.redhat.com/1185826
Signed-off-by: Daniel Erez <de...@redhat.com>
---
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProviderResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProvidersResource.java
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ApiRootLinksCreator.java
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/LinkHelper.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
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/BackendApplication.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java
M 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendApiResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResourceTest.java
A 
backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResourceTest.java
A 
backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/openstack/OpenStackVolumeProviderMapper.java
14 files changed, 764 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/03/39003/1

diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProviderResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProviderResource.java
new file mode 100644
index 0000000..19d01f6
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProviderResource.java
@@ -0,0 +1,27 @@
+/*
+* Copyright (c) 2014 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.openstack;
+
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
+import org.ovirt.engine.api.resource.ApiMediaType;
+import org.ovirt.engine.api.resource.ExternalProviderResource;
+
+import javax.ws.rs.Produces;
+
+@Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
+public interface OpenStackVolumeProviderResource extends 
ExternalProviderResource<OpenStackVolumeProvider> {
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProvidersResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProvidersResource.java
new file mode 100644
index 0000000..a4fbb3f
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/openstack/OpenStackVolumeProvidersResource.java
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2014 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.openstack;
+
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
+import org.ovirt.engine.api.model.OpenStackVolumeProviders;
+import org.ovirt.engine.api.resource.ApiMediaType;
+
+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;
+
+@Path("/openstackvolumeproviders")
+@Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
+public interface OpenStackVolumeProvidersResource {
+    @GET
+    public OpenStackVolumeProviders list();
+
+    @POST
+    @Consumes({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
+    public Response add(OpenStackVolumeProvider provider);
+
+    @DELETE
+    @Path("{id}")
+    public Response remove(@PathParam("id") String id);
+
+    @Path("{id}")
+    public OpenStackVolumeProviderResource 
getOpenStackVolumeProvider(@PathParam("id") String id);
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ApiRootLinksCreator.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ApiRootLinksCreator.java
index 7369fda..cd64a32 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ApiRootLinksCreator.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/ApiRootLinksCreator.java
@@ -61,6 +61,7 @@
         links.add(createLink("operatingsystems", baseUri));
         links.add(createLink("externalhostproviders", baseUri));
         links.add(createLink("openstackimageproviders", baseUri));
+        links.add(createLink("openstackvolumeproviders", baseUri));
         links.add(createLink("openstacknetworkproviders", baseUri));
         links.add(createLink("katelloerrata", baseUri));
         return links;
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/LinkHelper.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/LinkHelper.java
index 49dfd1f7..8ebf97c 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/LinkHelper.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/utils/LinkHelper.java
@@ -78,6 +78,7 @@
 import org.ovirt.engine.api.model.OpenStackNetwork;
 import org.ovirt.engine.api.model.OpenStackNetworkProvider;
 import org.ovirt.engine.api.model.OpenStackSubnet;
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
 import org.ovirt.engine.api.model.OperatingSystemInfo;
 import org.ovirt.engine.api.model.Parameter;
 import org.ovirt.engine.api.model.ParametersSet;
@@ -264,6 +265,8 @@
 import org.ovirt.engine.api.resource.openstack.OpenStackNetworksResource;
 import org.ovirt.engine.api.resource.openstack.OpenStackSubnetResource;
 import org.ovirt.engine.api.resource.openstack.OpenStackSubnetsResource;
+import org.ovirt.engine.api.resource.openstack.OpenStackVolumeProviderResource;
+import 
org.ovirt.engine.api.resource.openstack.OpenStackVolumeProvidersResource;
 
 /**
  * Contains a static addLinks() method which constructs any href attributes
@@ -549,6 +552,10 @@
         map.add(OpenStackImageResource.class, OpenStackImagesResource.class, 
OpenStackImageProvider.class);
         TYPES.put(OpenStackImage.class, map);
 
+        // OpenStack volume providers:
+        map = new ParentToCollectionMap(OpenStackVolumeProviderResource.class, 
OpenStackVolumeProvidersResource.class);
+        TYPES.put(OpenStackVolumeProvider.class, map);
+
         // OpenStack network providers:
         map = new 
ParentToCollectionMap(OpenStackNetworkProviderResource.class, 
OpenStackNetworkProvidersResource.class);
         TYPES.put(OpenStackNetworkProvider.class, map);
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 7a81124..2908879 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
@@ -5090,6 +5090,7 @@
           <xs:element name="requires_authentication" type="xs:boolean" 
minOccurs="0" maxOccurs="1"/>
           <xs:element name="username" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
           <xs:element name="password" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
+          <xs:element name="auth_url" type="xs:string" minOccurs="0" 
maxOccurs="1"/>
           <xs:element ref="properties" minOccurs="0" maxOccurs="1"/>
         </xs:sequence>
       </xs:extension>
@@ -5325,6 +5326,37 @@
     </xs:complexContent>
   </xs:complexType>
 
+  <!-- OpenStack volume providers: -->
+  <xs:element name="openstack_volume_provider" type="OpenStackVolumeProvider"/>
+
+  <xs:complexType name="OpenStackVolumeProvider">
+    <xs:complexContent>
+      <xs:extension base="OpenStackProvider">
+        <xs:sequence>
+          <xs:element ref="data_center" minOccurs="0" maxOccurs="1"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="openstack_volume_providers" 
type="OpenStackVolumeProviders"/>
+
+  <xs:complexType name="OpenStackVolumeProviders">
+    <xs:complexContent>
+      <xs:extension base="BaseResources">
+        <xs:sequence>
+          <xs:element ref="openstack_volume_provider" minOccurs="0" 
maxOccurs="unbounded">
+            <xs:annotation>
+              <xs:appinfo>
+                <jaxb:property name="OpenStackVolumeProviders"/>
+              </xs:appinfo>
+            </xs:annotation>
+          </xs:element>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
   <!-- OpenStack network providers: -->
   <xs:element name="openstack_network_provider" 
type="OpenStackNetworkProvider"/>
 
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 dd76285..129a994 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
@@ -6654,6 +6654,97 @@
       Content-Type: {value: application/xml|json, required: true}
       Correlation-Id: {value: 'any string', required: false}
 
+- name: /openstackvolumeproviders|rel=get
+  description: get the list of all OpenStack volume providers in the system
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams:
+      max: {context: matrix, type: 'xs:int', value: 'max results', required: 
false}
+    headers: {}
+- name: /openstackvolumeproviders/{openstackvolumeprovider:id}|rel=get
+  description: get the details of the specified OpenStack volume provider in 
the system
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams: {}
+    headers: {}
+- name: /openstackvolumeproviders/{openstackvolumeprovider:id}|rel=delete
+  description: delete the specified OpenStack volume provider in the system
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams:
+      async: {context: matrix, type: 'xs:boolean', value: true|false, 
required: false}
+    headers:
+      Correlation-Id: {value: 'any string', required: false}
+- name: /openstackvolumeproviders/{openstackvolumeprovider:id}|rel=update
+  description: update the specified OpenStack volume provider in the system
+  request:
+    body:
+      parameterType: OpenStackVolumeProvider
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments:
+          openstack_volume_provider.name: xs:string
+          openstack_volume_provider.description: xs:string
+          openstack_volume_provider.data_center.id|name: xs:string,
+          openstack_volume_provider.requires_authentication: xs:boolean
+          openstack_volume_provider.username: xs:string
+          openstack_volume_provider.password: xs:string
+          openstack_volume_provider.properties.property--COLLECTION:
+            property.name: xs:string
+            property.value: xs:string
+        description: update the specified OpenStack image provider in the 
system
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Correlation-Id: {value: 'any string', required: false}
+- name: /openstackvolumeproviders|rel=add
+  description: add a new OpenStack volume provider to the system
+  request:
+    body:
+      parameterType: OpenStackVolumeProvider
+      signatures:
+      - mandatoryArguments:
+          openstack_image_provider.name: xs:string
+        optionalArguments:
+          openstack_volume_provider.description: xs:string
+          openstack_volume_provider.url: xs:string
+          openstack_volume_provider.data_center.id|name: xs:string,
+          openstack_volume_provider.requires_authentication: xs:boolean
+          openstack_volume_provider.username: xs:string
+          openstack_volume_provider.password: xs:string
+          openstack_volume_provider.properties.property--COLLECTION:
+            property.name: xs:string
+            property.value: xs:string
+        description: add a new OpenStack image provider to the system
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Expect: {value: 201-created, required: false}
+      Correlation-Id: {value: 'any string', required: false}
+- name: /openstackvolumeproviders/{openstackvolumeprovider:id}/images|rel=get
+  description: get the list of volumes from the OpenStack image provider
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams:
+      max: {context: matrix, type: 'xs:int', value: 'max results', required: 
false}
+    headers: {}
+- name: 
/openstackvolumeproviders/{openstackvolumeprovider:id}/images/{image:id}|rel=get
+  description: get the details of the specified volume from the OpenStack 
image provider
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams: {}
+    headers: {}
+
 - name: /openstacknetworkproviders|rel=get
   description: get the list of all OpenStack network providers in the system
   request:
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/BackendApplication.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/BackendApplication.java
index 1e8a65c..5cfb24c 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/BackendApplication.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/BackendApplication.java
@@ -61,6 +61,7 @@
 import 
org.ovirt.engine.api.restapi.resource.externalhostproviders.BackendSystemKatelloErrataResource;
 import 
org.ovirt.engine.api.restapi.resource.openstack.BackendOpenStackImageProvidersResource;
 import 
org.ovirt.engine.api.restapi.resource.openstack.BackendOpenStackNetworkProvidersResource;
+import 
org.ovirt.engine.api.restapi.resource.openstack.BackendOpenStackVolumeProvidersResource;
 import org.ovirt.engine.api.restapi.resource.validation.IOExceptionMapper;
 import org.ovirt.engine.api.restapi.resource.validation.JsonExceptionMapper;
 import 
org.ovirt.engine.api.restapi.resource.validation.MalformedIdExceptionMapper;
@@ -155,6 +156,7 @@
         addResource(new BackendExternalHostProvidersResource());
         addResource(new BackendOpenStackImageProvidersResource());
         addResource(new BackendOpenStackNetworkProvidersResource());
+        addResource(new BackendOpenStackVolumeProvidersResource());
         addResource(new BackendSystemKatelloErrataResource());
 
         final SessionProcessor processor = new SessionProcessor();
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResource.java
new file mode 100644
index 0000000..7bbe1bd
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResource.java
@@ -0,0 +1,31 @@
+/*
+* Copyright (c) 2014 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.restapi.resource.openstack;
+
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
+import org.ovirt.engine.api.resource.openstack.OpenStackVolumeProviderResource;
+import 
org.ovirt.engine.api.restapi.resource.AbstractBackendExternalProviderResource;
+
+import static 
org.ovirt.engine.api.restapi.resource.openstack.BackendOpenStackVolumeProvidersResource.SUB_COLLECTIONS;
+
+public class BackendOpenStackVolumeProviderResource
+        extends 
AbstractBackendExternalProviderResource<OpenStackVolumeProvider>
+        implements OpenStackVolumeProviderResource {
+    public BackendOpenStackVolumeProviderResource(String id) {
+        super(id, OpenStackVolumeProvider.class, SUB_COLLECTIONS);
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResource.java
new file mode 100644
index 0000000..ecb0765
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResource.java
@@ -0,0 +1,141 @@
+/*
+* Copyright (c) 2014 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.restapi.resource.openstack;
+
+import org.apache.commons.lang.StringUtils;
+import org.ovirt.engine.api.common.util.QueryHelper;
+import org.ovirt.engine.api.model.DataCenter;
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
+import org.ovirt.engine.api.model.OpenStackVolumeProviders;
+import org.ovirt.engine.api.resource.openstack.OpenStackVolumeProviderResource;
+import 
org.ovirt.engine.api.resource.openstack.OpenStackVolumeProvidersResource;
+import org.ovirt.engine.api.restapi.resource.AbstractBackendCollectionResource;
+import org.ovirt.engine.api.restapi.resource.BackendExternalProviderHelper;
+import org.ovirt.engine.api.restapi.resource.SingleEntityResource;
+import org.ovirt.engine.api.restapi.types.DataCenterMapper;
+import org.ovirt.engine.core.common.action.ProviderParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Provider;
+import org.ovirt.engine.core.common.businessentities.ProviderType;
+import org.ovirt.engine.core.common.businessentities.StoragePool;
+import org.ovirt.engine.core.common.interfaces.SearchType;
+import org.ovirt.engine.core.common.queries.GetAllProvidersParameters;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.NameQueryParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+public class BackendOpenStackVolumeProvidersResource
+        extends AbstractBackendCollectionResource<OpenStackVolumeProvider, 
Provider>
+        implements OpenStackVolumeProvidersResource {
+    static final String[] SUB_COLLECTIONS = {
+        "volumetypes",
+        "certificates"
+    };
+
+    public BackendOpenStackVolumeProvidersResource() {
+        super(OpenStackVolumeProvider.class, Provider.class, SUB_COLLECTIONS);
+    }
+
+    @Override
+    public OpenStackVolumeProviders list() {
+        return mapCollection(getBackendCollection());
+    }
+
+    private OpenStackVolumeProviders mapCollection(List<Provider> entities) {
+        OpenStackVolumeProviders collection = new OpenStackVolumeProviders();
+        for (Provider entity : entities) {
+            
collection.getOpenStackVolumeProviders().add(addLinks(map(entity)));
+        }
+        return collection;
+    }
+
+    private List<Provider> getBackendCollection() {
+        if (isFiltered()) {
+            return getBackendCollection(
+                VdcQueryType.GetAllProviders,
+                new GetAllProvidersParameters(ProviderType.OPENSTACK_VOLUME)
+            );
+        }
+        else {
+            return getBackendCollection(SearchType.Provider, getConstraint());
+        }
+    }
+
+    private String getConstraint() {
+        StringBuilder buffer = new StringBuilder();
+        buffer.append("Providers: type=");
+        buffer.append(ProviderType.OPENSTACK_VOLUME.name());
+        String query = QueryHelper.getConstraint(getUriInfo(), null, 
modelType, false);
+        if (StringUtils.isNotBlank(query)) {
+            buffer.append(" AND (");
+            buffer.append(query);
+            buffer.append(")");
+        }
+        return buffer.toString();
+    }
+
+    @Override
+    public Response add(OpenStackVolumeProvider provider) {
+        validateParameters(provider, "name", "dataCenter.name|id");
+        StoragePool storagePool = getStoragePool(provider.getDataCenter());
+        provider.setDataCenter(DataCenterMapper.map(storagePool, null));
+        return performCreate(
+                VdcActionType.AddProvider,
+                new ProviderParameters(map(provider)),
+                new QueryIdResolver<Guid>(VdcQueryType.GetProviderById, 
IdQueryParameters.class)
+        );
+    }
+
+    @Override
+    protected Response performRemove(String id) {
+        Provider provider = BackendExternalProviderHelper.getProvider(this, 
id);
+        ProviderParameters parameters = new ProviderParameters(provider);
+        return performAction(VdcActionType.RemoveProvider, parameters);
+    }
+
+    @Override
+    protected OpenStackVolumeProvider doPopulate(OpenStackVolumeProvider 
model, Provider entity) {
+        return model;
+    }
+
+    @Override
+    @SingleEntityResource
+    public OpenStackVolumeProviderResource 
getOpenStackVolumeProvider(@PathParam("id") String id) {
+        return inject(new BackendOpenStackVolumeProviderResource(id));
+    }
+
+    public StoragePool getStoragePool(DataCenter dataCenter) {
+        StoragePool pool = null;
+        if (dataCenter.isSetId()) {
+            Guid id = asGuid(dataCenter.getId());
+            pool = getEntity(StoragePool.class, 
VdcQueryType.GetStoragePoolById,
+                    new IdQueryParameters(id), "Datacenter: id=" + 
dataCenter.getId());
+        } else if (dataCenter.isSetName()) {
+            pool = getEntity(StoragePool.class, 
VdcQueryType.GetStoragePoolByDatacenterName,
+                    new NameQueryParameters(dataCenter.getName()), 
"Datacenter: name=" + dataCenter.getName());
+        }
+        if (pool == null) {
+            notFound(DataCenter.class);
+        }
+        return pool;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java
index a0a0183..eace5e3 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/utils/FeaturesHelper.java
@@ -98,6 +98,7 @@
             addErrataForHostsFeature(features);
             addCumulativeNetworkUsageFeature(features);
             addGuestMemoryBufferedCached(features);
+            addOpenStackVolumeProvidersFeature(features);
         }
         return features;
     }
@@ -560,4 +561,11 @@
         feature.setDescription("Report of used cached and buffered memory in 
the guest OS");
         features.getFeature().add(feature);
     }
+
+    private void addOpenStackVolumeProvidersFeature(Features features) {
+        Feature feature = new Feature();
+        feature.setName("OpenStack Volume Providers");
+        feature.setDescription("Add/modify/remove OpenStack volume 
providers.");
+        features.getFeature().add(feature);
+    }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendApiResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendApiResourceTest.java
index dfa9850..cf72733 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendApiResourceTest.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendApiResourceTest.java
@@ -130,6 +130,7 @@
         "operatingsystems",
         "externalhostproviders",
         "openstackimageproviders",
+        "openstackvolumeproviders",
         "openstacknetworkproviders",
         "katelloerrata"
     };
@@ -197,6 +198,7 @@
         BASE_PATH + "/operatingsystems",
         BASE_PATH + "/externalhostproviders",
         BASE_PATH + "/openstackimageproviders",
+        BASE_PATH + "/openstackvolumeproviders",
         BASE_PATH + "/openstacknetworkproviders",
         BASE_PATH + "/katelloerrata"
     };
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResourceTest.java
new file mode 100644
index 0000000..8abf0fd
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProviderResourceTest.java
@@ -0,0 +1,179 @@
+/*
+* Copyright (c) 2014 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.restapi.resource.openstack;
+
+import org.junit.Test;
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
+import org.ovirt.engine.api.restapi.resource.AbstractBackendSubResourceTest;
+import org.ovirt.engine.core.common.action.ProviderParameters;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Provider;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+
+import javax.ws.rs.WebApplicationException;
+
+import static org.easymock.EasyMock.expect;
+
+public class BackendOpenStackVolumeProviderResourceTest
+        extends AbstractBackendSubResourceTest<OpenStackVolumeProvider, 
Provider, BackendOpenStackVolumeProviderResource> {
+    public BackendOpenStackVolumeProviderResourceTest() {
+        super(new BackendOpenStackVolumeProviderResource(GUIDS[0].toString()));
+    }
+
+    @Test
+    public void testBadGuid() throws Exception {
+        control.replay();
+        try {
+            new BackendOpenStackVolumeProviderResource("foo");
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyNotFoundException(wae);
+        }
+    }
+
+    @Test
+    public void testGetNotFound() throws Exception {
+        setUriInfo(setUpBasicUriExpectations());
+        setUpGetEntityExpectations(1, true);
+        control.replay();
+        try {
+            resource.get();
+            fail("expected WebApplicationException");
+        } catch (WebApplicationException wae) {
+            verifyNotFoundException(wae);
+        }
+    }
+
+    @Test
+    public void testGet() throws Exception {
+        setUriInfo(setUpBasicUriExpectations());
+        setUpGetEntityExpectations(1);
+        control.replay();
+        verifyModel(resource.get(), 0);
+    }
+
+    @Test
+    public void testUpdateNotFound() throws Exception {
+        setUriInfo(setUpBasicUriExpectations());
+        setUpGetEntityExpectations(1, true);
+        control.replay();
+        try {
+            resource.update(getModel(0));
+            fail("expected WebApplicationException");
+        } catch (WebApplicationException wae) {
+            verifyNotFoundException(wae);
+        }
+    }
+
+    @Test
+    public void testUpdate() throws Exception {
+        setUpGetEntityExpectations(2);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.UpdateProvider,
+                ProviderParameters.class,
+                new String[] { "Provider.Id" },
+                new Object[] { GUIDS[0] },
+                true,
+                true
+            )
+        );
+        verifyModel(resource.update(getModel(0)), 0);
+    }
+
+    @Test
+    public void testUpdateCantDo() throws Exception {
+        doTestBadUpdate(false, true, CANT_DO);
+    }
+
+    @Test
+    public void testUpdateFailed() throws Exception {
+        doTestBadUpdate(true, false, FAILURE);
+    }
+
+    private void doTestBadUpdate(boolean canDo, boolean success, String 
detail) throws Exception {
+        setUpGetEntityExpectations(1);
+        setUriInfo(
+            setUpActionExpectations(
+                VdcActionType.UpdateProvider,
+                ProviderParameters.class,
+                new String[] { "Provider.Id" },
+                new Object[] { GUIDS[0] },
+                canDo,
+                success
+            )
+        );
+        try {
+            resource.update(getModel(0));
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyFault(wae, detail);
+        }
+    }
+
+    @Test
+    public void testConflictedUpdate() throws Exception {
+        setUriInfo(setUpBasicUriExpectations());
+        setUpGetEntityExpectations(1);
+        control.replay();
+
+        OpenStackVolumeProvider model = getModel(1);
+        model.setId(GUIDS[1].toString());
+        try {
+            resource.update(model);
+            fail("expected WebApplicationException");
+        }
+        catch (WebApplicationException wae) {
+            verifyImmutabilityConstraint(wae);
+        }
+    }
+
+    private OpenStackVolumeProvider getModel(int index) {
+        OpenStackVolumeProvider model = new OpenStackVolumeProvider();
+        model.setName(NAMES[index]);
+        model.setDescription(DESCRIPTIONS[index]);
+        return model;
+    }
+
+    @Override
+    protected Provider getEntity(int index) {
+        Provider provider = control.createMock(Provider.class);
+        expect(provider.getId()).andReturn(GUIDS[index]).anyTimes();
+        expect(provider.getName()).andReturn(NAMES[index]).anyTimes();
+        
expect(provider.getDescription()).andReturn(DESCRIPTIONS[index]).anyTimes();
+        return provider;
+    }
+
+    protected void setUpGetEntityExpectations(int times) throws Exception {
+        setUpGetEntityExpectations(times, false);
+    }
+
+    protected void setUpGetEntityExpectations(int times, boolean notFound) 
throws Exception {
+        while (times-- > 0) {
+            setUpGetEntityExpectations(
+                VdcQueryType.GetProviderById,
+                IdQueryParameters.class,
+                new String[] { "Id" },
+                new Object[] { GUIDS[0] },
+                notFound? null: getEntity(0)
+            );
+        }
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResourceTest.java
 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResourceTest.java
new file mode 100644
index 0000000..6d2fdeb
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/openstack/BackendOpenStackVolumeProvidersResourceTest.java
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2014 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.restapi.resource.openstack;
+
+import org.apache.commons.lang.StringUtils;
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
+import 
org.ovirt.engine.api.restapi.resource.AbstractBackendCollectionResourceTest;
+import org.ovirt.engine.core.common.businessentities.Provider;
+import org.ovirt.engine.core.common.businessentities.ProviderType;
+import org.ovirt.engine.core.common.interfaces.SearchType;
+
+import java.util.List;
+
+import static org.easymock.EasyMock.expect;
+
+public class BackendOpenStackVolumeProvidersResourceTest extends
+        AbstractBackendCollectionResourceTest<OpenStackVolumeProvider, 
Provider, BackendOpenStackVolumeProvidersResource> {
+
+    public BackendOpenStackVolumeProvidersResourceTest() {
+        super(
+            new BackendOpenStackVolumeProvidersResource(),
+            SearchType.Provider,
+            "Providers: type=" + ProviderType.OPENSTACK_VOLUME.name()
+        );
+    }
+
+    @Override
+    protected List<OpenStackVolumeProvider> getCollection() {
+        return collection.list().getOpenStackVolumeProviders();
+    }
+
+    @Override
+    protected void setUpQueryExpectations(String query) throws Exception {
+        if (StringUtils.isNotBlank(query)) {
+            query = " AND (" + query + ")";
+        }
+        super.setUpQueryExpectations(query);
+    }
+
+    @Override
+    protected Provider getEntity(int index) {
+        Provider provider = control.createMock(Provider.class);
+        expect(provider.getId()).andReturn(GUIDS[index]).anyTimes();
+        expect(provider.getName()).andReturn(NAMES[index]).anyTimes();
+        
expect(provider.getDescription()).andReturn(DESCRIPTIONS[index]).anyTimes();
+        return provider;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/openstack/OpenStackVolumeProviderMapper.java
 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/openstack/OpenStackVolumeProviderMapper.java
new file mode 100644
index 0000000..23d2ed5
--- /dev/null
+++ 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/openstack/OpenStackVolumeProviderMapper.java
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2014 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.restapi.types.openstack;
+
+import org.ovirt.engine.api.model.DataCenter;
+import org.ovirt.engine.api.model.OpenStackVolumeProvider;
+import org.ovirt.engine.api.model.Properties;
+import org.ovirt.engine.api.model.Property;
+import org.ovirt.engine.api.restapi.types.Mapping;
+import org.ovirt.engine.api.restapi.utils.GuidUtils;
+import org.ovirt.engine.core.common.businessentities.Provider;
+import org.ovirt.engine.core.common.businessentities.ProviderType;
+import 
org.ovirt.engine.core.common.businessentities.storage.OpenStackVolumeProviderProperties;
+import org.ovirt.engine.core.compat.Guid;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class OpenStackVolumeProviderMapper {
+    @Mapping(from = OpenStackVolumeProvider.class, to = Provider.class)
+    public static Provider<OpenStackVolumeProviderProperties> 
map(OpenStackVolumeProvider model,
+                Provider<OpenStackVolumeProviderProperties> template) {
+        Provider<OpenStackVolumeProviderProperties> entity =
+                template != null? template: new 
Provider<OpenStackVolumeProviderProperties>();
+        entity.setType(ProviderType.OPENSTACK_VOLUME);
+        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.isSetUrl()) {
+            entity.setUrl(model.getUrl());
+        }
+        if (model.isSetRequiresAuthentication()) {
+            
entity.setRequiringAuthentication(model.isRequiresAuthentication());
+        }
+        if (model.isSetUsername()) {
+            entity.setUsername(model.getUsername());
+        }
+        if (model.isSetPassword()) {
+            entity.setPassword(model.getPassword());
+        }
+        if (model.isSetAuthUrl()) {
+            entity.setAuthUrl(model.getAuthUrl());
+        }
+        if (model.isSetProperties()) {
+            Map<String, String> map = new HashMap<>();
+            for (Property property : model.getProperties().getProperties()) {
+                map.put(property.getName(), property.getValue());
+            }
+            entity.setCustomProperties(map);
+        }
+        OpenStackVolumeProviderProperties additionalProperties = new 
OpenStackVolumeProviderProperties();
+        if (model.isSetTenantName()) {
+            additionalProperties.setTenantName(model.getTenantName());
+        }
+        if (model.isSetDataCenter()) {
+            
additionalProperties.setStoragePoolId(Guid.createGuidFromString(model.getDataCenter().getId()));
+        }
+        entity.setAdditionalProperties(additionalProperties);
+        return entity;
+    }
+
+    @Mapping(from = Provider.class, to = OpenStackVolumeProvider.class)
+    public static OpenStackVolumeProvider 
map(Provider<OpenStackVolumeProviderProperties> entity,
+                                              OpenStackVolumeProvider 
template) {
+        OpenStackVolumeProvider model = template != null? template: new 
OpenStackVolumeProvider();
+        if (entity.getId() != null) {
+            model.setId(entity.getId().toString());
+        }
+        if (entity.getName() != null) {
+            model.setName(entity.getName());
+        }
+        if (entity.getDescription() != null) {
+            model.setDescription(entity.getDescription());
+        }
+        if (entity.getUrl() != null) {
+            model.setUrl(entity.getUrl());
+        }
+        if (entity.getAuthUrl() != null) {
+            model.setAuthUrl(entity.getAuthUrl());
+        }
+        model.setRequiresAuthentication(entity.isRequiringAuthentication());
+        if (entity.getUsername() != null) {
+            model.setUsername(entity.getUsername());
+        }
+        // The password isn't mapped for security reasons.
+        // if (entity.getPassword() != null) {
+        //     model.setPassword(entity.getPassword());
+        // }
+        Map<String, String> customProperties = entity.getCustomProperties();
+        if (customProperties != null) {
+            Properties properties = new Properties();
+            for (Map.Entry<String, String> entry : 
customProperties.entrySet()) {
+                Property property = new Property();
+                property.setName(entry.getKey());
+                property.setValue(entry.getValue());
+                properties.getProperties().add(property);
+            }
+            model.setProperties(properties);
+        }
+        OpenStackVolumeProviderProperties additionalProperties = 
entity.getAdditionalProperties();
+        if (additionalProperties != null) {
+            if (additionalProperties.getTenantName() != null) {
+                model.setTenantName(additionalProperties.getTenantName());
+            }
+            if (additionalProperties.getStoragePoolId() != null) {
+                DataCenter dataCenter = new DataCenter();
+                
dataCenter.setId(additionalProperties.getStoragePoolId().toString());
+                model.setDataCenter(dataCenter);
+            }
+        }
+        return model;
+    }
+}


-- 
To view, visit https://gerrit.ovirt.org/39003
To unsubscribe, visit https://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I89d2e9d975750d2ec22599079603bd48cff2603e
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Daniel Erez <de...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to