QoS Support (Capacity IOPS on the pool, Create Offering with QoS and Resize Changes for IOPS) - #102
suryag1201 wants to merge 15 commits into
Conversation
🔴 Test Coverage Grade:
|
| Metric | Value |
|---|---|
| Line coverage | 24.78% |
| Branch coverage | 18.92% |
Grade Scale
| Grade | Line Coverage | Meaning |
|---|---|---|
| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |
| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |
| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |
| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |
| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |
Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run
🔴 Test Coverage Grade:
|
| Metric | Value |
|---|---|
| Line coverage | 24.80% |
| Branch coverage | 18.94% |
Grade Scale
| Grade | Line Coverage | Meaning |
|---|---|---|
| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |
| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |
| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |
| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |
| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |
Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run
🔴 Test Coverage Grade:
|
| Metric | Value |
|---|---|
| Line coverage | 24.79% |
| Branch coverage | 18.93% |
Grade Scale
| Grade | Line Coverage | Meaning |
|---|---|---|
| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |
| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |
| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |
| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |
| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |
Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run
|
|
||
| CloudStackVolume request = iscsi | ||
| ? createCloneLunRequest(storagePool, details, volumeInfo, templatePoolRef, templateId) | ||
| ? createCloneLunRequest(storagePool, details, volumeInfo, templatePoolRef, templateId, qosPolicy) |
There was a problem hiding this comment.
can you help reminding me the reason for keeping this implementation like this instead strategy specific implementation ?
There was a problem hiding this comment.
Here, we are just creating the clone request the actual logic for file and lun are in specific strategy only.
it is also in same line with create, delete, and update.
|
This pull request has merge conflicts. Dear author, please fix the conflicts and sync your branch with the base branch. |
| if (userVmDetails != null) { | ||
| String minIops = userVmDetails.get(MIN_IOPS); | ||
| String maxIops = userVmDetails.get(MAX_IOPS); | ||
| String minIops = userVmDetails.get(VmDetailConstants.MIN_IOPS); |
There was a problem hiding this comment.
can you check for setters also for iops specific statements?
There was a problem hiding this comment.
From community, someone already raised the PR so i copied the same code as per the PR, will check the setter and update
There was a problem hiding this comment.
I checked the code and it is setting the value like deployVmData['details[0].minIops'] = this.minIops
deployVmData['details[0].maxIops'] = this.maxIops
So, the issue was with get only
| return; | ||
| } | ||
| VolumeQosPolicy policy = getVolumeQosPolicyByUuid(policyUuid); | ||
| if (policy.getObjectCount() != null && policy.getObjectCount() > 0) { |
There was a problem hiding this comment.
what if policy is retuned as null? it can be potentials candidate for NPE.
|
|
||
| @Override | ||
| public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) {} | ||
| public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback) { |
There was a problem hiding this comment.
Lets add todo for actual size specific impl until satvika's changes are not in
| @RequestLine("PATCH /api/storage/luns/{uuid}") | ||
| @Headers({"Authorization: {authHeader}", "Content-Type: application/json"}) | ||
| void updateLun(@Param("authHeader") String authHeader, @Param("uuid") String uuid, Lun lun); | ||
| JobResponse updateLun(@Param("authHeader") String authHeader, @Param("uuid") String uuid, Lun lun); |
There was a problem hiding this comment.
can you watch for usage of this method, have you updated all of them for this signature change ?
There was a problem hiding this comment.
@suryag1201 Some of the Ontap version has mix of return code for patch lun, 200 or 202. Could you please cross check if after 9.15.1, all version follows same code.
There was a problem hiding this comment.
created this task to address review comment: https://netapp.atlassian.net/browse/CSTACKEX-335
| "Unable to determine whether the ONTAP cluster is AFF or FAS"); | ||
| } | ||
| for (ClusterNode node : response.getRecords()) { | ||
| if (node == null || Boolean.FALSE.equals(node.getAllFlashOptimized())) { |
There was a problem hiding this comment.
null for node also treat this as non-AFF, this is not intended behaviour, right ?
| fetchData () { | ||
| this.loading = true | ||
| if (this.resource.size != null) { | ||
| this.form.size = Math.round(this.resource.size / (1024 * 1024 * 1024)) |
There was a problem hiding this comment.
math.round is not required as we discussed
There was a problem hiding this comment.
rebased the branch so this code change is not present under this PR
There was a problem hiding this comment.
I did not get the response, I can still see the method used.
There was a problem hiding this comment.
there was some issue with the rebase, now this change not present
| this.form.diskofferingid = this.offerings[0].id || '' | ||
| this.customDiskOffering = this.offerings[0].iscustomized || false | ||
| this.customDiskOfferingIops = this.offerings[0].iscustomizediops || false | ||
| const currentOffering = (json.listdiskofferingsresponse.diskoffering || [])[0] |
There was a problem hiding this comment.
how can we ensure it will not regress any existing workflow?
There was a problem hiding this comment.
rebased the branch so this code change is not present under this PR
eca1e9a to
cfdc801
Compare
🔴 Test Coverage Grade:
|
| Metric | Value |
|---|---|
| Line coverage | 24.79% |
| Branch coverage | 18.93% |
Grade Scale
| Grade | Line Coverage | Meaning |
|---|---|---|
| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |
| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |
| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |
| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |
| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |
Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run
| storagePool, details, volumeObject, qosPolicy); | ||
| try { | ||
| CloudStackVolume created = storageStrategy.createCloudStackVolume(request); | ||
| persistQosPolicyDetails(volumeObject.getId(), qosPolicy); |
There was a problem hiding this comment.
if there is no QoS, workflows are working fine.
Testing section also updated with details
🔴 Test Coverage Grade:
|
| Metric | Value |
|---|---|
| Line coverage | 24.79% |
| Branch coverage | 18.93% |
Grade Scale
| Grade | Line Coverage | Meaning |
|---|---|---|
| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |
| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |
| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |
| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |
| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |
Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run
| storageStrategy.deleteCloudStackVolume(cloudStackVolumeRequest); | ||
| if (qosPolicyDetail != null) { | ||
| volumeDetailsDao.removeDetail(volumeInfo.getId(), OntapStorageConstants.QOS_POLICY_UUID); | ||
| storageStrategy.deleteVolumeQosPolicy(qosPolicyDetail.getValue()); |
There was a problem hiding this comment.
you need to handle the exception here since you already have deleted the cloudstack volume above, we can not make this method fail. Lets add logger.error in exception case and this has to pass.
| return created; | ||
| } catch (RuntimeException e) { | ||
| if (qosPolicy != null) { | ||
| storageStrategy.deleteVolumeQosPolicy(qosPolicy.getUuid()); |
There was a problem hiding this comment.
Do ensure to check whether intended policy is not shared one before delete as part of rollback.
There was a problem hiding this comment.
deleteVolumeQosPolicy method will check for Object count before performing delete operation
| StorageStrategy storageStrategy = StorageProviderFactory.getStrategy(ontapStorage); | ||
| boolean isValid = storageStrategy.connect(); | ||
| if (isValid) { | ||
| details.put(OntapStorageConstants.IS_AFF, Boolean.toString(storageStrategy.isAff())); |
There was a problem hiding this comment.
isAFF also throwing an exception for one scenario, it is not handled here
There was a problem hiding this comment.
Current code never reads is_capacity_optimized or is_perf_optimized for isAFF. It only checks for is_all_flash_optimized and make the isAFF as true as per this field "is_all_flash_optimized".
d3ba527 to
9e8fe3e
Compare
| "Unable to determine whether the ONTAP cluster is AFF or FAS"); | ||
| } | ||
| for (ClusterNode node : response.getRecords()) { | ||
| if (node != null && Boolean.FALSE.equals(node.getAllFlashOptimized())) { |
There was a problem hiding this comment.
What happens if node.getAllFlashOptimized() returns null for a node? With the current implementation, that scenario would still result in the node being classified as AFF. It would be safer to add an explicit else block to handle such cases and avoid incorrect classification due to unexpected or missing values.
🔴 Test Coverage Grade:
|
| Metric | Value |
|---|---|
| Line coverage | 24.79% |
| Branch coverage | 18.93% |
Grade Scale
| Grade | Line Coverage | Meaning |
|---|---|---|
| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |
| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |
| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |
| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |
| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |
Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run
| @RequestLine("PATCH /api/storage/luns/{uuid}") | ||
| @Headers({"Authorization: {authHeader}", "Content-Type: application/json"}) | ||
| void updateLun(@Param("authHeader") String authHeader, @Param("uuid") String uuid, Lun lun); | ||
| JobResponse updateLun(@Param("authHeader") String authHeader, @Param("uuid") String uuid, Lun lun); |
There was a problem hiding this comment.
@suryag1201 Some of the Ontap version has mix of return code for patch lun, 200 or 202. Could you please cross check if after 9.15.1, all version follows same code.
| @RequestLine("DELETE /api/storage/luns/{uuid}") | ||
| @Headers({"Authorization: {authHeader}"}) | ||
| void deleteLun(@Param("authHeader") String authHeader, @Param("uuid") String uuid, @QueryMap Map<String, Object> queryMap); | ||
| JobResponse deleteLun(@Param("authHeader") String authHeader, @Param("uuid") String uuid, @QueryMap Map<String, Object> queryMap); |
There was a problem hiding this comment.
same here, check for 200 or 202 both.
There was a problem hiding this comment.
I do not have 9.15.1 cluster, i will check this
| private Integer minThroughputIops = null; | ||
|
|
||
| @JsonProperty("fixed") | ||
| private Fixed fixed; |
There was a problem hiding this comment.
Why not rename this file as QosPolicy as this model is also used for File qos also ?
There was a problem hiding this comment.
u mean from VolumeQoSPolicy to QoSPolicy?
There was a problem hiding this comment.
this file is already existing and usage is also 67 places, we can take this up later if required
| @JsonInclude(JsonInclude.Include.NON_NULL) | ||
| public static class Fixed { | ||
| @JsonProperty("capacity_shared") | ||
| private Boolean capacityShared; |
There was a problem hiding this comment.
have default value for this incase we don get these field
There was a problem hiding this comment.
If the field is left unset, @JsonInclude(NON_NULL) omits it, and ONTAP treats a missing capacity_shared as false.
| + ONTAP_MIN_VOLUME_SIZE_IN_BYTES + " bytes (20 MB)"); | ||
| } | ||
| // IOPS capacity is optional; when left blank no pool-level IOPS ceiling is enforced. | ||
| if (capacityIops != null && capacityIops <= 0) { |
There was a problem hiding this comment.
we should have capacityIops == null check also for API user, otherwise null will be set in details.
There was a problem hiding this comment.
it will not store capacityIOPS in details map
| logger.error("createCloudStackVolume: " + errMsg); | ||
| throw new CloudRuntimeException(errMsg); | ||
| } | ||
| if (cloudstackVolume.getFile() != null && cloudstackVolume.getFile().getQosPolicy() != null) { |
There was a problem hiding this comment.
will a file have a qos already attached if we are checking != null ? is there a default qos attached when file is created ?
There was a problem hiding this comment.
QoS value, i am setting during request creation and using it here for the patch operation after file create
| } | ||
| if (cloudstackVolume.getFile() != null && cloudstackVolume.getFile().getQosPolicy() != null) { | ||
| try { | ||
| updateCloudStackVolume(cloudstackVolume); |
There was a problem hiding this comment.
is this part create workflow or update ?
There was a problem hiding this comment.
this update method will patch the file with QoS
🔴 Test Coverage Grade:
|
| Metric | Value |
|---|---|
| Line coverage | 24.78% |
| Branch coverage | 18.93% |
Grade Scale
| Grade | Line Coverage | Meaning |
|---|---|---|
| 🟢 A | ≥ 80% | Excellent - this code sleeps well at night 😴 |
| 🟡 B | 60-79% | Good - almost there, don't stop now 😉 |
| 🟠 C | 40-59% | Acceptable - your code is wearing a seatbelt, but no airbags 😬 |
| 🔴 D | 20-39% | Marginal - boldly shipping where no test has gone before 🖖 |
| ⛔ F | < 20% | Failing - tests? what tests? 🔥 |
Branch coverage is shown as a secondary signal. Grade is determined by line coverage.
View full Actions run
Description
QoS Support includes:
1- Capacity IOPS on the pool,
2- Create Disk/Compute offering with QoS
3- Resize changes for QoS
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
Performed the below testing for ISCSI and NFS both
1- Created the compute/disk offering with CustomIOPS and Fix IOPS both (min 2000, max 10000)
2- Created a Storage Pool with Total IOPS 5000 - It will just store the value in DB
3- Create a VM with Fix IOPS (ROOT + 1 DATA) - Created Lun/File, QoS policy got created and attached to file/lun
4- Create a VM with Custom IOPS (min 2000, max 5000) (ROOT + 1 DATA) - Created Lun/File, new QoS policy got created and attached to file/lun
5- Create a VM with Fix IOPS (ROOT + 1 DATA) again - Failed with error saying there is no more IOPS on a pool
6- Change the Total IOPS on pool - worked and new VM creation also went fine.
7- Resize the Volume, QoS existing field got populated and changed the min and max value - that also worked by creating new QoS if not found and attached to the file/Lun
8- Tested on FAS platform where Min QoS is set 1000 and it throw the error in logs, not on UI as UI is not using the thrown message from vendor
9- Tested on FAS platform where Min QoS is set 0 and VM created successfully.
10- Tested with No QoS - Success
How did you try to break this feature and the system with this change?