From e44395915b4a981723d7dba6cdd7a41c5ec7b7f5 Mon Sep 17 00:00:00 2001 From: Henrique Sato Date: Wed, 8 Oct 2025 18:12:01 -0300 Subject: [PATCH 1/3] Add offering preset variable to Network and VPC tariffs --- ...s-between-management-and-usage-context.xml | 2 + ...spring-engine-schema-core-daos-context.xml | 2 - .../presetvariables/PresetVariableHelper.java | 32 +++++++++++++++- .../activationrule/presetvariables/Value.java | 24 ++++++++++++ .../PresetVariableHelperTest.java | 37 +++++++++++++++++++ 5 files changed, 94 insertions(+), 3 deletions(-) diff --git a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml index d308a9e5aaf9..15fd9c76b61c 100644 --- a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml +++ b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml @@ -73,4 +73,6 @@ + + diff --git a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 7e9d6c3b54f0..82c10496a6a4 100644 --- a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -236,13 +236,11 @@ - - diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java index 2a6ad132f63e..b6ca54a0cea1 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java @@ -28,11 +28,12 @@ import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterDetailsVO; import com.cloud.host.HostTagVO; +import com.cloud.hypervisor.Hypervisor; import com.cloud.network.dao.NetworkVO; +import com.cloud.network.vpc.VpcOfferingVO; import com.cloud.network.vpc.VpcVO; import javax.inject.Inject; -import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.StoragePoolTagVO; import org.apache.cloudstack.acl.RoleVO; import org.apache.cloudstack.acl.dao.RoleDao; @@ -66,6 +67,7 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostTagsDao; +import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.server.ResourceTag; @@ -191,6 +193,9 @@ public class PresetVariableHelper { @Inject ClusterDetailsDao clusterDetailsDao; + @Inject + VpcOfferingDao vpcOfferingDao; + protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value(); private List runningAndAllocatedVmUsageTypes = Arrays.asList(UsageTypes.RUNNING_VM, UsageTypes.ALLOCATED_VM); @@ -778,6 +783,19 @@ protected void loadPresetVariableValueForNetwork(UsageVO usageRecord, Value valu value.setId(network.getUuid()); value.setName(network.getName()); value.setState(usageRecord.getState()); + + value.setNetworkOffering(getPresetVariableValueNetworkOffering(network.getNetworkOfferingId())); + } + + protected GenericPresetVariable getPresetVariableValueNetworkOffering(Long networkOfferingId) { + NetworkOfferingVO networkOfferingVo = networkOfferingDao.findByIdIncludingRemoved(networkOfferingId); + validateIfObjectIsNull(networkOfferingVo, networkOfferingId, "network offering"); + + GenericPresetVariable networkOffering = new GenericPresetVariable(); + networkOffering.setId(networkOfferingVo.getUuid()); + networkOffering.setName(networkOfferingVo.getName()); + + return networkOffering; } protected void loadPresetVariableValueForVpc(UsageVO usageRecord, Value value) { @@ -793,6 +811,18 @@ protected void loadPresetVariableValueForVpc(UsageVO usageRecord, Value value) { value.setId(vpc.getUuid()); value.setName(vpc.getName()); + value.setVpcOffering(getPresetVariableValueVpcOffering(vpc.getVpcOfferingId())); + } + + protected GenericPresetVariable getPresetVariableValueVpcOffering(long vpcOfferingId) { + VpcOfferingVO vpcOfferingVo = vpcOfferingDao.findByIdIncludingRemoved(vpcOfferingId); + validateIfObjectIsNull(vpcOfferingVo, vpcOfferingId, "vpc offering"); + + GenericPresetVariable vpcOffering = new GenericPresetVariable(); + vpcOffering.setId(vpcOfferingVo.getUuid()); + vpcOffering.setName(vpcOfferingVo.getName()); + + return vpcOffering; } /** diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java index 77e539db0f3d..c76cbe137e61 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java @@ -100,6 +100,12 @@ public class Value extends GenericPresetVariable { private String state; + @PresetVariableDefinition(description = "Network offering of the network.", supportedTypes = {QuotaTypes.NETWORK}) + private GenericPresetVariable networkOffering; + + @PresetVariableDefinition(description = "VPC offering of the VPC.", supportedTypes = {QuotaTypes.VPC}) + private GenericPresetVariable vpcOffering; + public Host getHost() { return host; } @@ -279,4 +285,22 @@ public void setState(String state) { this.state = state; fieldNamesToIncludeInToString.add("state"); } + + public GenericPresetVariable getNetworkOffering() { + return networkOffering; + } + + public void setNetworkOffering(GenericPresetVariable networkOffering) { + this.networkOffering = networkOffering; + fieldNamesToIncludeInToString.add("networkOffering"); + } + + public GenericPresetVariable getVpcOffering() { + return vpcOffering; + } + + public void setVpcOffering(GenericPresetVariable vpcOffering) { + this.vpcOffering = vpcOffering; + fieldNamesToIncludeInToString.add("vpcOffering"); + } } diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java index c692cb7c1e73..c86fad2c7c62 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java @@ -31,6 +31,8 @@ import com.cloud.dc.ClusterDetailsVO; import com.cloud.host.HostTagVO; import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.vpc.VpcOfferingVO; +import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.storage.StoragePoolTagVO; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.RoleVO; @@ -188,6 +190,9 @@ public class PresetVariableHelperTest { @Mock BackupOfferingDao backupOfferingDaoMock; + @Mock + VpcOfferingDao vpcOfferingDao; + List runningAndAllocatedVmUsageTypes = Arrays.asList(UsageTypes.RUNNING_VM, UsageTypes.ALLOCATED_VM); List templateAndIsoUsageTypes = Arrays.asList(UsageTypes.TEMPLATE, UsageTypes.ISO); @@ -1339,4 +1344,36 @@ public void testGetSnapshotImageStoreRefNotNull() { Mockito.when(imageStoreDaoMock.findById(1L)).thenReturn(store); Assert.assertNotNull(presetVariableHelperSpy.getSnapshotImageStoreRef(1L, 1L)); } + + @Test + public void getPresetVariableValueNetworkOfferingTestSetValuesAndReturnObject() { + NetworkOfferingVO networkOfferingVoMock = Mockito.mock(NetworkOfferingVO.class); + Mockito.doReturn(networkOfferingVoMock).when(networkOfferingDaoMock).findByIdIncludingRemoved(Mockito.anyLong()); + mockMethodValidateIfObjectIsNull(); + + GenericPresetVariable expected = getGenericPresetVariableForTests(); + Mockito.doReturn(expected.getId()).when(networkOfferingVoMock).getUuid(); + Mockito.doReturn(expected.getName()).when(networkOfferingVoMock).getName(); + + GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueNetworkOffering(1L); + + assertPresetVariableIdAndName(expected, result); + validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result); + } + + @Test + public void getPresetVariableValueVpcOfferingTestSetValuesAndReturnObject() { + VpcOfferingVO vpcOfferingVoMock = Mockito.mock(VpcOfferingVO.class); + Mockito.doReturn(vpcOfferingVoMock).when(vpcOfferingDao).findByIdIncludingRemoved(Mockito.anyLong()); + mockMethodValidateIfObjectIsNull(); + + GenericPresetVariable expected = getGenericPresetVariableForTests(); + Mockito.doReturn(expected.getId()).when(vpcOfferingVoMock).getUuid(); + Mockito.doReturn(expected.getName()).when(vpcOfferingVoMock).getName(); + + GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueVpcOffering(1L); + + assertPresetVariableIdAndName(expected, result); + validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result); + } } From d09628c8e1dcce4db21a18b2b15dfb9c355af988 Mon Sep 17 00:00:00 2001 From: Henrique Sato Date: Mon, 30 Mar 2026 12:23:03 -0300 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Fabricio Duarte --- .../activationrule/presetvariables/PresetVariableHelper.java | 2 +- .../cloudstack/quota/activationrule/presetvariables/Value.java | 2 -- .../presetvariables/PresetVariableHelperTest.java | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java index d04cf295f193..cd87052e878c 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java @@ -814,7 +814,7 @@ protected void loadPresetVariableValueForVpc(UsageVO usageRecord, Value value) { value.setVpcOffering(getPresetVariableValueVpcOffering(vpc.getVpcOfferingId())); } - protected GenericPresetVariable getPresetVariableValueVpcOffering(long vpcOfferingId) { + protected GenericPresetVariable getPresetVariableValueVpcOffering(Long vpcOfferingId) { VpcOfferingVO vpcOfferingVo = vpcOfferingDao.findByIdIncludingRemoved(vpcOfferingId); validateIfObjectIsNull(vpcOfferingVo, vpcOfferingId, "vpc offering"); diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java index 742823b2a7e4..aff2c040e742 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java @@ -268,7 +268,6 @@ public GenericPresetVariable getNetworkOffering() { public void setNetworkOffering(GenericPresetVariable networkOffering) { this.networkOffering = networkOffering; - fieldNamesToIncludeInToString.add("networkOffering"); } public GenericPresetVariable getVpcOffering() { @@ -277,6 +276,5 @@ public GenericPresetVariable getVpcOffering() { public void setVpcOffering(GenericPresetVariable vpcOffering) { this.vpcOffering = vpcOffering; - fieldNamesToIncludeInToString.add("vpcOffering"); } } diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java index 1cbac8abb7b2..eefedf75a016 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java @@ -1308,7 +1308,6 @@ public void getPresetVariableValueNetworkOfferingTestSetValuesAndReturnObject() GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueNetworkOffering(1L); assertPresetVariableIdAndName(expected, result); - validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result); } @Test @@ -1324,6 +1323,5 @@ public void getPresetVariableValueVpcOfferingTestSetValuesAndReturnObject() { GenericPresetVariable result = presetVariableHelperSpy.getPresetVariableValueVpcOffering(1L); assertPresetVariableIdAndName(expected, result); - validateFieldNamesToIncludeInToString(Arrays.asList("id", "name"), result); } } From 61715c42b39ef2ff919bf9311174fe90507ad0f9 Mon Sep 17 00:00:00 2001 From: Henrique Sato Date: Mon, 30 Mar 2026 12:41:20 -0300 Subject: [PATCH 3/3] Add tests --- .../PresetVariableHelperTest.java | 96 ++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java index eefedf75a016..fb093a456790 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java @@ -31,7 +31,9 @@ import com.cloud.dc.ClusterDetailsVO; import com.cloud.host.HostTagVO; import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.dao.NetworkVO; import com.cloud.network.vpc.VpcOfferingVO; +import com.cloud.network.vpc.VpcVO; import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.storage.StoragePoolTagVO; import org.apache.cloudstack.acl.RoleType; @@ -40,7 +42,9 @@ import org.apache.cloudstack.backup.BackupOfferingVO; import org.apache.cloudstack.backup.dao.BackupOfferingDao; import org.apache.cloudstack.quota.constant.QuotaTypes; +import org.apache.cloudstack.quota.dao.NetworkDao; import org.apache.cloudstack.quota.dao.VmTemplateDao; +import org.apache.cloudstack.quota.dao.VpcDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -191,7 +195,13 @@ public class PresetVariableHelperTest { BackupOfferingDao backupOfferingDaoMock; @Mock - VpcOfferingDao vpcOfferingDao; + NetworkDao networkDaoMock; + + @Mock + VpcDao vpcDaoMock; + + @Mock + VpcOfferingDao vpcOfferingDaoMock; List runningAndAllocatedVmUsageTypes = Arrays.asList(UsageTypes.RUNNING_VM, UsageTypes.ALLOCATED_VM); List templateAndIsoUsageTypes = Arrays.asList(UsageTypes.TEMPLATE, UsageTypes.ISO); @@ -228,6 +238,8 @@ private Value getValueForTests() { value.setVmSnapshotType(VMSnapshot.Type.Disk.toString()); value.setComputingResources(getComputingResourcesForTests()); value.setVolumeType(Volume.Type.DATADISK.toString()); + value.setNetworkOffering(getNetworkOfferingForTests()); + value.setVpcOffering(getVpcOfferingForTests()); return value; } @@ -329,6 +341,20 @@ private DiskOfferingPresetVariables getDiskOfferingForTests() { return diskOffering; } + private GenericPresetVariable getNetworkOfferingForTests() { + GenericPresetVariable networkOffering = new GenericPresetVariable(); + networkOffering.setId("network_offering_id"); + networkOffering.setName("network_offering_name"); + return networkOffering; + } + + private GenericPresetVariable getVpcOfferingForTests() { + GenericPresetVariable vpcOffering = new GenericPresetVariable(); + vpcOffering.setId("vpc_offering_id"); + vpcOffering.setName("vpc_offering_name"); + return vpcOffering; + } + private void mockMethodValidateIfObjectIsNull() { Mockito.doNothing().when(presetVariableHelperSpy).validateIfObjectIsNull(Mockito.any(), Mockito.anyLong(), Mockito.anyString()); } @@ -1295,6 +1321,72 @@ public void testGetSnapshotImageStoreRefNotNull() { Assert.assertNotNull(presetVariableHelperSpy.getSnapshotImageStoreRef(1L, 1L)); } + @Test + public void loadPresetVariableValueForNetworkTestRecordIsNotANetworkDoNothing() { + getQuotaTypesForTests(UsageTypes.NETWORK).forEach(type -> { + Mockito.doReturn(type.getKey()).when(usageVoMock).getUsageType(); + presetVariableHelperSpy.loadPresetVariableValueForNetwork(usageVoMock, null); + }); + + Mockito.verifyNoInteractions(networkDaoMock); + } + + @Test + public void loadPresetVariableValueForNetworkTestRecordIsNetworkSetFields() { + Value expected = getValueForTests(); + + NetworkVO networkVoMock = Mockito.mock(NetworkVO.class); + Mockito.doReturn(networkVoMock).when(networkDaoMock).findByIdIncludingRemoved(Mockito.anyLong()); + + mockMethodValidateIfObjectIsNull(); + + Mockito.doReturn(expected.getId()).when(networkVoMock).getUuid(); + Mockito.doReturn(expected.getName()).when(networkVoMock).getName(); + Mockito.doReturn(expected.getState()).when(usageVoMock).getState(); + Mockito.doReturn(expected.getNetworkOffering()).when(presetVariableHelperSpy).getPresetVariableValueNetworkOffering(Mockito.anyLong()); + + Mockito.doReturn(UsageTypes.NETWORK).when(usageVoMock).getUsageType(); + + Value result = new Value(); + presetVariableHelperSpy.loadPresetVariableValueForNetwork(usageVoMock, result); + + assertPresetVariableIdAndName(expected, result); + Assert.assertEquals(expected.getState(), result.getState()); + Assert.assertEquals(expected.getNetworkOffering(), result.getNetworkOffering()); + } + + @Test + public void loadPresetVariableValueForVpcTestRecordIsNotAVpcDoNothing() { + getQuotaTypesForTests(UsageTypes.VPC).forEach(type -> { + Mockito.doReturn(type.getKey()).when(usageVoMock).getUsageType(); + presetVariableHelperSpy.loadPresetVariableValueForVpc(usageVoMock, null); + }); + + Mockito.verifyNoInteractions(networkDaoMock); + } + + @Test + public void loadPresetVariableValueForVpcTestRecordIsVpcSetFields() { + Value expected = getValueForTests(); + + VpcVO networkVoMock = Mockito.mock(VpcVO.class); + Mockito.doReturn(networkVoMock).when(vpcDaoMock).findByIdIncludingRemoved(Mockito.anyLong()); + + mockMethodValidateIfObjectIsNull(); + + Mockito.doReturn(expected.getId()).when(networkVoMock).getUuid(); + Mockito.doReturn(expected.getName()).when(networkVoMock).getName(); + Mockito.doReturn(expected.getVpcOffering()).when(presetVariableHelperSpy).getPresetVariableValueVpcOffering(Mockito.anyLong()); + + Mockito.doReturn(UsageTypes.VPC).when(usageVoMock).getUsageType(); + + Value result = new Value(); + presetVariableHelperSpy.loadPresetVariableValueForVpc(usageVoMock, result); + + assertPresetVariableIdAndName(expected, result); + Assert.assertEquals(expected.getVpcOffering(), result.getVpcOffering()); + } + @Test public void getPresetVariableValueNetworkOfferingTestSetValuesAndReturnObject() { NetworkOfferingVO networkOfferingVoMock = Mockito.mock(NetworkOfferingVO.class); @@ -1313,7 +1405,7 @@ public void getPresetVariableValueNetworkOfferingTestSetValuesAndReturnObject() @Test public void getPresetVariableValueVpcOfferingTestSetValuesAndReturnObject() { VpcOfferingVO vpcOfferingVoMock = Mockito.mock(VpcOfferingVO.class); - Mockito.doReturn(vpcOfferingVoMock).when(vpcOfferingDao).findByIdIncludingRemoved(Mockito.anyLong()); + Mockito.doReturn(vpcOfferingVoMock).when(vpcOfferingDaoMock).findByIdIncludingRemoved(Mockito.anyLong()); mockMethodValidateIfObjectIsNull(); GenericPresetVariable expected = getGenericPresetVariableForTests();