Skip to content

Conversation

@rafaelweingartner
Copy link
Member

Description

When the feature to enable disk offering replacement during volume migration was created, we were forcing the tags of the new disk offering to exact the same as the tags of the target storage poll. However, that is not how ACS manages volumes allocation. This change modifies this validation to make it consistent with volume allocation.

The idea is to make the validation consistent with the mechanism used to select a storage pool to deploy a volume when a virtual machine is deployed or when a new data disk is allocated. The scenarios when this method returns true or false is presented in the following table.

#Disk offering tagsStorage tagsDoes the storage support the disk offering?
1A,BANO
2A,B,CA,B,C,D,XYES
3A,B,CX,Y,ZNO
4nullA,S,DYES
5AnullNO
6nullnullYES

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)

How Has This Been Tested?

Locally and via unit tests that were added for the code that has been changed.

Checklist:

  • I have read the CONTRIBUTING document.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
    Testing
  • I have added tests to cover my changes.
  • All relevant new and existing integration tests have passed.
  • A full integration testsuite with all test that can run on my environment has passed.

@rohityadavcloud
Copy link
Member

@rafaelweingartner this is opened against master, if you do not want this in 4.11 can you change the milestone to 4.12.0.0?

Copy link
Contributor

@DaanHoogland DaanHoogland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you(r tests) rule, @rafaelweingartner

}

@Test
public void doesTargetStorageSupportNewDiskOfferingTestDiskOfferingMoreTagsThanStorageTags() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow, how java of you @rafaelweingartner , can you translate this name?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, this is something I do to control the unit tests. The pattern I normally use is the following:
Test
Translating this case:
I am testing the method doesTargetStorageSupportNewDiskOffering with the following condition:

  • the disk offering will have more tags than the target storage

There is also another format I use:
<methodNamte>Test
Happy day test. It can be the case when the method finishes successfully or a method that does not have different execution flows.

* </body>
* </table>
*/
protected boolean doesTargetStorageSupportNewDiskOffering(StoragePool destPool, DiskOfferingVO newDiskOffering) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see the parameter appearing in the method name. why not isSupported(pool, offering);?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point. I normally try to be very descriptive with method names. When I see names such as isSupported, even though we see the parameters there, we have no clues what the method is checking. It could be that the method is checking if the storage has enough IOPs, or the method has enough space, or any other business logic. Maybe, a better name here would be doesTargetStorageSupportNewDiskOfferingTags.

Of course, here I have documented the method in detail. However, this should not be an excuse not to try to work out a good and descriptive method name.

Copy link
Contributor

@borisstoyanov borisstoyanov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rafaelweingartner
Copy link
Member Author

@rhtyd the feature I am enhancing is only in 4.12. That is why this PR is targeting 4.12.

@rafaelweingartner rafaelweingartner modified the milestones: 4.11.2.0, 4.12.0.0 May 11, 2018
@rafaelweingartner
Copy link
Member Author

Ops, now I see what you meant. I selected 4.11.2, instead of 4.12.
Problem fixed now.

if (isnewDiskOfferingTagsBlank) {
return true;
}
String storageTags = getStoragePoolTags(destPool);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rafaelweingartner, Thanks for the fix. I would suggest the variable name as storagePoolTags.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

*/
protected boolean doesTargetStorageSupportNewDiskOffering(StoragePool destPool, DiskOfferingVO newDiskOffering) {
String newDiskOfferingTags = newDiskOffering.getTags();
boolean isnewDiskOfferingTagsBlank = org.apache.commons.lang.StringUtils.isBlank(newDiskOfferingTags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, we use the variable only once, can we scrap this and put the statement directly in IF condition. Same for isStorageTagsBlank. Like if(org.apache.commons.lang.StringUtils.isBlank(newDiskOfferingTags)).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I can do that.

@rafaelweingartner rafaelweingartner force-pushed the consitentValidationInVolumeMigrationWithDiskOfferingReplacement branch 2 times, most recently from 215ac45 to 27ecc5b Compare May 11, 2018 11:47
return true;
}
String storagePoolTags = getStoragePoolTags(destPool);
boolean isStorageTagsBlank = org.apache.commons.lang.StringUtils.isBlank(storagePoolTags);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

@Test
public void doesTargetStorageSupportNewDiskOfferingTestDiskOfferingTagsIsSubSetOfStorageTags() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, would be good if we add the equal case as well. Like DiskOfferingTag('A') and StoragePoolTag('A'). Should return true.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

@rafaelweingartner rafaelweingartner force-pushed the consitentValidationInVolumeMigrationWithDiskOfferingReplacement branch from ef92a2d to bead306 Compare May 16, 2018 20:44
@rafaelweingartner
Copy link
Member Author

@blueorangutan package

@blueorangutan
Copy link

@rafaelweingartner a Jenkins job has been kicked to build packages. I'll keep you posted as I make progress.

@blueorangutan
Copy link

Packaging result: ✔centos6 ✔centos7 ✔debian. JID-2060

…replacement

When the feature to enable disk offering replacement during volume migration was created, we were forcing the tags of the new disk offering to exact the same as the tags of the target storage poll. However, that is not how ACS manages volumes allocation. This change modifies this validation to make it consistent with volume allocation.
@rafaelweingartner rafaelweingartner force-pushed the consitentValidationInVolumeMigrationWithDiskOfferingReplacement branch from bead306 to 4f59b93 Compare July 13, 2018 13:47
@rafaelweingartner
Copy link
Member Author

@DaanHoogland can you please run tests here?

@DaanHoogland
Copy link
Contributor

@blueorangutan test

@blueorangutan
Copy link

@DaanHoogland a Trillian-Jenkins test job (centos7 mgmt + kvm-centos7) has been kicked to run smoke tests

@blueorangutan
Copy link

Trillian test result (tid-2847)
Environment: kvm-centos7 (x2), Advanced Networking with Mgmt server 7
Total time taken: 17056 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr2636-t2847-kvm-centos7.zip
Intermitten failure detected: /marvin/tests/smoke/test_certauthority_root.py
Intermitten failure detected: /marvin/tests/smoke/test_primary_storage.py
Intermitten failure detected: /marvin/tests/smoke/test_privategw_acl.py
Intermitten failure detected: /marvin/tests/smoke/test_public_ip_range.py
Intermitten failure detected: /marvin/tests/smoke/test_reset_vm_on_reboot.py
Intermitten failure detected: /marvin/tests/smoke/test_router_dhcphosts.py
Intermitten failure detected: /marvin/tests/smoke/test_router_dns.py
Intermitten failure detected: /marvin/tests/smoke/test_router_dnsservice.py
Intermitten failure detected: /marvin/tests/smoke/test_routers_iptables_default_policy.py
Intermitten failure detected: /marvin/tests/smoke/test_routers_network_ops.py
Intermitten failure detected: /marvin/tests/smoke/test_routers.py
Intermitten failure detected: /marvin/tests/smoke/test_secondary_storage.py
Intermitten failure detected: /marvin/tests/smoke/test_service_offerings.py
Intermitten failure detected: /marvin/tests/smoke/test_snapshots.py
Intermitten failure detected: /marvin/tests/smoke/test_ssvm.py
Intermitten failure detected: /marvin/tests/smoke/test_templates.py
Intermitten failure detected: /marvin/tests/smoke/test_usage.py
Intermitten failure detected: /marvin/tests/smoke/test_vm_life_cycle.py
Intermitten failure detected: /marvin/tests/smoke/test_vm_snapshots.py
Intermitten failure detected: /marvin/tests/smoke/test_volumes.py
Intermitten failure detected: /marvin/tests/smoke/test_vpc_redundant.py
Intermitten failure detected: /marvin/tests/smoke/test_vpc_router_nics.py
Intermitten failure detected: /marvin/tests/smoke/test_vpc_vpn.py
Intermitten failure detected: /marvin/tests/smoke/test_host_maintenance.py
Intermitten failure detected: /marvin/tests/smoke/test_hostha_kvm.py
Smoke tests completed. 43 look OK, 24 have error(s)
Only failed tests results shown below:

Test Result Time (s) Test File
test_provision_certificate Error 8.21 test_certauthority_root.py
test_01_add_primary_storage_disabled_host Error 1.20 test_primary_storage.py
test_01_primary_storage_nfs Error 0.10 test_primary_storage.py
ContextSuite context=TestStorageTags>:setup Error 0.18 test_primary_storage.py
test_03_vpc_privategw_restart_vpc_cleanup Failure 337.38 test_privategw_acl.py
test_04_rvpc_privategw_static_routes Failure 535.67 test_privategw_acl.py
test_04_rvpc_privategw_static_routes Error 581.76 test_privategw_acl.py
ContextSuite context=TestResetVmOnReboot>:setup Error 0.00 test_reset_vm_on_reboot.py
ContextSuite context=TestRouterDHCPHosts>:setup Error 0.00 test_router_dhcphosts.py
ContextSuite context=TestRouterDHCPOpts>:setup Error 0.00 test_router_dhcphosts.py
ContextSuite context=TestRouterDns>:setup Error 0.00 test_router_dns.py
ContextSuite context=TestVmSnapshot>:setup Error 0.04 test_vm_snapshots.py
ContextSuite context=TestRouterDnsService>:setup Error 0.00 test_router_dnsservice.py
ContextSuite context=TestRouterIpTablesPolicies>:setup Error 0.00 test_routers_iptables_default_policy.py
ContextSuite context=TestVPCIpTablesPolicies>:setup Error 0.00 test_routers_iptables_default_policy.py
test_01_isolate_network_FW_PF_default_routes_egress_true Error 0.11 test_routers_network_ops.py
test_02_isolate_network_FW_PF_default_routes_egress_false Error 0.10 test_routers_network_ops.py
ContextSuite context=TestRedundantIsolateNetworks>:setup Error 1.24 test_routers_network_ops.py
ContextSuite context=TestRouterServices>:setup Error 0.00 test_routers.py
test_01_sys_vm_start Failure 0.08 test_secondary_storage.py
test_02_sys_template_ready Failure 0.06 test_secondary_storage.py
ContextSuite context=TestCpuCapServiceOfferings>:setup Error 0.00 test_service_offerings.py
ContextSuite context=TestServiceOfferings>:setup Error 0.14 test_service_offerings.py
ContextSuite context=TestSnapshotRootDisk>:setup Error 0.00 test_snapshots.py
test_01_list_sec_storage_vm Failure 0.03 test_ssvm.py
test_02_list_cpvm_vm Failure 0.03 test_ssvm.py
test_03_ssvm_internals Failure 0.03 test_ssvm.py
test_04_cpvm_internals Failure 0.03 test_ssvm.py
test_05_stop_ssvm Failure 0.03 test_ssvm.py
test_06_stop_cpvm Failure 0.03 test_ssvm.py
test_07_reboot_ssvm Failure 0.03 test_ssvm.py
test_08_reboot_cpvm Failure 0.03 test_ssvm.py
test_09_destroy_ssvm Failure 0.03 test_ssvm.py
test_10_destroy_cpvm Failure 0.03 test_ssvm.py
test_02_create_template_with_checksum_sha1 Error 65.34 test_templates.py
test_03_create_template_with_checksum_sha256 Error 65.34 test_templates.py
test_04_create_template_with_checksum_md5 Error 65.34 test_templates.py
test_05_create_template_with_no_checksum Error 65.33 test_templates.py
test_02_deploy_vm_from_direct_download_template Error 5.03 test_templates.py
test_03_deploy_vm_wrong_checksum Error 5.28 test_templates.py
ContextSuite context=TestTemplates>:setup Error 18.73 test_templates.py
ContextSuite context=TestISOUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestLBRuleUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestNatRuleUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestPublicIPUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestSnapshotUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestVmUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestVolumeUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestVpnUsage>:setup Error 0.00 test_usage.py
ContextSuite context=TestCreateVolume>:setup Error 0.00 test_volumes.py
ContextSuite context=TestVolumes>:setup Error 0.00 test_volumes.py
ContextSuite context=TestDeployVM>:setup Error 0.00 test_vm_life_cycle.py
ContextSuite context=TestSecuredVmMigration>:setup Error 0.00 test_vm_life_cycle.py
ContextSuite context=TestVMLifeCycle>:setup Error 0.00 test_vm_life_cycle.py
test_01_create_redundant_VPC_2tiers_4VMs_4IPs_4PF_ACL Error 2.65 test_vpc_redundant.py
test_02_redundant_VPC_default_routes Error 3.65 test_vpc_redundant.py
test_03_create_redundant_VPC_1tier_2VMs_2IPs_2PF_ACL_reboot_routers Error 2.65 test_vpc_redundant.py
test_04_rvpc_network_garbage_collector_nics Error 1.62 test_vpc_redundant.py
test_05_rvpc_multi_tiers Error 1.63 test_vpc_redundant.py
test_01_VPC_nics_after_destroy Error 3.65 test_vpc_router_nics.py
test_02_VPC_default_routes Error 2.61 test_vpc_router_nics.py
test_01_redundant_vpc_site2site_vpn Failure 2.25 test_vpc_vpn.py
test_01_vpc_site2site_vpn_multiple_options Failure 2.23 test_vpc_vpn.py
test_01_vpc_remote_access_vpn Failure 1.12 test_vpc_vpn.py
test_01_vpc_site2site_vpn Failure 2.24 test_vpc_vpn.py
test_01_cancel_host_maintenace_with_no_migration_jobs Failure 0.09 test_host_maintenance.py
test_02_cancel_host_maintenace_with_migration_jobs Error 1.23 test_host_maintenance.py
test_hostha_enable_ha_when_host_in_maintenance Error 2.44 test_hostha_kvm.py

@borisstoyanov
Copy link
Contributor

@blueorangutan test

@blueorangutan
Copy link

@borisstoyanov a Trillian-Jenkins test job (centos7 mgmt + kvm-centos7) has been kicked to run smoke tests

@blueorangutan
Copy link

Trillian test result (tid-2853)
Environment: kvm-centos7 (x2), Advanced Networking with Mgmt server 7
Total time taken: 23457 seconds
Marvin logs: https://github.com/blueorangutan/acs-prs/releases/download/trillian/pr2636-t2853-kvm-centos7.zip
Intermitten failure detected: /marvin/tests/smoke/test_certauthority_root.py
Intermitten failure detected: /marvin/tests/smoke/test_privategw_acl.py
Intermitten failure detected: /marvin/tests/smoke/test_vm_life_cycle.py
Intermitten failure detected: /marvin/tests/smoke/test_vpc_redundant.py
Smoke tests completed. 64 look OK, 3 have error(s)
Only failed tests results shown below:

Test Result Time (s) Test File
test_provision_certificate Error 7.22 test_certauthority_root.py
test_03_vpc_privategw_restart_vpc_cleanup Error 149.37 test_privategw_acl.py
test_01_secured_vm_migration Error 37.45 test_vm_life_cycle.py
test_02_not_secured_vm_migration Error 37.46 test_vm_life_cycle.py
test_03_secured_to_nonsecured_vm_migration Error 37.47 test_vm_life_cycle.py
test_04_nonsecured_to_secured_vm_migration Error 37.47 test_vm_life_cycle.py

* </body>
* </table>
*/
protected boolean doesTargetStorageSupportNewDiskOffering(StoragePool destPool, DiskOfferingVO newDiskOffering) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a protected method. When we want to let a hypervisor do the entire migration it would be convenient to call this method from elsewhere. Does it make sense to put it on the interface? I am thinking about the VirtualMachineManager or the HypervisorGurus.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I am not sure if we have some other places that can use this method. I would normally only set a method to public and declare it in an interface if I need really need it. I can declare it if you think it is important though.

P.S.: I find our interface usage sometimes quite silly with single implementations. A good example is using interface for POJOs. It does not provide benefits, the only thing it does is adding dozens more lines for every object.

Copy link
Contributor

@DaanHoogland DaanHoogland Jul 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, nice subject: another valid usage is mutual dependent services. Or dependency injection.
I this case my concern is that the implementation of tag matching is done in several places while it should be uniform and thus implemented centrally. doesTargetStorageASupportNewDiskOffering() is a specialisation of does_this_entities_tags_match_the_resource_it_is_going_to(entity, resource) which is applicable to volume/storage in case of new offering but also in case of migration, and is also applicable for vm-serviceoffering/host-cluster-pod etc. I cant' think of any others by head but these are surely there as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new method that I implemented is the consolidation of the logic of tag matching in ACS, which is not extracted in a specific method and spread around the code. That is one of the reasons why I “made the mistake” in one of the features I developed where the tag matching was being too strict (requiring all tags to match) and was not making sense to operation guys.

To answer your question, yes this method can be used in other places. I am not sure if simply declaring the method in the interface will help much though. The person that is willing to consolidate these execution flow could do both, declare this method in the interface, and then use it in all of those places that you mentioned.

What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a nice future plan to extract the logic to a tagging utility and then make this method use it and be given a more general name like

 doesTargetStorageSupportDiskOffering() // not no 'New' in there

and have it call the utility

 matchOk(Set<String> tags, List<String> supported);

plan?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matchOk is just a bad method-name i came up with. we need a set of methods that do the matching for us for
Set tags, List supported or
List<List> tags, List supported or
String tag(s), List supported etc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but in this case I think we should create methods on demand. I mean, we do not know what we need yet. Therefore, there is no reason to start coding methods that we do not even know if we will use them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, maybe postpone this discussion to a beer session ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course I meant hackathon

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahaha.. I do not know why, but I would prefer a beer session...

I will do the change you asked later (making the method public in the interface).

@rafaelweingartner
Copy link
Member Author

@DaanHoogland I applied your suggestion here regarding "doesTargetStorageSupportDiskOffering" method in the interface.

}
String[] storageTagsAsStringArray = org.apache.commons.lang.StringUtils.split(storagePoolTags, ",");
String[] newDiskOfferingTagsAsStringArray = org.apache.commons.lang.StringUtils.split(newDiskOfferingTags, ",");
String[] newDiskOfferingTagsAsStringArray = org.apache.commons.lang.StringUtils.split(diskOfferingTags, ",");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a StringUtils.listToCsvTags() method.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong advice here, see below

if (org.apache.commons.lang.StringUtils.isBlank(storagePoolTags)) {
return false;
}
String[] storageTagsAsStringArray = org.apache.commons.lang.StringUtils.split(storagePoolTags, ",");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is a StringUtils.csvTagsToList()

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you talking about com.cloud.utils.StringUtils.csvTagsToList(String)?
Didn't we talk about stop using that "utils" class, so we can then remove it in the future?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we agreed to move all string operation in it so it we have a small interface plain to external libraries.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we?! That means we would create a layer over a library. I think we had a discussion, but I was under the impression that the idea was not to redo the wheel. Of course, my memory is not as good as it was before, so I am probably mistaken.

Copy link
Contributor

@DaanHoogland DaanHoogland Jul 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion it is best to isolate all external libraries in wrappers so porting from version to version or from vendor to vendor becomes easier/more isolated. In fact the hypervisor guru and resource and data motion strategies are examples of that as well. We didn't make an on mail list decision of it but I thought I had convinced you of it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, but those "gurus"/plugins/drivers and so on are different "things".
I mean, they are not library, they are part of our code base to deliver our business. On the other hand, creating a layer over third party utils libraries such as StringUtils, NumberUtils, Hibernate, Spring and so on sound like an overkill.

We should discuss that we beers in Montreal :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one word: gson
and a lot of beers

@DaanHoogland
Copy link
Contributor

@rafaelweingartner , I would argue this is a bug fix and should go on the lts branch (4.11). agree?

@rafaelweingartner
Copy link
Member Author

Unless I am mistaken, this feature is not in 4.11

@DaanHoogland
Copy link
Contributor

ah, the offering replacement.

@borisstoyanov
Copy link
Contributor

Is there any outstanding comments? I think this looks good for merging.

@rafaelweingartner rafaelweingartner merged commit 756a7e8 into apache:master Jul 21, 2018
borisstoyanov pushed a commit to shapeblue/cloudstack that referenced this pull request Jul 23, 2018
…replacement (apache#2636)

* Fix limitation on tag matching in 'migrateVolume' with disk offering replacement

When the feature to enable disk offering replacement during volume migration was created, we were forcing the tags of the new disk offering to exact the same as the tags of the target storage poll. However, that is not how ACS manages volumes allocation. This change modifies this validation to make it consistent with volume allocation.

* Address Nitin's suggestions

* Apply Daan's suggestion regarding "doesTargetStorageSupportDiskOffering" method

* fix problem
julien-vaz pushed a commit to scclouds/cloudstack that referenced this pull request Feb 18, 2025
Restauração do `apilog.log`

Closes apache#2636

See merge request scclouds/scclouds!1141
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants