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