From 452fa434e0aadef66d2ffcd7518a1e568fbc1ad8 Mon Sep 17 00:00:00 2001 From: Ramgopal Nagaboina Date: Tue, 15 Sep 2026 13:46:01 -0400 Subject: [PATCH] test: deploy planner and metrics smoke test VMs in the test's own network test_vm_deployment_planner.py and the VM tests in test_metrics_api.py deploy their VMs as the admin with no network, so they land in the admin account's shared network. When that network's router is stuck, or an earlier test has left the network in Shutdown, every VM in these files fails to start and the smoke run reports failures that have nothing to do with the change under test. Create an L2 network owned by the test account and deploy into it (in advanced zones only for the metrics test, which also runs on basic zones), and wait for usage history stats to show up instead of sleeping a fixed two minutes. --- test/integration/smoke/test_metrics_api.py | 51 +++++++++++++++---- .../smoke/test_vm_deployment_planner.py | 30 +++++++++++ 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/test/integration/smoke/test_metrics_api.py b/test/integration/smoke/test_metrics_api.py index ab2644fc1aad..436d61e48187 100644 --- a/test/integration/smoke/test_metrics_api.py +++ b/test/integration/smoke/test_metrics_api.py @@ -68,6 +68,23 @@ def setUpClass(cls): domainid=cls.domain.id ) cls._cleanup.append(cls.account) + cls.network = None + if cls.zone.networktype.lower() == 'advanced': + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["l2-network_offering"] + ) + cls._cleanup.append(cls.network_offering) + cls.network_offering.update(cls.apiclient, state="enabled") + cls.network = Network.create( + cls.apiclient, + cls.services["l2-network"], + accountid=cls.account.name, + domainid=cls.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls._cleanup.append(cls.network) cls.hypervisorNotSupported = True if cls.hypervisor.lower() != 'simulator': cls.hypervisorNotSupported = False @@ -207,6 +224,9 @@ def run_list_vm_metrics_test(self, is_user): self.small_virtual_machine = VirtualMachine.create( apiclient, self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + networkids=[self.network.id] if self.network else None, serviceofferingid=self.service_offering.id, templateid=self.template.id, zoneid=self.zone.id @@ -466,19 +486,19 @@ def test_list_vms_metrics_history(self): self.small_virtual_machine = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + networkids=[self.network.id] if self.network else None, serviceofferingid=self.service_offering.id, templateid=self.template.id, zoneid=self.zone.id ) self.cleanup.append(self.small_virtual_machine) - # Wait for 2 minutes - time.sleep(120) - cmd = listVirtualMachinesUsageHistory.listVirtualMachinesUsageHistoryCmd() cmd.id = self.small_virtual_machine.id - result = self.apiclient.listVirtualMachinesUsageHistory(cmd)[0] + result = self.wait_for_stats(lambda: self.apiclient.listVirtualMachinesUsageHistory(cmd)) self.assertEqual(result.id, self.small_virtual_machine.id) self.assertTrue(hasattr(result, 'stats')) @@ -510,6 +530,9 @@ def test_list_volumes_metrics_history(self): self.small_virtual_machine = VirtualMachine.create( self.apiclient, self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + networkids=[self.network.id] if self.network else None, serviceofferingid=self.service_offering.id, templateid=self.template.id, zoneid=self.zone.id @@ -522,17 +545,15 @@ def test_list_volumes_metrics_history(self): self.skipTest("Skipping test because volume metrics doesn't work on hypervisor\ %s, %s" % (currentHost.hypervisor, currentHost.hypervisorversion)) - # Wait for 2 minutes - time.sleep(120) - volume = Volume.list( self.apiclient, - virtualmachineid=self.small_virtual_machine.id)[0] + virtualmachineid=self.small_virtual_machine.id, + listall=True)[0] cmd = listVolumesUsageHistory.listVolumesUsageHistoryCmd() cmd.id = volume.id - result = self.apiclient.listVolumesUsageHistory(cmd)[0] + result = self.wait_for_stats(lambda: self.apiclient.listVolumesUsageHistory(cmd)) self.assertEqual(result.id, volume.id) self.assertTrue(hasattr(result, 'stats')) self.assertTrue(type(result.stats) == list and len(result.stats) > 0) @@ -547,6 +568,18 @@ def test_list_volumes_metrics_history(self): return + def wait_for_stats(self, list_usage_history): + def stats_collected(): + response = list_usage_history() + if isinstance(response, list) and len(response) > 0 and \ + isinstance(getattr(response[0], 'stats', None), list) and len(response[0].stats) > 0: + return True, response[0] + return False, None + + collected, result = wait_until(15, 20, stats_collected) + self.assertTrue(collected, "No usage history stats were collected within 5 minutes") + return result + def validate_vm_stats(self, stats): self.assertTrue(hasattr(stats, 'cpuused')) self.assertTrue(hasattr(stats, 'diskiopstotal')) diff --git a/test/integration/smoke/test_vm_deployment_planner.py b/test/integration/smoke/test_vm_deployment_planner.py index e8d24cbf31e5..db2586043dfa 100644 --- a/test/integration/smoke/test_vm_deployment_planner.py +++ b/test/integration/smoke/test_vm_deployment_planner.py @@ -21,6 +21,8 @@ from marvin.cloudstackTestCase import cloudstackTestCase from marvin.lib.base import (Account, ServiceOffering, + NetworkOffering, + Network, Host, Pod, Cluster) from marvin.lib.common import (get_domain, get_zone, @@ -61,10 +63,33 @@ def setUpClass(cls): cls.service_offering ] + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["l2-network_offering"] + ) + cls._cleanup.append(cls.network_offering) + cls.network_offering.update(cls.apiclient, state="enabled") + + cls.network = Network.create( + cls.apiclient, + cls.services["l2-network"], + accountid=cls.account.name, + domainid=cls.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls._cleanup.append(cls.network) + @classmethod def tearDownClass(cls): super(TestVMDeploymentPlanner, cls).tearDownClass() + def set_owner(self, cmd): + cmd.account = self.account.name + cmd.domainid = self.account.domainid + cmd.networkids = [self.network.id] + return cmd + def deploy_vm(self, destination_id): cmd = deployVirtualMachine.deployVirtualMachineCmd() template = get_template( @@ -75,6 +100,7 @@ def deploy_vm(self, destination_id): cmd.templateid = template.id cmd.serviceofferingid = self.service_offering.id cmd.hostid = destination_id + self.set_owner(cmd) return self.apiclient.deployVirtualMachine(cmd) def destroy_vm(self, vm_id): @@ -123,6 +149,7 @@ def test_02_deploy_vm_on_specific_cluster(self): cmd.serviceofferingid = self.service_offering.id cmd.templateid = template.id cmd.clusterid = target_id + self.set_owner(cmd) vm = self.apiclient.deployVirtualMachine(cmd) vm_host = Host.list(self.apiclient, @@ -160,6 +187,7 @@ def test_03_deploy_vm_on_specific_pod(self): cmd.templateid = template.id cmd.podid = target_pod.id + self.set_owner(cmd) vm = self.apiclient.deployVirtualMachine(cmd) vm_host = Host.list(self.apiclient, @@ -200,6 +228,7 @@ def test_04_deploy_vm_on_host_override_pod_and_cluster(self): cmd.podid = pod.id cmd.clusterid = clusters[1].id if len(clusters) > 1 else clusters[0].id cmd.hostid = host.id + self.set_owner(cmd) vm = self.apiclient.deployVirtualMachine(cmd) @@ -235,6 +264,7 @@ def test_05_deploy_vm_on_cluster_override_pod(self): # Add optional deployment params cmd.podid = pod.id cmd.clusterid = clusters[0].id + self.set_owner(cmd) vm = self.apiclient.deployVirtualMachine(cmd)