Gilad Chaplik has uploaded a new change for review.

Change subject: restapi: add QoS RESTful interface for storage QoS
......................................................................

restapi: add QoS RESTful interface for storage QoS

- POST: /ovirt-engine/api/datacenters/{datacenter:id}/qoss; body: qos; 
response: qos
<qos type="storage">
  <name>test_qos</name>
  <description>aaaaa</description>
  <max_throughput>1</max_throughput>
  <max_read_throughput>1</max_read_throughput>
  <max_write_throughput>1</max_write_throughput>
  <max_iops>1</max_iops>
  <max_read_iops>1</max_read_iops>
  <max_write_iops>1</max_write_iops>
</qos>
- GET: /ovirt-engine/api/datacenters/{datacenter:id}/qoss; response: qoss
- DELETE: /ovirt-engine/api/datacenters/{datacenter:id}/qoss/{qos:id};
- GET: /ovirt-engine/api/datacenters/{datacenter:id}/qoss/{qos:id}; response: 
qos
<qos type="storage" 
href="/ovirt-engine/api/datacenters/00000002-0002-0002-0002-000000000321/qoss/a66577ff-d5f1-40f7-aebb-0b350ad8bb8c"
 id="a66577ff-d5f1-40f7-aebb-0b350ad8bb8c">
  <name>test_qos</name>
  <description>aaaaa</description>
  <data_center 
href="/ovirt-engine/api/datacenters/00000002-0002-0002-0002-000000000321" 
id="00000002-0002-0002-0002-000000000321"/>
  <max_throughput>1</max_throughput>
  <max_read_throughput>1</max_read_throughput>
  <max_write_throughput>1</max_write_throughput>
  <max_iops>1</max_iops>
  <max_read_iops>1</max_read_iops>
  <max_write_iops>1</max_write_iops>
</qos>
- PUT: /ovirt-engine/api/datacenters/{datacenter:id}/qoss/{qos:id}; body: qos; 
response: qos

For more information see: http://www.ovirt.org/Features/aggregate_QoS,
http://www.ovirt.org/Features/blkio-support#RESTful_API

Change-Id: I1a9af59277b50554531522802f19046c0051d82f
Signed-off-by: Gilad Chaplik <[email protected]>
---
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/QosType.java
M 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/DataCenterResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QoSsResource.java
A 
backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QosResource.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/resource/BackendCapabilitiesResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterClustersResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterResource.java
M 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCentersResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQosResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQossResource.java
A 
backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/QosValidator.java
A 
backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QosMapper.java
A 
backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/QosMapperTest.java
17 files changed, 581 insertions(+), 31 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/06/31806/1

diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/QosType.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/QosType.java
new file mode 100644
index 0000000..25f5389
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/model/QosType.java
@@ -0,0 +1,17 @@
+package org.ovirt.engine.api.model;
+
+public enum QosType {
+    STORAGE;
+
+    public String value() {
+        return name().toLowerCase();
+    }
+
+    public static QosType fromValue(String value) {
+        try {
+            return valueOf(value.toUpperCase());
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/DataCenterResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/DataCenterResource.java
index 45275da..b348996 100644
--- 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/DataCenterResource.java
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/DataCenterResource.java
@@ -41,4 +41,7 @@
 
     @Path("iscsibonds")
     public IscsiBondsResource getIscsiBondsResource();
+
+    @Path("qoss")
+    public QoSsResource getQossResource();
 }
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QoSsResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QoSsResource.java
new file mode 100644
index 0000000..b1035fb
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QoSsResource.java
@@ -0,0 +1,32 @@
+package org.ovirt.engine.api.resource;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+import org.ovirt.engine.api.model.QoS;
+import org.ovirt.engine.api.model.QoSs;
+
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface QoSsResource {
+
+    @GET
+    public QoSs list();
+
+    @POST
+    @Consumes({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+    public Response add(QoS qos);
+
+    @DELETE
+    @Path("{id}")
+    public Response remove(@PathParam("id") String id);
+
+    @Path("{id}")
+    public QosResource getQosSubResource(@PathParam("id") String id);
+
+}
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QosResource.java
 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QosResource.java
new file mode 100644
index 0000000..91279c1
--- /dev/null
+++ 
b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/QosResource.java
@@ -0,0 +1,10 @@
+package org.ovirt.engine.api.resource;
+
+import javax.ws.rs.Produces;
+
+import org.ovirt.engine.api.model.QoS;
+
+@Produces({ ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, 
ApiMediaType.APPLICATION_X_YAML })
+public interface QosResource extends UpdatableResource<QoS> {
+
+}
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 9995beb..e796325 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
@@ -68,6 +68,7 @@
 import org.ovirt.engine.api.model.Permission;
 import org.ovirt.engine.api.model.Permit;
 import org.ovirt.engine.api.model.Quota;
+import org.ovirt.engine.api.model.QoS;
 import org.ovirt.engine.api.model.ReportedDevice;
 import org.ovirt.engine.api.model.Request;
 import org.ovirt.engine.api.model.Role;
@@ -148,6 +149,8 @@
 import org.ovirt.engine.api.resource.PermissionResource;
 import org.ovirt.engine.api.resource.PermitResource;
 import org.ovirt.engine.api.resource.PermitsResource;
+import org.ovirt.engine.api.resource.QosResource;
+import org.ovirt.engine.api.resource.QoSsResource;
 import org.ovirt.engine.api.resource.QuotaResource;
 import org.ovirt.engine.api.resource.QuotasResource;
 import org.ovirt.engine.api.resource.ReadOnlyDeviceResource;
@@ -454,6 +457,10 @@
 
         map = new ParentToCollectionMap(IscsiBondResource.class, 
IscsiBondsResource.class, DataCenter.class);
         TYPES.put(IscsiBond.class, map);
+
+        map = new ParentToCollectionMap(QosResource.class, QoSsResource.class, 
DataCenter.class);
+        TYPES.put(QoS.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 5a1f6cd..06ef8c9 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
@@ -654,6 +654,7 @@
           <xs:element ref="selinux_modes" minOccurs="0" />
           <xs:element ref="rng_sources" minOccurs="0" />
           <xs:element ref="scheduling_policy_unit_types" minOccurs="0" />
+          <xs:element ref="qos_types" minOccurs="0" />
         </xs:sequence>
       </xs:extension>
     </xs:complexContent>
@@ -4551,6 +4552,31 @@
     </xs:complexContent>
   </xs:complexType>
 
+  <xs:element name="qos" type="QoS" />
+
+  <xs:complexType name="QoS">
+    <xs:complexContent>
+      <xs:extension base="BaseResource">
+        <xs:sequence>
+          <xs:element ref="data_center" minOccurs="0" maxOccurs="1" />
+          <xs:element name="max_throughput" type="xs:int"
+            minOccurs="0" maxOccurs="1" />
+          <xs:element name="max_read_throughput" type="xs:int" minOccurs="0"
+            maxOccurs="1" />
+          <xs:element name="max_write_throughput" type="xs:int"
+            minOccurs="0" maxOccurs="1" />
+          <xs:element name="max_iops" type="xs:int"
+            minOccurs="0" maxOccurs="1" />
+          <xs:element name="max_read_iops" type="xs:int"
+            minOccurs="0" maxOccurs="1" />
+          <xs:element name="max_write_iops" type="xs:int"
+            minOccurs="0" maxOccurs="1" />
+        </xs:sequence>
+        <xs:attribute name="type" type="xs:string"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
   <xs:complexType name="NumaNodes">
     <xs:complexContent>
       <xs:extension base="BaseResources">
@@ -4589,6 +4615,24 @@
               </xs:appinfo>
             </xs:annotation>
           </xs:element>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <xs:element name="qoss" type="QoSs" />
+
+  <xs:complexType name="QoSs">
+    <xs:complexContent>
+      <xs:extension base="BaseResources">
+        <xs:sequence>
+          <xs:annotation>
+            <xs:appinfo>
+              <jaxb:property name="QoSs" />
+            </xs:appinfo>
+          </xs:annotation>
+          <xs:element ref="qos" minOccurs="0"
+            maxOccurs="unbounded" />
         </xs:sequence>
       </xs:extension>
     </xs:complexContent>
@@ -4663,4 +4707,18 @@
   <xs:element name="iscsi_bond" type="IscsiBond"/>
 
   <xs:element name="iscsi_bonds" type="IscsiBonds"/>
+
+  <xs:element name="qos_types" type="QosTypes"/>
+
+  <xs:complexType name="QosTypes">
+    <xs:sequence>
+      <xs:element name="qos_type" type="xs:string" minOccurs="0" 
maxOccurs="unbounded">
+        <xs:annotation>
+          <xs:appinfo>
+            <jaxb:property name="QosTypes"/>
+          </xs:appinfo>
+        </xs:annotation>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
 </xs:schema>
diff --git 
a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml
 
b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml
index 329e65b..c3f9844 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
@@ -1362,6 +1362,72 @@
       async: {context: matrix, type: 'xs:boolean', value: true|false, 
required: false}
     headers:
       Correlation-Id: {value: 'any string', required: false}
+- name: /datacenters/{datacenter:id}/qoss|rel=get
+  description: get QoSs for the datacenter in the system
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams:
+      max: {context: matrix, type: 'xs:int', value: 'max results', required: 
false}
+    headers: {}
+- name: /datacenters/{datacenter:id}/qoss/{qos:id}|rel=get
+  description: get the specified QoS in the datacenter
+  request:
+    body:
+      parameterType: null
+      signatures: []
+    urlparams: {}
+    headers: {}
+- name: /datacenters/{datacenter:id}/qoss/{qos:id}|rel=delete
+  description: delete the specified QoS in the datacenter
+  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: /datacenters/{datacenter:id}/qoss/{qos:id}|rel=update
+  description: update the specified QoS in the datacenter
+  request:
+    body:
+      parameterType: QoS
+      signatures:
+      - mandatoryArguments: {}
+        optionalArguments: {qos.name: 'xs:string',
+                           qos.description: 'xs:string',
+                           qos.max_throughput: 'xs:int',
+                           qos.max_read_throughput: 'xs:int',
+                           qos.max_write_throughput: 'xs:int',
+                           qos.max_iops: 'xs:int',
+                           qos.max_read_iops: 'xs:int',
+                           qos.max_write_iops: 'xs:int'}
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Correlation-Id: {value: 'any string', required: false}
+- name: /datacenters/{datacenter:id}/qoss|rel=add
+  description: add a new QoS to the datacenter
+  request:
+    body:
+      parameterType: QoS
+      signatures:
+      - mandatoryArguments: {qos.name: 'xs:string', qos.type: 'xs:string'}
+        optionalArguments: {qos.description: 'xs:string',
+                           qos.max_throughput: 'xs:int',
+                           qos.max_read_throughput: 'xs:int',
+                           qos.max_write_throughput: 'xs:int',
+                           qos.max_iops: 'xs:int',
+                           qos.max_read_iops: 'xs:int',
+                           qos.max_write_iops: 'xs:int'}
+        description: add a new QoS to the datacenter
+    urlparams: {}
+    headers:
+      Content-Type: {value: application/xml|json, required: true}
+      Expect: {value: 201-created, required: false}
+      Correlation-Id: {value: 'any string', required: false}
 - name: /storagedomains|rel=get
   description: get storage domains in the system
   request:
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java
index 6bf2425..4950867 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendCapabilitiesResource.java
@@ -72,6 +72,7 @@
 import org.ovirt.engine.api.model.PowerManagementStates;
 import org.ovirt.engine.api.model.PowerManagementStatus;
 import org.ovirt.engine.api.model.PowerManagers;
+import org.ovirt.engine.api.model.QosTypes;
 import org.ovirt.engine.api.model.ReportedDeviceType;
 import org.ovirt.engine.api.model.ReportedDeviceTypes;
 import org.ovirt.engine.api.model.SELinuxMode;
@@ -142,7 +143,7 @@
 
 public class BackendCapabilitiesResource extends BackendResource implements 
CapabilitiesResource {
 
-    private FeaturesHelper featuresHelper = new FeaturesHelper();
+    private final FeaturesHelper featuresHelper = new FeaturesHelper();
 
     public static final Version VERSION_3_0 = new Version() {
         {
@@ -184,14 +185,14 @@
 
     @Override
     public Capabilities list() {
-    Capabilities caps = new Capabilities();
+        Capabilities caps = new Capabilities();
         for (Version v : getSupportedClusterLevels()) {
             caps.getVersions().add(generateVersionCaps(v));
         }
 
         caps.setPermits(getPermits());
         caps.setSchedulingPolicies(getSchedulingPolicies());
-        return  caps;
+        return caps;
     }
 
     public VersionCaps generateVersionCaps(Version v) {
@@ -234,10 +235,11 @@
         addOsTypes(version);
         addNfsVersions(version, NfsVersion.values());
         addKdumpStates(version, KdumpStatus.values());
+        addSupportedQosTypes(version);
 
         addGlusterTypesAndStates(version);
 
-        //Add States. User can't update States, but he still needs to know 
which exist.
+        // Add States. User can't update States, but he still needs to know 
which exist.
         addCreationStates(version, CreationStatus.values());
         addStorageDomaintStates(version, StorageDomainStatus.values());
         addPowerManagementStateses(version, PowerManagementStatus.values());
@@ -280,7 +282,7 @@
             version.setCurrent(false);
         }
 
-        LinkHelper.<VersionCaps>addLinks(getUriInfo(), version);
+        LinkHelper.<VersionCaps> addLinks(getUriInfo(), version);
 
         return version;
     }
@@ -439,13 +441,13 @@
             addGlusterHookContentTypes(version, HookContentType.values());
             addStages(version, HookStage.values());
             addGlusterHookStates(version, HookStatus.values());
-         }
+        }
     }
 
     private Version getCurrentVersion() {
         if (currentVersion == null) {
             currentVersion = 
VersionHelper.parseVersion(getConfigurationValueDefault(String.class,
-                                                                              
ConfigurationValues.VdcVersion));
+                    ConfigurationValues.VdcVersion));
         }
         return currentVersion;
     }
@@ -607,8 +609,14 @@
 
     private List<CustomProperty> getVmHooksEnvs(Version version) {
         List<CustomProperty> ret = new ArrayList<CustomProperty>();
-        
ret.addAll(CustomPropertiesParser.parse(getConfigurationValue(String.class, 
ConfigurationValues.PredefinedVMProperties, version), true));
-        
ret.addAll(CustomPropertiesParser.parse(getConfigurationValue(String.class, 
ConfigurationValues.UserDefinedVMProperties, version), true));
+        
ret.addAll(CustomPropertiesParser.parse(getConfigurationValue(String.class,
+                ConfigurationValues.PredefinedVMProperties,
+                version),
+                true));
+        
ret.addAll(CustomPropertiesParser.parse(getConfigurationValue(String.class,
+                ConfigurationValues.UserDefinedVMProperties,
+                version),
+                true));
         return ret;
     }
 
@@ -620,8 +628,8 @@
 
     public List<Version> getSupportedClusterLevels() {
         List<Version> versions = new ArrayList<Version>();
-        for (org.ovirt.engine.core.compat.Version v :
-                    
(Set<org.ovirt.engine.core.compat.Version>)getConfigurationValueDefault(Set.class,
 ConfigurationValues.SupportedClusterLevels)){
+        for (org.ovirt.engine.core.compat.Version v : 
(Set<org.ovirt.engine.core.compat.Version>) 
getConfigurationValueDefault(Set.class,
+                ConfigurationValues.SupportedClusterLevels)) {
             Version version = new Version();
             version.setMajor(v.getMajor());
             version.setMinor(v.getMinor());
@@ -755,49 +763,49 @@
     // Gluster related types and states
     private void addGlusterVolumeTypes(VersionCaps version, 
GlusterVolumeType[] types) {
         version.setGlusterVolumeTypes(new GlusterVolumeTypes());
-        for(GlusterVolumeType type : types) {
+        for (GlusterVolumeType type : types) {
             
version.getGlusterVolumeTypes().getGlusterVolumeTypes().add(type.value());
         }
     }
 
     private void addTransportTypes(VersionCaps version, TransportType[] types) 
{
         version.setTransportTypes(new TransportTypes());
-        for(TransportType type : types) {
+        for (TransportType type : types) {
             version.getTransportTypes().getTransportTypes().add(type.value());
         }
     }
 
     private void addGlusterVolumeStates(VersionCaps version, GlusterState[] 
states) {
         version.setGlusterVolumeStates(new GlusterStates());
-        for(GlusterState type : states) {
+        for (GlusterState type : states) {
             
version.getGlusterVolumeStates().getGlusterStates().add(type.value());
         }
     }
 
     private void addGlusterBrickStates(VersionCaps version, GlusterState[] 
states) {
         version.setBrickStates(new GlusterStates());
-        for(GlusterState type : states) {
+        for (GlusterState type : states) {
             version.getBrickStates().getGlusterStates().add(type.value());
         }
     }
 
     private void addGlusterHookContentTypes(VersionCaps version, 
HookContentType[] values) {
         version.setContentTypes(new ContentTypes());
-        for (HookContentType type: values) {
+        for (HookContentType type : values) {
             version.getContentTypes().getContentTypes().add(type.value());
         }
     }
 
     private void addGlusterHookStates(VersionCaps version, HookStatus[] 
values) {
         version.setHookStates(new HookStates());
-        for (HookStatus status: values) {
+        for (HookStatus status : values) {
             version.getHookStates().getHookStates().add(status.value());
         }
     }
 
     private void addStages(VersionCaps version, HookStage[] values) {
         version.setStages(new Stages());
-        for (HookStage stage: values) {
+        for (HookStage stage : values) {
             version.getStages().getStages().add(stage.value());
         }
     }
@@ -813,7 +821,7 @@
 
     private void addStepEnumTypes(VersionCaps version, StepEnum[] states) {
         version.setStepTypes(new StepTypes());
-        for(StepEnum type : states) {
+        for (StepEnum type : states) {
             version.getStepTypes().getStepType().add(type.value());
         }
     }
@@ -848,7 +856,7 @@
     private void addSELinuxModes(VersionCaps version, SELinuxMode[] values) {
         if (VersionUtils.greaterOrEqual(version, VERSION_3_5)) {
             version.setSelinuxModes(new SELinuxModes());
-            for (SELinuxMode mode: values) {
+            for (SELinuxMode mode : values) {
                 version.getSelinuxModes().getSELinuxModes().add(mode.value());
             }
         }
@@ -866,7 +874,16 @@
     private void addPolicyUnitTypes(VersionCaps version, PolicyUnitType[] 
values) {
         version.setSchedulingPolicyUnitTypes(new SchedulingPolicyUnitTypes());
         for (PolicyUnitType policyUnitType : values) {
-            
version.getSchedulingPolicyUnitTypes().getSchedulingPolicyUnitTypes().add(policyUnitType.name().toLowerCase());
+            version.getSchedulingPolicyUnitTypes()
+                    .getSchedulingPolicyUnitTypes()
+                    .add(policyUnitType.name().toLowerCase());
+        }
+    }
+
+    private void addSupportedQosTypes(VersionCaps version) {
+        version.setQosTypes(new QosTypes());
+        if (VersionUtils.greaterOrEqual(version, VERSION_3_5)) {
+            
version.getQosTypes().getQosTypes().add(org.ovirt.engine.api.model.QosType.STORAGE.name().toLowerCase());
         }
     }
 
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
index fdbd402..ef43ac7 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendClustersResource.java
@@ -74,7 +74,7 @@
     public Response add(Cluster cluster) {
         validateParameters(cluster, "name", "dataCenter.name|id");
         validateEnums(Cluster.class, cluster);
-        StoragePool pool = getStoragePool(cluster, this);
+        StoragePool pool = getStoragePool(cluster.getDataCenter(), this);
         VDSGroup entity = map(cluster, map(pool));
         return performCreate(VdcActionType.AddVdsGroup,
                 new VdsGroupOperationParameters(entity),
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterClustersResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterClustersResource.java
index bd9883d..10efe1a 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterClustersResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterClustersResource.java
@@ -49,7 +49,7 @@
         DataCenter dataCenter = new DataCenter();
         dataCenter.setId(dataCenterId.toString());
         cluster.setDataCenter(dataCenter);
-        StoragePool pool = getStoragePool(cluster, this);
+        StoragePool pool = getStoragePool(cluster.getDataCenter(), this);
         VDSGroup entity = map(cluster, map(pool));
         return performCreate(VdcActionType.AddVdsGroup,
                 new VdsGroupOperationParameters(entity),
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterResource.java
index b0cf716..b0a0269 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCenterResource.java
@@ -5,7 +5,6 @@
 
 import java.util.List;
 
-import org.ovirt.engine.api.model.Cluster;
 import org.ovirt.engine.api.model.DataCenter;
 import org.ovirt.engine.api.resource.AssignedPermissionsResource;
 import org.ovirt.engine.api.resource.AttachedStorageDomainsResource;
@@ -13,6 +12,7 @@
 import org.ovirt.engine.api.resource.DataCenterResource;
 import org.ovirt.engine.api.resource.IscsiBondsResource;
 import org.ovirt.engine.api.resource.NetworksResource;
+import org.ovirt.engine.api.resource.QoSsResource;
 import org.ovirt.engine.api.resource.QuotasResource;
 import org.ovirt.engine.api.restapi.utils.MalformedIdException;
 import org.ovirt.engine.core.common.VdcObjectType;
@@ -29,7 +29,7 @@
 public class BackendDataCenterResource extends 
AbstractBackendSubResource<DataCenter, StoragePool>
         implements DataCenterResource {
 
-    private BackendDataCentersResource parent;
+    private final BackendDataCentersResource parent;
 
     public BackendDataCenterResource(String id, BackendDataCentersResource 
parent) {
         super(id, DataCenter.class, StoragePool.class, SUB_COLLECTIONS);
@@ -64,6 +64,7 @@
         return inject(new BackendAttachedStorageDomainsResource(id));
     }
 
+    @Override
     public NetworksResource getNetworksResource() {
         return inject(new BackendDataCenterNetworksResource(id));
     }
@@ -110,10 +111,10 @@
      * cluster.
      */
     @SuppressWarnings("unchecked")
-    public static StoragePool getStoragePool(Cluster cluster, 
AbstractBackendResource parent) {
+    public static StoragePool getStoragePool(DataCenter dataCenter, 
AbstractBackendResource parent) {
         StoragePool pool = null;
-        if (cluster.getDataCenter().isSetId()) {
-            String id = cluster.getDataCenter().getId();
+        if (dataCenter.isSetId()) {
+            String id = dataCenter.getId();
             Guid guid;
             try {
                 guid = new Guid(id); // can't use asGuid() because the method 
is static.
@@ -123,11 +124,11 @@
             pool = parent.getEntity(StoragePool.class, 
VdcQueryType.GetStoragePoolById,
                     new IdQueryParameters(guid), "Datacenter: id=" + id);
         } else {
-            String clusterName = cluster.getDataCenter().getName();
+            String clusterName = dataCenter.getName();
             pool = parent.getEntity(StoragePool.class, 
VdcQueryType.GetStoragePoolByDatacenterName,
                     new NameQueryParameters(clusterName), "Datacenter: name="
                             + clusterName);
-            cluster.getDataCenter().setId(pool.getId().toString());
+            dataCenter.setId(pool.getId().toString());
         }
         return pool;
     }
@@ -144,4 +145,9 @@
                                                     "Datacenters",
                                                     true);
     }
+
+    @Override
+    public QoSsResource getQossResource() {
+        return inject(new BackendQossResource(id));
+    }
 }
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCentersResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCentersResource.java
index a0ff9ac..215b74e 100644
--- 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCentersResource.java
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendDataCentersResource.java
@@ -25,7 +25,7 @@
         AbstractBackendCollectionResource<DataCenter, StoragePool> implements 
DataCentersResource {
 
     static final String[] SUB_COLLECTIONS =
-            { "storagedomains", "clusters", "networks", "permissions", 
"quotas", "iscsibonds" };
+            { "storagedomains", "clusters", "networks", "permissions", 
"quotas", "iscsibonds", "qoss" };
 
     public BackendDataCentersResource() {
         super(DataCenter.class, StoragePool.class, SUB_COLLECTIONS);
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQosResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQosResource.java
new file mode 100644
index 0000000..91aee74
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQosResource.java
@@ -0,0 +1,79 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import org.ovirt.engine.api.model.QoS;
+import org.ovirt.engine.api.resource.QosResource;
+import org.ovirt.engine.core.common.action.QosParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+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 BackendQosResource extends AbstractBackendSubResource<QoS, 
QosBase> implements QosResource {
+
+    protected BackendQossResource parent;
+
+    public BackendQossResource getParent() {
+        return parent;
+    }
+
+    public BackendQosResource(String id, BackendQossResource parent) {
+        super(id, QoS.class, QosBase.class);
+        this.parent = parent;
+    }
+
+    @Override
+    public QoS get() {
+        IdQueryParameters params = new IdQueryParameters(guid);
+        QoS qos = performGet(VdcQueryType.GetQosById, params);
+        return qos;
+    }
+
+    @Override
+    public QoS update(final QoS incoming) {
+        QueryIdResolver<Guid> entityResolver =
+                new QueryIdResolver<Guid>(VdcQueryType.GetQosById, 
IdQueryParameters.class);
+        final QosBase qosBase =
+                getEntity(new QueryIdResolver<Guid>(VdcQueryType.GetQosById, 
IdQueryParameters.class), true);
+        VdcActionType updateActionType = null;
+
+        switch (qosBase.getQosType()) {
+        case STORAGE:
+            updateActionType = VdcActionType.UpdateStorageQos;
+            break;
+
+        default:
+            break;
+        }
+        return performUpdate(incoming,
+                entityResolver,
+                updateActionType,
+                new ParametersProvider<QoS, QosBase>() {
+                    @Override
+                    public VdcActionParametersBase getParameters(QoS model,
+                            QosBase entity) {
+                        QosParametersBase<QosBase> parameters = new 
QosParametersBase<QosBase>();
+                        parameters.setQosId(guid);
+                        parameters.setQos(map(incoming, entity));
+                        return parameters;
+                    }
+                });
+    }
+
+    protected class UpdateParametersProvider implements 
ParametersProvider<QoS, QosBase> {
+        @Override
+        public VdcActionParametersBase getParameters(QoS incoming,
+                QosBase entity) {
+            QosParametersBase<QosBase> parameters = new 
QosParametersBase<QosBase>();
+            parameters.setQosId(guid);
+            parameters.setQos(map(incoming, entity));
+            return parameters;
+        }
+    }
+
+    @Override
+    protected QoS doPopulate(QoS model, QosBase entity) {
+        return model;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQossResource.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQossResource.java
new file mode 100644
index 0000000..9979bdd
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendQossResource.java
@@ -0,0 +1,95 @@
+package org.ovirt.engine.api.restapi.resource;
+
+import java.util.List;
+
+import javax.ws.rs.core.Response;
+
+import org.ovirt.engine.api.model.DataCenter;
+import org.ovirt.engine.api.model.QoS;
+import org.ovirt.engine.api.model.QoSs;
+import org.ovirt.engine.api.resource.QoSsResource;
+import org.ovirt.engine.api.resource.QosResource;
+import org.ovirt.engine.api.restapi.utils.GuidUtils;
+import org.ovirt.engine.core.common.action.QosParametersBase;
+import org.ovirt.engine.core.common.action.VdcActionType;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.core.common.businessentities.qos.QosType;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+import org.ovirt.engine.core.common.queries.IdQueryParameters;
+import org.ovirt.engine.core.common.queries.QosQueryParameterBase;
+import org.ovirt.engine.core.common.queries.VdcQueryType;
+import org.ovirt.engine.core.compat.Guid;
+
+public class BackendQossResource extends 
AbstractBackendCollectionResource<QoS, QosBase> implements QoSsResource {
+
+    protected Guid dataCenterId;
+
+    protected BackendQossResource(String datacenterId) {
+        super(QoS.class, QosBase.class);
+        this.dataCenterId = asGuid(datacenterId);
+    }
+
+    @Override
+    public QoSs list() {
+        return 
mapCollection(getBackendCollection(VdcQueryType.GetAllQosByStoragePoolIdAndType,
+                new QosQueryParameterBase(dataCenterId)));
+    }
+
+    @Override
+    public Response add(QoS qos) {
+        validateParameters(qos, "name");
+        validateEnums(QoS.class, qos);
+        QosParametersBase<QosBase> params = new QosParametersBase<QosBase>();
+        QosBase entity = null;
+        VdcActionType addVdcActionType = null;
+        switch (QosType.valueOf(qos.getType().toUpperCase())) {
+        case STORAGE:
+            entity = new StorageQos();
+            addVdcActionType = VdcActionType.AddStorageQos;
+            break;
+
+        default:
+            break;
+        }
+        params.setQos(map(qos, entity));
+        if (dataCenterId != null) {
+            entity.setStoragePoolId(dataCenterId);
+        }
+        return performCreate(addVdcActionType,
+                params,
+                new QueryIdResolver<Guid>(VdcQueryType.GetQosById, 
IdQueryParameters.class));
+    }
+
+    @Override
+    protected Response performRemove(String id) {
+        QosParametersBase<?> params = new QosParametersBase<>();
+        params.setQosId(GuidUtils.asGuid(id));
+        return performAction(VdcActionType.RemoveStorageQos, params);
+    }
+
+    @Override
+    @SingleEntityResource
+    public QosResource getQosSubResource(String id) {
+        return inject(new BackendQosResource(id, this));
+    }
+
+    protected QoSs mapCollection(List<QosBase> entities) {
+        QoSs collection = new QoSs();
+        for (QosBase entity : entities) {
+            collection.getQoSs().add(addLinks(populate(map(entity), entity)));
+        }
+        return collection;
+    }
+
+    @Override
+    protected QoS addParents(QoS qos) {
+        qos.setDataCenter(new DataCenter());
+        qos.getDataCenter().setId(dataCenterId.toString());
+        return qos;
+    }
+
+    @Override
+    protected QoS doPopulate(QoS model, QosBase entity) {
+        return model;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/QosValidator.java
 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/QosValidator.java
new file mode 100644
index 0000000..5e5580a
--- /dev/null
+++ 
b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/validation/QosValidator.java
@@ -0,0 +1,15 @@
+package org.ovirt.engine.api.restapi.resource.validation;
+
+import static org.ovirt.engine.api.common.util.EnumValidator.validateEnum;
+
+import org.ovirt.engine.api.model.QoS;
+import org.ovirt.engine.core.common.businessentities.qos.QosType;
+
+@ValidatedClass(clazz = QoS.class)
+public class QosValidator implements Validator<QoS> {
+
+    @Override
+    public void validateEnums(QoS qos) {
+        validateEnum(QosType.class, qos.getType(), true);
+    }
+}
diff --git 
a/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QosMapper.java
 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QosMapper.java
new file mode 100644
index 0000000..f744a41
--- /dev/null
+++ 
b/backend/manager/modules/restapi/types/src/main/java/org/ovirt/engine/api/restapi/types/QosMapper.java
@@ -0,0 +1,105 @@
+package org.ovirt.engine.api.restapi.types;
+
+import org.ovirt.engine.api.model.DataCenter;
+import org.ovirt.engine.api.model.QoS;
+import org.ovirt.engine.api.model.QosType;
+import org.ovirt.engine.api.restapi.utils.GuidUtils;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+import org.ovirt.engine.core.common.businessentities.qos.StorageQos;
+
+public class QosMapper {
+
+    @Mapping(from = QosBase.class, to = QoS.class)
+    public static QoS map(QosBase entity, QoS template) {
+        QoS model = template != null ? template : new QoS();
+        model.setId(entity.getId().toString());
+        model.setName(entity.getName());
+        
model.setType(org.ovirt.engine.api.model.QosType.fromValue(entity.getQosType().toString()).name().toLowerCase());
+        model.setDataCenter(new DataCenter());
+        model.getDataCenter().setId(entity.getStoragePoolId().toString());
+        model.setDescription(entity.getDescription());
+        switch (entity.getQosType()) {
+        case STORAGE:
+            StorageQos storageQos = null;
+            // avoid findbugs error.
+            if (entity instanceof StorageQos) {
+                storageQos = (StorageQos) entity;
+            }
+            // avoid findbugs error.
+            if (storageQos == null) {
+                return model;
+            }
+            model.setMaxThroughput(storageQos.getMaxThroughput());
+            model.setMaxReadThroughput(storageQos.getMaxReadThroughput());
+            model.setMaxWriteThroughput(storageQos.getMaxWriteThroughput());
+            model.setMaxIops(storageQos.getMaxIops());
+            model.setMaxReadIops(storageQos.getMaxReadIops());
+            model.setMaxWriteIops(storageQos.getMaxWriteIops());
+        default:
+            break;
+        }
+
+        return model;
+    }
+
+    @Mapping(from = QoS.class, to = QosBase.class)
+    public static QosBase map(QoS model, QosBase template) {
+        QosBase entity = null;
+        if (template != null) {
+            entity = template;
+        }
+        QosType qosType =
+                model.getType() != null ? QosType.valueOf(model
+                        .getType().toUpperCase()) : entity != null ? 
QosType.valueOf(entity
+                        .getQosType().toString().toUpperCase()) : 
QosType.STORAGE;
+        switch (qosType) {
+        case STORAGE:
+            if (entity == null) {
+                entity = new StorageQos();
+            }
+            if (model.isSetMaxThroughput()) {
+                ((StorageQos) entity)
+                        
.setMaxThroughput(IntegerMapper.mapMinusOneToNull(model.getMaxThroughput()));
+            }
+            if (model.isSetMaxReadThroughput()) {
+                ((StorageQos) 
entity).setMaxReadThroughput(IntegerMapper.mapMinusOneToNull(model
+                        .getMaxReadThroughput()));
+            }
+            if (model.isSetMaxWriteThroughput()) {
+                ((StorageQos) 
entity).setMaxWriteThroughput(IntegerMapper.mapMinusOneToNull(model
+                        .getMaxWriteThroughput()));
+            }
+            if (model.isSetMaxIops()) {
+                ((StorageQos) entity)
+                        
.setMaxIops(IntegerMapper.mapMinusOneToNull(model.getMaxIops()));
+            }
+            if (model.isSetMaxReadIops()) {
+                ((StorageQos) entity)
+                        
.setMaxReadIops(IntegerMapper.mapMinusOneToNull(model.getMaxReadIops()));
+            }
+            if (model.isSetMaxWriteIops()) {
+                ((StorageQos) entity)
+                        
.setMaxWriteIops(IntegerMapper.mapMinusOneToNull(model.getMaxWriteIops()));
+            }
+            break;
+        default:
+            break;
+        }
+
+        if (model.isSetId()) {
+            entity.setId(GuidUtils.asGuid(model.getId()));
+        }
+        if (model.isSetName()) {
+            entity.setName(model.getName());
+        }
+        if (model.isSetDataCenter() && model.getDataCenter().isSetId()) {
+            entity.setStoragePoolId(GuidUtils.asGuid(model.getDataCenter()
+                    .getId()));
+        }
+        if (model.isSetDescription()) {
+            entity.setDescription(model.getDescription());
+        }
+
+        return entity;
+    }
+}
diff --git 
a/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/QosMapperTest.java
 
b/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/QosMapperTest.java
new file mode 100644
index 0000000..0458ea0
--- /dev/null
+++ 
b/backend/manager/modules/restapi/types/src/test/java/org/ovirt/engine/api/restapi/types/QosMapperTest.java
@@ -0,0 +1,40 @@
+package org.ovirt.engine.api.restapi.types;
+
+import org.ovirt.engine.api.model.QoS;
+import org.ovirt.engine.api.model.QosType;
+import org.ovirt.engine.core.common.businessentities.qos.QosBase;
+
+public class QosMapperTest extends AbstractInvertibleMappingTest<QoS, QosBase, 
QosBase> {
+
+    public QosMapperTest() {
+        super(QoS.class,
+                QosBase.class,
+                QosBase.class);
+    }
+
+    @Override
+    protected void verify(QoS model, QoS transform) {
+        assertNotNull(transform);
+        assertEquals(model.getName(), transform.getName());
+        assertEquals(model.getId(), transform.getId());
+        assertNotNull(transform.getDataCenter());
+        assertEquals(model.getDataCenter().getId(), 
transform.getDataCenter().getId());
+        assertEquals(model.getType(), transform.getType());
+        assertEquals(model.getDescription(), transform.getDescription());
+
+        // storage limits:
+        assertEquals(model.getMaxThroughput(), transform.getMaxThroughput());
+        assertEquals(model.getMaxReadThroughput(), 
transform.getMaxReadThroughput());
+        assertEquals(model.getMaxWriteThroughput(), 
transform.getMaxWriteThroughput());
+        assertEquals(model.getMaxIops(), transform.getMaxIops());
+        assertEquals(model.getMaxReadIops(), transform.getMaxReadIops());
+        assertEquals(model.getMaxWriteIops(), transform.getMaxWriteIops());
+    }
+
+    @Override
+    protected QoS postPopulate(QoS model) {
+        model = super.postPopulate(model);
+        
model.setType(MappingTestHelper.shuffle(QosType.class).name().toLowerCase());
+        return model;
+    }
+}


-- 
To view, visit http://gerrit.ovirt.org/31806
To unsubscribe, visit http://gerrit.ovirt.org/settings

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

Reply via email to