This is an automated email from the ASF dual-hosted git repository.

DaanHoogland pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new c07f1fd5d29 Number of running and stopped VMs as preset variables for 
`Network` type Quota tariffs (#11689)
c07f1fd5d29 is described below

commit c07f1fd5d29ab2c6ba3a419dbf6d21b0a4f3900b
Author: Henrique Sato <[email protected]>
AuthorDate: Fri May 1 06:54:40 2026 -0300

    Number of running and stopped VMs as preset variables for `Network` type 
Quota tariffs (#11689)
    
    Co-authored-by: Fabricio Duarte <[email protected]>
---
 .../presetvariables/PresetVariableHelper.java      | 14 +++++-
 .../presetvariables/ResourceCounting.java          | 52 ++++++++++++++++++++++
 .../activationrule/presetvariables/Value.java      | 11 +++++
 .../presetvariables/PresetVariableHelperTest.java  | 37 +++++++++++++--
 .../api/response/QuotaResponseBuilderImpl.java     |  3 +-
 5 files changed, 112 insertions(+), 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 cd87052e878..23020292027 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
@@ -35,6 +35,7 @@ import com.cloud.network.vpc.VpcVO;
 import javax.inject.Inject;
 
 import com.cloud.storage.StoragePoolTagVO;
+import com.cloud.vm.VirtualMachine;
 import org.apache.cloudstack.acl.RoleVO;
 import org.apache.cloudstack.acl.dao.RoleDao;
 import org.apache.cloudstack.backup.BackupOfferingVO;
@@ -783,10 +784,21 @@ public class PresetVariableHelper {
         value.setId(network.getUuid());
         value.setName(network.getName());
         value.setState(usageRecord.getState());
-
+        
value.setResourceCounting(getPresetVariableValueNetworkResourceCounting(networkId));
         
value.setNetworkOffering(getPresetVariableValueNetworkOffering(network.getNetworkOfferingId()));
     }
 
+    protected ResourceCounting 
getPresetVariableValueNetworkResourceCounting(Long networkId) {
+        ResourceCounting resourceCounting = new ResourceCounting();
+        List<VMInstanceVO> vmInstancesVO = 
vmInstanceDao.listNonRemovedVmsByTypeAndNetwork(networkId, 
VirtualMachine.Type.User);
+        int runningVms = (int) vmInstancesVO.stream().filter(vm -> 
vm.getState().equals(VirtualMachine.State.Running)).count();
+        int stoppedVms = (int) vmInstancesVO.stream().filter(vm -> 
vm.getState().equals(VirtualMachine.State.Stopped)).count();
+
+        resourceCounting.setRunningVms(runningVms);
+        resourceCounting.setStoppedVms(stoppedVms);
+        return resourceCounting;
+    }
+
     protected GenericPresetVariable getPresetVariableValueNetworkOffering(Long 
networkOfferingId) {
         NetworkOfferingVO networkOfferingVo = 
networkOfferingDao.findByIdIncludingRemoved(networkOfferingId);
         validateIfObjectIsNull(networkOfferingVo, networkOfferingId, "network 
offering");
diff --git 
a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ResourceCounting.java
 
b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ResourceCounting.java
new file mode 100644
index 00000000000..75049c3486a
--- /dev/null
+++ 
b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ResourceCounting.java
@@ -0,0 +1,52 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package org.apache.cloudstack.quota.activationrule.presetvariables;
+
+
+import org.apache.cloudstack.quota.constant.QuotaTypes;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+public class ResourceCounting {
+
+    @PresetVariableDefinition(description = "The number of running user 
instances.", supportedTypes = {QuotaTypes.NETWORK})
+    private int runningVms;
+    @PresetVariableDefinition(description = "The number of stopped user 
instances.", supportedTypes = {QuotaTypes.NETWORK})
+    private int stoppedVms;
+
+    public int getRunningVms() {
+        return runningVms;
+    }
+
+    public void setRunningVms(int runningVms) {
+        this.runningVms = runningVms;
+    }
+
+    public int getStoppedVms() {
+        return stoppedVms;
+    }
+
+    public void setStoppedVms(int stoppedVms) {
+        this.stoppedVms = stoppedVms;
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, 
ToStringStyle.JSON_STYLE);
+    }
+}
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 aff2c040e74..286fe5c60fd 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
@@ -84,6 +84,9 @@ public class Value extends GenericPresetVariable {
     @PresetVariableDefinition(description = "Backup offering of the backup.", 
supportedTypes = {QuotaTypes.BACKUP})
     private BackupOffering backupOffering;
 
+    @PresetVariableDefinition(description = "The amount of resources of the 
usage type.")
+    private ResourceCounting resourceCounting;
+
     @PresetVariableDefinition(description = "The hypervisor where the resource 
was deployed. Values can be: XenServer, KVM, VMware, Hyperv, BareMetal, Ovm, 
Ovm3 and LXC.",
             supportedTypes = {QuotaTypes.RUNNING_VM, QuotaTypes.ALLOCATED_VM, 
QuotaTypes.VM_SNAPSHOT, QuotaTypes.SNAPSHOT})
     private String hypervisorType;
@@ -262,6 +265,14 @@ public class Value extends GenericPresetVariable {
         this.state = state;
     }
 
+    public ResourceCounting getResourceCounting() {
+        return resourceCounting;
+    }
+
+    public void setResourceCounting(ResourceCounting resourceCounting) {
+        this.resourceCounting = resourceCounting;
+    }
+
     public GenericPresetVariable getNetworkOffering() {
         return networkOffering;
     }
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 fb093a45679..bcdbc3b46ce 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,11 +31,13 @@ import com.cloud.dc.ClusterDetailsDao;
 import com.cloud.dc.ClusterDetailsVO;
 import com.cloud.host.HostTagVO;
 import com.cloud.hypervisor.Hypervisor;
+import com.cloud.network.Network;
 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 com.cloud.vm.VirtualMachine;
 import org.apache.cloudstack.acl.RoleType;
 import org.apache.cloudstack.acl.RoleVO;
 import org.apache.cloudstack.acl.dao.RoleDao;
@@ -238,6 +240,8 @@ public class PresetVariableHelperTest {
         value.setVmSnapshotType(VMSnapshot.Type.Disk.toString());
         value.setComputingResources(getComputingResourcesForTests());
         value.setVolumeType(Volume.Type.DATADISK.toString());
+        value.setState(Network.State.Implemented.toString());
+        value.setResourceCounting(getResourceCountingForTests());
         value.setNetworkOffering(getNetworkOfferingForTests());
         value.setVpcOffering(getVpcOfferingForTests());
         return value;
@@ -276,6 +280,13 @@ public class PresetVariableHelperTest {
         return configuration;
     }
 
+    private ResourceCounting getResourceCountingForTests() {
+        ResourceCounting resourceCounting = new ResourceCounting();
+        resourceCounting.setRunningVms(1);
+        resourceCounting.setStoppedVms(1);
+        return resourceCounting;
+    }
+
     private List<HostTagVO> getHostTagsForTests() {
         return Arrays.asList(new HostTagVO(1, "tag1", false), new HostTagVO(1, 
"tag2", false));
     }
@@ -1343,8 +1354,8 @@ public class PresetVariableHelperTest {
         Mockito.doReturn(expected.getId()).when(networkVoMock).getUuid();
         Mockito.doReturn(expected.getName()).when(networkVoMock).getName();
         Mockito.doReturn(expected.getState()).when(usageVoMock).getState();
+        
Mockito.doReturn(expected.getResourceCounting()).when(presetVariableHelperSpy).getPresetVariableValueNetworkResourceCounting(Mockito.anyLong());
         
Mockito.doReturn(expected.getNetworkOffering()).when(presetVariableHelperSpy).getPresetVariableValueNetworkOffering(Mockito.anyLong());
-
         Mockito.doReturn(UsageTypes.NETWORK).when(usageVoMock).getUsageType();
 
         Value result = new Value();
@@ -1352,7 +1363,27 @@ public class PresetVariableHelperTest {
 
         assertPresetVariableIdAndName(expected, result);
         Assert.assertEquals(expected.getState(), result.getState());
-        Assert.assertEquals(expected.getNetworkOffering(), 
result.getNetworkOffering());
+        Assert.assertEquals(expected.getResourceCounting(), 
result.getResourceCounting());
+    }
+
+    @Test
+    public void 
getPresetVariableValueNetworkResourceCountingTestSetValueAndReturnObject() {
+        VMInstanceVO vmInstanceVoMock1 = Mockito.spy(VMInstanceVO.class);
+        vmInstanceVoMock1.setState(VirtualMachine.State.Stopped);
+
+        VMInstanceVO vmInstanceVoMock2 = Mockito.spy(VMInstanceVO.class);
+        vmInstanceVoMock2.setState(VirtualMachine.State.Running);
+
+        Mockito.doReturn(List.of(vmInstanceVoMock1, 
vmInstanceVoMock2)).when(vmInstanceDaoMock).listNonRemovedVmsByTypeAndNetwork(Mockito.anyLong(),
 Mockito.any());
+
+        mockMethodValidateIfObjectIsNull();
+
+        ResourceCounting expected = getResourceCountingForTests();
+
+        ResourceCounting result = 
presetVariableHelperSpy.getPresetVariableValueNetworkResourceCounting(1L);
+
+        Assert.assertEquals(expected.getRunningVms(), result.getRunningVms());
+        Assert.assertEquals(expected.getStoppedVms(), result.getStoppedVms());
     }
 
     @Test
@@ -1362,7 +1393,7 @@ public class PresetVariableHelperTest {
             presetVariableHelperSpy.loadPresetVariableValueForVpc(usageVoMock, 
null);
         });
 
-        Mockito.verifyNoInteractions(networkDaoMock);
+        Mockito.verifyNoInteractions(vpcDaoMock);
     }
 
     @Test
diff --git 
a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java
 
b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java
index 173c0723731..c919bb5887c 100644
--- 
a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java
+++ 
b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java
@@ -98,6 +98,7 @@ import 
org.apache.cloudstack.quota.activationrule.presetvariables.ComputingResou
 import 
org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
 import 
org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableDefinition;
 import 
org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
+import 
org.apache.cloudstack.quota.activationrule.presetvariables.ResourceCounting;
 import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
 import org.apache.cloudstack.quota.constant.QuotaConfig;
 import org.apache.cloudstack.quota.constant.QuotaTypes;
@@ -185,7 +186,7 @@ public class QuotaResponseBuilderImpl implements 
QuotaResponseBuilder {
     private VolumeDao volumeDao;
 
 
-    private final Class<?>[] assignableClasses = {GenericPresetVariable.class, 
ComputingResources.class};
+    private final Class<?>[] assignableClasses = {GenericPresetVariable.class, 
ComputingResources.class, ResourceCounting.class};
 
     private Set<Account.Type> accountTypesThatCanListAllQuotaSummaries = 
Sets.newHashSet(Account.Type.ADMIN, Account.Type.DOMAIN_ADMIN);
 

Reply via email to