Gilad Chaplik has uploaded a new change for review.

Change subject: restapi: implement Quota REST-API
......................................................................

restapi: implement Quota REST-API

adding quota element to REST-API:
Quota is a subcollection of Data Center and consists limits
for consuming cluster (# of vcpus, memory(GB)) and storage (size (GB))
resources.
Quota entity:
- data_center - link to DC
- soft and hard thresholds (in percentage), grace and threshould in UI.
- Quota sub collections:
        StorageQuotaLimit entity
        - storage_domain - link to specific storage domain,
        no link means it's a single global limit for all SD in DC
        - limit- the actual limit in GB (-1 unlimited)
        - usage- current usage of the limit
        ClusterQuotaLimit entity
        - cluster - link to specific cluster, no link
        means it's a single global limit for all cluster in DC
        - vcpu_limit - limit for vcpus (-1 unlimited)
        - vcpu_usage - current usage of vcpus
        - memroy_limit - limit for memory (in GB)
        - memory_usage - current usage of memroy
Change-Id: Ifaead35839c2c5f89f1551e67e58a58aa253cab5
Bug-Url: https://bugzilla.redhat.com/893927
Signed-off-by: Gilad Chaplik <[email protected]>
---
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitsResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitsResource.java
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaResource.java
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotasResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/StorageQuotaLimitResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/StorageQuotaLimitsResource.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
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitsResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitsResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotasResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitsResource.java
M 
backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QuotaMapper.java
20 files changed, 839 insertions(+), 14 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/04/39904/1

diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitResource.java
new file mode 100644
index 0000000..aefdee3
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitResource.java
@@ -0,0 +1,9 @@
+package org.ovirt.engine.api.resource;
+
+import javax.ws.rs.Produces;
+
+import org.ovirt.engine.api.model.ClusterQuotaLimit;
+
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface ClusterQuotaLimitResource extends 
QuotaLimitResource<ClusterQuotaLimit> {
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitsResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitsResource.java
new file mode 100644
index 0000000..92c64f9
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/ClusterQuotaLimitsResource.java
@@ -0,0 +1,16 @@
+package org.ovirt.engine.api.resource;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.ovirt.engine.api.model.ClusterQuotaLimit;
+import org.ovirt.engine.api.model.ClusterQuotaLimits;
+
+@Path("/clusterquotalimits")
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface ClusterQuotaLimitsResource extends 
QuotaLimitsResource<ClusterQuotaLimits, ClusterQuotaLimit> {
+    @Override
+    @Path("{id}")
+    public ClusterQuotaLimitResource getSubResource(@PathParam("id") String 
id);
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitResource.java
new file mode 100644
index 0000000..34f57ba
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitResource.java
@@ -0,0 +1,12 @@
+package org.ovirt.engine.api.resource;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Produces;
+
+import org.ovirt.engine.api.model.BaseResource;
+
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface QuotaLimitResource<Q extends BaseResource> {
+    @GET
+    public Q get();
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitsResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitsResource.java
new file mode 100644
index 0000000..f782615
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaLimitsResource.java
@@ -0,0 +1,30 @@
+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.ovirt.engine.api.model.BaseResource;
+import org.ovirt.engine.api.model.BaseResources;
+
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface QuotaLimitsResource<P extends BaseResources, Q extends 
BaseResource> {
+    @GET
+    public P list();
+
+    @POST
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    public Q add(Q limit);
+
+    @DELETE
+    @Path("{id}")
+    public Response remove(@PathParam("id") String id);
+
+    @Path("{id}")
+    public QuotaLimitResource<Q> getSubResource(@PathParam("id") String id);
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaResource.java
index 258a3cb..97a8e3f 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaResource.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotaResource.java
@@ -1,13 +1,16 @@
 package org.ovirt.engine.api.resource;
 
-import javax.ws.rs.GET;
+import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 
 import org.ovirt.engine.api.model.Quota;
 
 @Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
-public interface QuotaResource {
+public interface QuotaResource extends UpdatableResource<Quota> {
 
-    @GET
-    public Quota get();
+    @Path("storagequotalimits")
+    public StorageQuotaLimitsResource getStorageQuotaLimitsResource();
+
+    @Path("clusterquotalimits")
+    public ClusterQuotaLimitsResource getClusterQuotaLimitsResource();
 }
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotasResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotasResource.java
index 0abc471..36cc759 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotasResource.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QuotasResource.java
@@ -1,10 +1,15 @@
 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.ovirt.engine.api.model.Quota;
 import org.ovirt.engine.api.model.Quotas;
 
 @Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML})
@@ -16,4 +21,11 @@
     @Path("{id}")
     public QuotaResource getQuotaSubResource(@PathParam("id") String id);
 
+    @POST
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    public Response add(Quota quota);
+
+    @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/StorageQuotaLimitResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/StorageQuotaLimitResource.java
new file mode 100644
index 0000000..04b570e
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/StorageQuotaLimitResource.java
@@ -0,0 +1,9 @@
+package org.ovirt.engine.api.resource;
+
+import javax.ws.rs.Produces;
+
+import org.ovirt.engine.api.model.StorageQuotaLimit;
+
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface StorageQuotaLimitResource extends 
QuotaLimitResource<StorageQuotaLimit> {
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/StorageQuotaLimitsResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/StorageQuotaLimitsResource.java
new file mode 100644
index 0000000..35fd37a
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/StorageQuotaLimitsResource.java
@@ -0,0 +1,16 @@
+package org.ovirt.engine.api.resource;
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+
+import org.ovirt.engine.api.model.StorageQuotaLimit;
+import org.ovirt.engine.api.model.StorageQuotaLimits;
+
+@Path("/storagequotalimits")
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface StorageQuotaLimitsResource extends 
QuotaLimitsResource<StorageQuotaLimits, StorageQuotaLimit> {
+    @Override
+    @Path("{id}")
+    public StorageQuotaLimitResource getSubResource(@PathParam("id") String 
id);
+}
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 0cb7f33..ab43620 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
@@ -38,6 +38,7 @@
 import org.ovirt.engine.api.model.Bookmark;
 import org.ovirt.engine.api.model.CdRom;
 import org.ovirt.engine.api.model.Cluster;
+import org.ovirt.engine.api.model.ClusterQuotaLimit;
 import org.ovirt.engine.api.model.CpuProfile;
 import org.ovirt.engine.api.model.DataCenter;
 import org.ovirt.engine.api.model.DetailedLink;
@@ -99,6 +100,7 @@
 import org.ovirt.engine.api.model.Storage;
 import org.ovirt.engine.api.model.StorageConnection;
 import org.ovirt.engine.api.model.StorageDomain;
+import org.ovirt.engine.api.model.StorageQuotaLimit;
 import org.ovirt.engine.api.model.Tag;
 import org.ovirt.engine.api.model.Template;
 import org.ovirt.engine.api.model.Url;
@@ -126,6 +128,8 @@
 import org.ovirt.engine.api.resource.BookmarksResource;
 import org.ovirt.engine.api.resource.CapabilitiesResource;
 import org.ovirt.engine.api.resource.CapabiliyResource;
+import org.ovirt.engine.api.resource.ClusterQuotaLimitResource;
+import org.ovirt.engine.api.resource.ClusterQuotaLimitsResource;
 import org.ovirt.engine.api.resource.ClusterResource;
 import org.ovirt.engine.api.resource.ClustersResource;
 import org.ovirt.engine.api.resource.CpuProfileResource;
@@ -196,6 +200,8 @@
 import org.ovirt.engine.api.resource.StorageDomainContentsResource;
 import org.ovirt.engine.api.resource.StorageDomainResource;
 import org.ovirt.engine.api.resource.StorageDomainsResource;
+import org.ovirt.engine.api.resource.StorageQuotaLimitResource;
+import org.ovirt.engine.api.resource.StorageQuotaLimitsResource;
 import org.ovirt.engine.api.resource.StorageResource;
 import org.ovirt.engine.api.resource.StorageServerConnectionResource;
 import org.ovirt.engine.api.resource.StorageServerConnectionsResource;
@@ -456,6 +462,11 @@
         map = new ParentToCollectionMap(QuotaResource.class, 
QuotasResource.class, DataCenter.class);
         TYPES.put(Quota.class, map);
 
+        map = new ParentToCollectionMap(StorageQuotaLimitResource.class, 
StorageQuotaLimitsResource.class, Quota.class);
+        TYPES.put(StorageQuotaLimit.class, map);
+        map = new ParentToCollectionMap(ClusterQuotaLimitResource.class, 
ClusterQuotaLimitsResource.class, Quota.class);
+        TYPES.put(ClusterQuotaLimit.class, map);
+
         map = new ParentToCollectionMap(GlusterVolumeResource.class, 
GlusterVolumesResource.class, Cluster.class);
         TYPES.put(GlusterVolume.class, map);
         TYPES.put(GlusterVolumeProfileDetails.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 5fcb62d..1f1ee40 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
@@ -4058,6 +4058,10 @@
           <xs:element ref="vms" minOccurs="0" maxOccurs="1"/>
           <xs:element ref="disks" minOccurs="0" maxOccurs="1"/>
           <xs:element ref="users" minOccurs="0" maxOccurs="1"/>
+          <xs:element name="cluster_soft_limit_pct" type="xs:int" 
minOccurs="0" maxOccurs="1"/>
+          <xs:element name="cluster_hard_limit_pct" type="xs:int" 
minOccurs="0" maxOccurs="1"/>
+          <xs:element name="storage_soft_limit_pct" type="xs:int" 
minOccurs="0" maxOccurs="1"/>
+          <xs:element name="storage_hard_limit_pct" type="xs:int" 
minOccurs="0" maxOccurs="1"/>
         </xs:sequence>
       </xs:extension>
     </xs:complexContent>
@@ -4079,6 +4083,84 @@
       </xs:extension>
     </xs:complexContent>
   </xs:complexType>
+
+  <xs:element name="storage_quota_limit" type="StorageQuotaLimit" />
+
+  <xs:complexType name="StorageQuotaLimit">
+    <xs:complexContent>
+      <xs:extension base="BaseResource">
+        <xs:sequence>
+          <xs:element ref="quota" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element ref="storage_domain" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element name="limit" type="xs:long" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element name="usage" type="xs:double" minOccurs="0"
+            maxOccurs="1" />
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="storage_quota_limits" type="StorageQuotaLimits" />
+
+  <xs:complexType name="StorageQuotaLimits">
+    <xs:complexContent>
+      <xs:extension base="BaseResources">
+        <xs:sequence>
+          <xs:element ref="storage_quota_limit" minOccurs="0" 
maxOccurs="unbounded">
+            <xs:annotation>
+              <xs:appinfo>
+                <jaxb:property name="StorageQuotaLimits" />
+              </xs:appinfo>
+            </xs:annotation>
+          </xs:element>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="cluster_quota_limit" type="ClusterQuotaLimit" />
+
+  <xs:complexType name="ClusterQuotaLimit">
+    <xs:complexContent>
+      <xs:extension base="BaseResource">
+        <xs:sequence>
+          <xs:element ref="quota" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element ref="cluster" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element name="vcpu_limit" type="xs:int" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element name="vcpu_usage" type="xs:int" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element name="memory_limit" type="xs:double" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element name="memory_usage" type="xs:double" minOccurs="0"
+            maxOccurs="1" />
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="cluster_quota_limits" type="ClusterQuotaLimits" />
+
+  <xs:complexType name="ClusterQuotaLimits">
+    <xs:complexContent>
+      <xs:extension base="BaseResources">
+        <xs:sequence>
+          <xs:element ref="cluster_quota_limit" minOccurs="0" 
maxOccurs="unbounded">
+            <xs:annotation>
+              <xs:appinfo>
+                <jaxb:property name="ClusterQuotaLimits" />
+              </xs:appinfo>
+            </xs:annotation>
+          </xs:element>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
   <!-- RSDL -->
 
   <xs:element name="url" type="Url"/>
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 3f45540..1b71d64 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
@@ -5465,3 +5465,108 @@
     body:
       parameterType: null
       signatures: []
+- name: /datacenters/{datacenter:id}/quotas|rel=get
+  description: get a list of Quotas for specified Data Center
+  request:
+    body:
+      parameterType: null
+      signatures: []
+- name: /datacenters/{datacenter:id}/quotas/{quota:id}|rel=get
+  description: get the details of the specified Quota
+  request:
+    body:
+      parameterType: null
+      signatures: []
+- name: /datacenters/{datacenter:id}/quotas/{quota:id}|rel=delete
+  description: delete the specified user defined scheduling policy in the 
system
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams:
+      async: {context: matrix, type: 'xs:boolean', value: true|false, 
required: false}
+- name: /datacenters/{datacenter:id}/quotas|rel=add
+  description: add a new Quota to a Data Center
+  request:
+    body:
+      parameterType: Quota
+      signatures:
+      - mandatoryArguments: {quota.name: 'xs:string'}
+        optionalArguments:
+          quota.description: xs:string
+          quota.cluster_soft_limit_pct: xs:int
+          quota.cluster_hard_limit_pct: xs:int
+          quota.storage_soft_limit_pct: xs:int
+          quota.storage_hard_limit_pct: xs:int
+        description: add a new Quota to a Data Center
+- name: /datacenters/{datacenter:id}/quotas/{quota:id}|rel=update
+  description: update the specified Quota
+  request:
+    body:
+      parameterType: Quota
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments:
+          quota.name: xs:string
+          quota.description: xs:string
+          quota.cluster_soft_limit_pct: xs:int
+          quota.cluster_hard_limit_pct: xs:int
+          quota.storage_soft_limit_pct: xs:int
+          quota.storage_hard_limit_pct: xs:int
+        description: update the specified Quota
+- name: 
/datacenters/{datacenter:id}/quotas/{quota:id}/storagequotalimits|rel=get
+  description: get a list of specified storage limits of a Quota
+  request:
+    body:
+      parameterType: null
+      signatures: []
+- name: 
/datacenters/{datacenter:id}/quotas/{quota:id}/storagequotalimits/{storagequotalimit:id}|rel=get
+  description: get a specified storage limit of a Quota
+  request:
+    body:
+      parameterType: null
+      signatures: []
+- name: 
/datacenters/{datacenter:id}/quotas/{quota:id}/storagequotalimits/{storagequotalimit:id}|rel=delete
+  description: delete a storage limit from a Quota
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams:
+      async: {context: matrix, type: 'xs:boolean', value: true|false, 
required: false}
+- name: 
/datacenters/{datacenter:id}/quotas/{quota:id}/storagequotalimits|rel=add
+  description: add a storage limit to a specified Quota
+  request:
+    body:
+      parameterType: StorageQuotaLimit
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments:
+          storage_domain.id: 'xs:string'
+          limit: 'xs:long'
+        description: add a storage limit to a specified Quota
+- name: 
/datacenters/{datacenter:id}/quotas/{quota:id}/clusterquotalimits/{clusterquotalimit:id}|rel=get
+  description: get a specified cluster limit of a Quota
+  request:
+    body:
+      parameterType: null
+      signatures: []
+- name: 
/datacenters/{datacenter:id}/quotas/{quota:id}/clusterquotalimits/{clusterquotalimit:id}|rel=delete
+  description: delete a cluster limit from a Quota
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams:
+      async: {context: matrix, type: 'xs:boolean', value: true|false, 
required: false}
+- name: 
/datacenters/{datacenter:id}/quotas/{quota:id}/clusterquotalimits|rel=add
+  description: add a cluster limit to a specified Quota
+  request:
+    body:
+      parameterType: ClusterQuotaLimit
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments:
+          cluster_domain.id: 'xs:string'
+          limit: 'xs:long'
+        description: add a cluster limit to a specified Quota
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitResource.java
new file mode 100644
index 0000000..6d55744
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitResource.java
@@ -0,0 +1,20 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.ClusterQuotaLimit;
+import org.ovirt.engine.api.resource.ClusterQuotaLimitResource;
+import org.ovirt.engine.core.compat.Guid;
+
+public class BackendClusterQuotaLimitResource extends 
BackendQuotaLimitResource<ClusterQuotaLimit> implements
+        ClusterQuotaLimitResource {
+
+    protected BackendClusterQuotaLimitResource(String id, Guid parentId) {
+        super(id, parentId, ClusterQuotaLimit.class);
+    }
+
+    @Override
+    protected ClusterQuotaLimit createQuotaLimit() {
+        ClusterQuotaLimit limit = new ClusterQuotaLimit();
+        limit.setId(id);
+        return limit;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitsResource.java
new file mode 100644
index 0000000..2bf5d7b
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClusterQuotaLimitsResource.java
@@ -0,0 +1,80 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.jboss.resteasy.spi.NotFoundException;
+import org.ovirt.engine.api.model.ClusterQuotaLimit;
+import org.ovirt.engine.api.model.ClusterQuotaLimits;
+import org.ovirt.engine.api.resource.ClusterQuotaLimitResource;
+import org.ovirt.engine.api.resource.ClusterQuotaLimitsResource;
+import org.ovirt.engine.core.common.businessentities.Quota;
+import org.ovirt.engine.core.common.businessentities.QuotaVdsGroup;
+import org.ovirt.engine.core.compat.Guid;
+
+public class BackendClusterQuotaLimitsResource extends 
BackendQuotaLimitsResource<ClusterQuotaLimits, ClusterQuotaLimit> implements 
ClusterQuotaLimitsResource {
+
+    protected BackendClusterQuotaLimitsResource(Guid quotaId) {
+        super(quotaId, ClusterQuotaLimit.class);
+    }
+
+    @Override
+    public ClusterQuotaLimits list() {
+        Quota quota = getQuota();
+        ClusterQuotaLimits limits = new ClusterQuotaLimits();
+        if (quota.getGlobalQuotaVdsGroup() != null) {
+            addLimit(quota.getGlobalQuotaVdsGroup(), quotaId.toString(), 
limits, quota);
+        } else if (quota.getQuotaVdsGroups() != null) {
+            for (QuotaVdsGroup quotaCluster : quota.getQuotaVdsGroups()) {
+                addLimit(quotaCluster, 
quotaCluster.getVdsGroupId().toString(), limits, quota);
+            }
+        }
+        return limits;
+    }
+
+    private void addLimit(QuotaVdsGroup quotaCluster, String id, 
ClusterQuotaLimits limits, Quota quota) {
+        ClusterQuotaLimit limit = new ClusterQuotaLimit();
+        limit.setId(id);
+        limits.getClusterQuotaLimits().add(addLinks(map(quota, limit)));
+    }
+
+    @Override
+    @SingleEntityResource
+    public ClusterQuotaLimitResource getSubResource(String id) {
+        return inject(new BackendClusterQuotaLimitResource(id, quotaId));
+    }
+
+    @Override
+    protected void updateEntityForRemove(Quota entity, Guid id) {
+        // since we're mocking remove using update, we'll throw 404 if the 
object isn't found
+        boolean throw404 = false;
+        // global cluster (has same id as quota)
+        if (entity.getId().equals(id)) {
+            if (entity.getGlobalQuotaVdsGroup() == null) {
+                throw404 = true;
+            } else {
+                entity.setGlobalQuotaVdsGroup(null);
+            }
+            // specific cluster (has same id as cluster)
+        } else {
+            if (entity.getQuotaVdsGroups() != null) {
+                for (int i = 0; i < entity.getQuotaVdsGroups().size(); i++) {
+                    if 
(entity.getQuotaVdsGroups().get(i).getVdsGroupId().equals(id)) {
+                        entity.getQuotaVdsGroups().remove(i);
+                        return;
+                    }
+                }
+                throw404 = true;
+            }
+        }
+        if (throw404) {
+            throw new NotFoundException("");
+        }
+    }
+
+    @Override
+    protected void updateIncomingId(ClusterQuotaLimit incoming, Quota entity) {
+        if (incoming.isSetCluster() && incoming.getCluster().isSetId()) {
+            incoming.setId(incoming.getCluster().getId());
+        } else {
+            incoming.setId(entity.getId().toString());
+        }
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitResource.java
new file mode 100644
index 0000000..083a396
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitResource.java
@@ -0,0 +1,38 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.BaseResource;
+import org.ovirt.engine.api.resource.QuotaLimitResource;
+import org.ovirt.engine.core.common.businessentities.Quota;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+public abstract class BackendQuotaLimitResource<T extends BaseResource> 
extends AbstractBackendSubResource<T, Quota> implements
+        QuotaLimitResource<T> {
+    private static final String[] SUB_COLLECTIONS = {};
+    private final Guid parentId;
+
+    protected BackendQuotaLimitResource(String id,
+            Guid parentId,
+            Class<T> modelType) {
+        super(id, modelType, Quota.class, SUB_COLLECTIONS);
+        this.parentId = parentId;
+    }
+
+    @Override
+    public T get() {
+        return performGet(VdcQueryType.GetQuotaByQuotaId, new 
IdQueryParameters(parentId));
+    }
+
+    @Override
+    protected T map(Quota entity, T template) {
+        return super.map(entity, createQuotaLimit());
+    }
+
+    @Override
+    protected T doPopulate(T model, Quota entity) {
+        return model;
+    }
+
+    protected abstract T createQuotaLimit();
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitsResource.java
new file mode 100644
index 0000000..c06145b
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaLimitsResource.java
@@ -0,0 +1,71 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import javax.ws.rs.core.Response;
+
+import org.ovirt.engine.api.model.BaseResource;
+import org.ovirt.engine.api.model.BaseResources;
+import org.ovirt.engine.api.resource.QuotaLimitsResource;
+import 
org.ovirt.engine.api.restapi.resource.AbstractBackendSubResource.ParametersProvider;
+import org.ovirt.engine.core.common.action.QuotaCRUDParameters;
+import org.ovirt.engine.core.common.action.VdcActionParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.Quota;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+public abstract class BackendQuotaLimitsResource<M extends BaseResources, N 
extends BaseResource> extends AbstractBackendCollectionResource<N, Quota> 
implements QuotaLimitsResource<M, N> {
+
+    protected final Guid quotaId;
+    private static final String[] SUB_COLLECTIONS = {};
+
+    protected BackendQuotaLimitsResource(Guid quotaId,
+            Class<N> baseResourcesClass) {
+        super(baseResourcesClass, Quota.class, SUB_COLLECTIONS);
+        this.quotaId = quotaId;
+    }
+
+    protected abstract void updateEntityForRemove(Quota entity, Guid id);
+
+    protected abstract void updateIncomingId(N incoming, Quota entity);
+
+    protected ParametersProvider<N, Quota> getAddParametersProvider() {
+        return new ParametersProvider<N, Quota>() {
+            @Override
+            public VdcActionParametersBase getParameters(N model, Quota 
entity) {
+                return new QuotaCRUDParameters(map(model, entity));
+            }
+        };
+    }
+
+    @Override
+    protected Response performRemove(String id) {
+        Quota entity = getQuota();
+        updateEntityForRemove(entity, asGuid(id));
+        return performAction(VdcActionType.UpdateQuota,
+                new QuotaCRUDParameters(entity));
+    }
+
+    @Override
+    public N add(N incoming) {
+        Quota entity = getQuota();
+        performAction(VdcActionType.UpdateQuota, 
getAddParametersProvider().getParameters(incoming, entity));
+        entity = getQuota();
+        updateIncomingId(incoming, entity);
+        N model = map(entity, incoming);
+        return addLinks(doPopulate(model, entity));
+    }
+
+    @Override
+    protected N doPopulate(N model, Quota entity) {
+        return model;
+    }
+
+    protected Quota getQuota() {
+        return getEntity(Quota.class,
+                VdcQueryType.GetQuotaByQuotaId,
+                new IdQueryParameters(quotaId),
+                quotaId.toString());
+    }
+
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaResource.java
index 8fa7f7f..20768fe 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotaResource.java
@@ -1,35 +1,43 @@
 package org.ovirt.engine.api.restapi.resource;
 
+import static 
org.ovirt.engine.api.restapi.resource.BackendQuotasResource.SUB_COLLECTIONS;
+
 import org.ovirt.engine.api.model.Quota;
+import org.ovirt.engine.api.resource.ClusterQuotaLimitsResource;
 import org.ovirt.engine.api.resource.QuotaResource;
+import org.ovirt.engine.api.resource.StorageQuotaLimitsResource;
 import org.ovirt.engine.core.common.action.QuotaCRUDParameters;
 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.compat.Guid;
 
 public class BackendQuotaResource extends AbstractBackendSubResource<Quota, 
org.ovirt.engine.core.common.businessentities.Quota> implements QuotaResource {
 
     protected BackendQuotasResource parent;
 
-   public BackendQuotasResource getParent() {
+    public BackendQuotasResource getParent() {
         return parent;
     }
 
     public BackendQuotaResource(String id, BackendQuotasResource parent) {
-        super(id, Quota.class, 
org.ovirt.engine.core.common.businessentities.Quota.class);
+        super(id,
+                Quota.class,
+                org.ovirt.engine.core.common.businessentities.Quota.class,
+                SUB_COLLECTIONS);
         this.parent = parent;
     }
 
     @Override
     public Quota get() {
-        IdQueryParameters params = new IdQueryParameters(guid);
-        Quota quota = performGet(VdcQueryType.GetQuotaByQuotaId, params);
-        return quota;
+        return addLinks(performGet(VdcQueryType.GetQuotaByQuotaId, new 
IdQueryParameters(guid)));
     }
 
     protected class UpdateParametersProvider implements 
ParametersProvider<Quota, org.ovirt.engine.core.common.businessentities.Quota> {
         @Override
-        public VdcActionParametersBase getParameters(Quota incoming, 
org.ovirt.engine.core.common.businessentities.Quota entity) {
+        public VdcActionParametersBase getParameters(Quota incoming,
+                org.ovirt.engine.core.common.businessentities.Quota entity) {
             return new QuotaCRUDParameters(map(incoming, entity));
         }
     }
@@ -38,4 +46,22 @@
     protected Quota doPopulate(Quota model, 
org.ovirt.engine.core.common.businessentities.Quota entity) {
         return model;
     }
+
+    @Override
+    public Quota update(Quota incoming) {
+        return performUpdate(incoming,
+                new QueryIdResolver<Guid>(VdcQueryType.GetQuotaByQuotaId, 
IdQueryParameters.class),
+                VdcActionType.UpdateQuota,
+                new UpdateParametersProvider());
+    }
+
+    @Override
+    public StorageQuotaLimitsResource getStorageQuotaLimitsResource() {
+        return inject(new BackendStorageQuotaLimitsResource(guid));
+    }
+
+    @Override
+    public ClusterQuotaLimitsResource getClusterQuotaLimitsResource() {
+        return inject(new BackendClusterQuotaLimitsResource(guid));
+    }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotasResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotasResource.java
index 4c2ad03..ec7a366 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotasResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQuotasResource.java
@@ -9,28 +9,48 @@
 import org.ovirt.engine.api.model.Quotas;
 import org.ovirt.engine.api.resource.QuotaResource;
 import org.ovirt.engine.api.resource.QuotasResource;
+import org.ovirt.engine.api.restapi.utils.GuidUtils;
+import org.ovirt.engine.core.common.action.QuotaCRUDParameters;
+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.compat.Guid;
 
 public class BackendQuotasResource extends 
AbstractBackendCollectionResource<Quota, 
org.ovirt.engine.core.common.businessentities.Quota> implements QuotasResource {
 
+    protected static final String[] SUB_COLLECTIONS = { "storagequotalimits", 
"clusterquotalimits" };
+
     protected Guid dataCenterId;
 
     protected BackendQuotasResource(String datacenterId) {
-        super(Quota.class, 
org.ovirt.engine.core.common.businessentities.Quota.class);
+        super(Quota.class, 
org.ovirt.engine.core.common.businessentities.Quota.class, SUB_COLLECTIONS);
         this.dataCenterId = asGuid(datacenterId);
     }
 
     @Override
     public Quotas list() {
-        IdQueryParameters params = new IdQueryParameters(dataCenterId);
-        return 
mapCollection(getBackendCollection(VdcQueryType.GetQuotaByStoragePoolId, 
params));
+        if (isFiltered()) {
+            return null;
+        } else {
+            IdQueryParameters params = new IdQueryParameters(dataCenterId);
+            return 
mapCollection(getBackendCollection(VdcQueryType.GetQuotaByStoragePoolId, 
params));
+        }
     }
 
     @Override
     protected Response performRemove(String id) {
-        throw new UnsupportedOperationException();
+        QuotaCRUDParameters prms = new QuotaCRUDParameters();
+        prms.setQuotaId(GuidUtils.asGuid(id));
+        return performAction(VdcActionType.RemoveQuota, prms);
+    }
+
+    @Override
+    public Response add(Quota quota) {
+        org.ovirt.engine.core.common.businessentities.Quota entity = 
map(quota);
+        entity.setStoragePoolId(dataCenterId);
+        return performCreate(VdcActionType.AddQuota,
+                new QuotaCRUDParameters(entity),
+                new QueryIdResolver<Guid>(VdcQueryType.GetQuotaByQuotaId, 
IdQueryParameters.class));
     }
 
     @Override
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitResource.java
new file mode 100644
index 0000000..08a6d4a
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitResource.java
@@ -0,0 +1,20 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.StorageQuotaLimit;
+import org.ovirt.engine.api.resource.StorageQuotaLimitResource;
+import org.ovirt.engine.core.compat.Guid;
+
+public class BackendStorageQuotaLimitResource extends 
BackendQuotaLimitResource<StorageQuotaLimit> implements
+        StorageQuotaLimitResource {
+
+    protected BackendStorageQuotaLimitResource(String id, Guid parentId) {
+        super(id, parentId, StorageQuotaLimit.class);
+    }
+
+    @Override
+    protected StorageQuotaLimit createQuotaLimit() {
+        StorageQuotaLimit limit = new StorageQuotaLimit();
+        limit.setId(id);
+        return limit;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitsResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitsResource.java
new file mode 100644
index 0000000..474fae9
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendStorageQuotaLimitsResource.java
@@ -0,0 +1,80 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.jboss.resteasy.spi.NotFoundException;
+import org.ovirt.engine.api.model.StorageQuotaLimit;
+import org.ovirt.engine.api.model.StorageQuotaLimits;
+import org.ovirt.engine.api.resource.StorageQuotaLimitResource;
+import org.ovirt.engine.api.resource.StorageQuotaLimitsResource;
+import org.ovirt.engine.core.common.businessentities.Quota;
+import org.ovirt.engine.core.common.businessentities.QuotaStorage;
+import org.ovirt.engine.core.compat.Guid;
+
+public class BackendStorageQuotaLimitsResource extends 
BackendQuotaLimitsResource<StorageQuotaLimits, StorageQuotaLimit> implements 
StorageQuotaLimitsResource {
+
+    protected BackendStorageQuotaLimitsResource(Guid quotaId) {
+        super(quotaId, StorageQuotaLimit.class);
+    }
+
+    @Override
+    public StorageQuotaLimits list() {
+        Quota quota = getQuota();
+        StorageQuotaLimits limits = new StorageQuotaLimits();
+        if (quota.getGlobalQuotaStorage() != null) {
+            addLimit(quota.getGlobalQuotaStorage(), quotaId.toString(), 
limits, quota);
+        } else if (quota.getQuotaStorages() != null) {
+            for (QuotaStorage quotaStorage : quota.getQuotaStorages()) {
+                addLimit(quotaStorage, quotaStorage.getStorageId().toString(), 
limits, quota);
+            }
+        }
+        return limits;
+    }
+
+    private void addLimit(QuotaStorage quotaStorage, String id, 
StorageQuotaLimits limits, Quota quota) {
+        StorageQuotaLimit limit = new StorageQuotaLimit();
+        limit.setId(id);
+        limits.getStorageQuotaLimits().add(addLinks(map(quota, limit)));
+    }
+
+    @Override
+    @SingleEntityResource
+    public StorageQuotaLimitResource getSubResource(String id) {
+        return inject(new BackendStorageQuotaLimitResource(id, quotaId));
+    }
+
+    @Override
+    protected void updateEntityForRemove(Quota entity, Guid id) {
+        // since we're mocking remove using update, we'll throw 404 if the 
object isn't found
+        boolean throw404 = false;
+        // global storage (has same id as quota)
+        if (entity.getId().equals(id)) {
+            if (entity.getGlobalQuotaStorage() == null) {
+                throw404 = true;
+            } else {
+                entity.setGlobalQuotaStorage(null);
+            }
+            // specific storage (has same id as storage domain)
+        } else {
+            if (entity.getQuotaStorages() != null) {
+                for (int i = 0; i < entity.getQuotaStorages().size(); i++) {
+                    if 
(entity.getQuotaStorages().get(i).getStorageId().equals(id)) {
+                        entity.getQuotaStorages().remove(i);
+                        return;
+                    }
+                }
+                throw404 = true;
+            }
+        }
+        if (throw404) {
+            throw new NotFoundException("");
+        }
+    }
+
+    @Override
+    protected void updateIncomingId(StorageQuotaLimit incoming, Quota entity) {
+        if (incoming.isSetStorageDomain() && 
incoming.getStorageDomain().isSetId()) {
+            incoming.setId(incoming.getStorageDomain().getId());
+        } else {
+            incoming.setId(entity.getId().toString());
+        }
+    }
+}
diff --git 
a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QuotaMapper.java
 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QuotaMapper.java
index 0d077d5..ce29bdc 100644
--- 
a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QuotaMapper.java
+++ 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QuotaMapper.java
@@ -1,8 +1,15 @@
 package org.ovirt.engine.api.restapi.types;
 
+import org.ovirt.engine.api.model.Cluster;
+import org.ovirt.engine.api.model.ClusterQuotaLimit;
 import org.ovirt.engine.api.model.DataCenter;
 import org.ovirt.engine.api.model.Quota;
+import org.ovirt.engine.api.model.StorageDomain;
+import org.ovirt.engine.api.model.StorageQuotaLimit;
 import org.ovirt.engine.api.restapi.utils.GuidUtils;
+import org.ovirt.engine.core.common.businessentities.QuotaStorage;
+import org.ovirt.engine.core.common.businessentities.QuotaVdsGroup;
+import org.ovirt.engine.core.compat.Guid;
 
 
 public class QuotaMapper {
@@ -21,6 +28,18 @@
         }
         if (model.isSetDataCenter()) {
             
entity.setStoragePoolId(GuidUtils.asGuid(model.getDataCenter().getId()));
+        }
+        if (model.isSetClusterHardLimitPct()) {
+            entity.setGraceVdsGroupPercentage(model.getClusterHardLimitPct());
+        }
+        if (model.isSetStorageHardLimitPct()) {
+            entity.setGraceStoragePercentage(model.getStorageHardLimitPct());
+        }
+        if (model.isSetClusterSoftLimitPct()) {
+            
entity.setThresholdVdsGroupPercentage(model.getClusterSoftLimitPct());
+        }
+        if (model.isSetStorageSoftLimitPct()) {
+            
entity.setThresholdStoragePercentage(model.getStorageSoftLimitPct());
         }
         return entity;
     }
@@ -43,6 +62,152 @@
             }
             ret.getDataCenter().setId(template.getStoragePoolId().toString());
         }
+        ret.setClusterHardLimitPct(template.getGraceVdsGroupPercentage());
+        ret.setStorageHardLimitPct(template.getGraceStoragePercentage());
+        ret.setClusterSoftLimitPct(template.getThresholdVdsGroupPercentage());
+        ret.setStorageSoftLimitPct(template.getThresholdStoragePercentage());
         return ret;
     }
+
+    @Mapping(from = org.ovirt.engine.core.common.businessentities.Quota.class, 
to = StorageQuotaLimit.class)
+    public static StorageQuotaLimit 
map(org.ovirt.engine.core.common.businessentities.Quota entity,
+            StorageQuotaLimit template) {
+        if (template == null) {
+            assert (false) : "StorageQuotaLimit cannot be null";
+            return null;
+        }
+        Guid guid = GuidUtils.asGuid(template.getId());
+        // global
+        if (guid.equals(entity.getId())) {
+            map(template, entity.getGlobalQuotaStorage(), null, 
entity.getStoragePoolId().toString(), entity.getId()
+                    .toString());
+        } else { // specific
+            if (entity.getQuotaStorages() != null) {
+                for (QuotaStorage quotaStorage : entity.getQuotaStorages()) {
+                    if (quotaStorage.getStorageId() != null && 
quotaStorage.getStorageId().equals(guid)) {
+                        map(template, quotaStorage, 
quotaStorage.getStorageId().toString(), entity.getStoragePoolId()
+                                .toString(), entity.getId().toString());
+                    }
+                }
+            }
+        }
+        return template;
+    }
+
+    private static void map(StorageQuotaLimit template,
+            QuotaStorage quotaStorage,
+            String storageDomainId,
+            String dataCenterId,
+            String quotaId) {
+        template.setQuota(new Quota());
+        template.getQuota().setId(quotaId);
+        template.getQuota().setDataCenter(new DataCenter());
+        template.getQuota().getDataCenter().setId(dataCenterId);
+        if (storageDomainId != null) {
+            template.setStorageDomain(new StorageDomain());
+            template.getStorageDomain().setId(storageDomainId);
+        }
+        if (quotaStorage.getStorageSizeGB() != null) {
+            template.setLimit(quotaStorage.getStorageSizeGB());
+        }
+        if (quotaStorage.getStorageSizeGBUsage() != null) {
+            template.setUsage(quotaStorage.getStorageSizeGBUsage());
+        }
+    }
+
+    @Mapping(from = StorageQuotaLimit.class, to = 
org.ovirt.engine.core.common.businessentities.Quota.class)
+    public static org.ovirt.engine.core.common.businessentities.Quota 
map(StorageQuotaLimit model,
+            org.ovirt.engine.core.common.businessentities.Quota template) {
+        org.ovirt.engine.core.common.businessentities.Quota entity =
+                template != null ? template : new 
org.ovirt.engine.core.common.businessentities.Quota();
+        QuotaStorage quotaStorage = new QuotaStorage();
+        if (model.isSetLimit()) {
+            quotaStorage.setStorageSizeGB(model.getLimit());
+        }
+        // specific SD
+        if(model.isSetStorageDomain() && model.getStorageDomain().isSetId()) {
+            
quotaStorage.setStorageId(GuidUtils.asGuid(model.getStorageDomain().getId()));
+            entity.getQuotaStorages().add(quotaStorage);
+        } else { // global
+            entity.setGlobalQuotaStorage(quotaStorage);
+        }
+        return entity;
+    }
+
+    @Mapping(from = org.ovirt.engine.core.common.businessentities.Quota.class, 
to = ClusterQuotaLimit.class)
+    public static ClusterQuotaLimit 
map(org.ovirt.engine.core.common.businessentities.Quota entity,
+            ClusterQuotaLimit template) {
+        if (template == null) {
+            assert (false) : "ClusterQuotaLimit cannot be null";
+            return null;
+        }
+        Guid guid = GuidUtils.asGuid(template.getId());
+        // global
+        if (guid.equals(entity.getId())) {
+            map(template, entity.getGlobalQuotaVdsGroup(), null, 
entity.getStoragePoolId().toString(), entity.getId()
+                    .toString());
+        } else { // specific
+            if (entity.getQuotaVdsGroups() != null) {
+                for (QuotaVdsGroup quotaCluster : entity.getQuotaVdsGroups()) {
+                    if (quotaCluster.getVdsGroupId() != null && 
quotaCluster.getVdsGroupId().equals(guid)) {
+                        map(template, quotaCluster, 
quotaCluster.getVdsGroupId().toString(), entity.getStoragePoolId()
+                                .toString(), entity.getId().toString());
+                    }
+                }
+            }
+        }
+        return template;
+    }
+
+    private static void map(ClusterQuotaLimit template,
+            QuotaVdsGroup quotaCluster,
+            String clusterId,
+            String dataCenterId,
+            String quotaId) {
+        template.setQuota(new Quota());
+        template.getQuota().setId(quotaId);
+        template.getQuota().setDataCenter(new DataCenter());
+        template.getQuota().getDataCenter().setId(dataCenterId);
+        if (clusterId != null) {
+            template.setCluster(new Cluster());
+            template.getCluster().setId(clusterId);
+        }
+        if (quotaCluster.getMemSizeMB() != null) {
+            // show GB instead of MB (ignore -1)
+            double value = quotaCluster.getMemSizeMB() == -1 ? 
quotaCluster.getMemSizeMB()
+                    : quotaCluster.getMemSizeMB() / 1024.0;
+            template.setMemoryLimit(value);
+        }
+        if (quotaCluster.getMemSizeMBUsage() != null) {
+            template.setMemoryUsage(quotaCluster.getMemSizeMBUsage() / 1024.0);
+        }
+        if (quotaCluster.getVirtualCpu() != null) {
+            template.setVcpuLimit(quotaCluster.getVirtualCpu());
+        }
+        if (quotaCluster.getVirtualCpuUsage() != null) {
+            template.setVcpuUsage(quotaCluster.getVirtualCpuUsage());
+        }
+    }
+
+    @Mapping(from = ClusterQuotaLimit.class, to = 
org.ovirt.engine.core.common.businessentities.Quota.class)
+    public static org.ovirt.engine.core.common.businessentities.Quota 
map(ClusterQuotaLimit model,
+            org.ovirt.engine.core.common.businessentities.Quota template) {
+        org.ovirt.engine.core.common.businessentities.Quota entity =
+                template != null ? template : new 
org.ovirt.engine.core.common.businessentities.Quota();
+        QuotaVdsGroup quotaCluster = new QuotaVdsGroup();
+        if (model.isSetVcpuLimit()) {
+            quotaCluster.setVirtualCpu(model.getVcpuLimit());
+        }
+        if (model.isSetMemoryLimit() && model.getMemoryLimit() != -1) {
+            quotaCluster.setMemSizeMB((long) (model.getMemoryLimit() * 1024));
+        }
+        // specific cluster
+        if (model.isSetCluster() && model.getCluster().isSetId()) {
+            
quotaCluster.setVdsGroupId(GuidUtils.asGuid(model.getCluster().getId()));
+            entity.getQuotaVdsGroups().add(quotaCluster);
+        } else { // global
+            entity.setGlobalQuotaVdsGroup(quotaCluster);
+        }
+        return entity;
+    }
 }


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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifaead35839c2c5f89f1551e67e58a58aa253cab5
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Gilad Chaplik <[email protected]>
_______________________________________________
Engine-patches mailing list
[email protected]
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to