You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by da...@apache.org on 2018/03/14 18:21:29 UTC
[cloudstack] branch 4.11 updated: CLOUDSTACK-10321: CPU Cap for KVM
(#2482)
This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 4.11
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.11 by this push:
new 74db647 CLOUDSTACK-10321: CPU Cap for KVM (#2482)
74db647 is described below
commit 74db647dbbaa224ffa5667a3203d53f48532d072
Author: Nicolas Vazquez <ni...@gmail.com>
AuthorDate: Wed Mar 14 15:21:24 2018 -0300
CLOUDSTACK-10321: CPU Cap for KVM (#2482)
---
.../com/cloud/agent/api/to/VirtualMachineTO.java | 10 ++
.../kvm/resource/LibvirtComputingResource.java | 28 ++++
.../hypervisor/kvm/resource/LibvirtVMDef.java | 27 ++++
.../kvm/resource/LibvirtComputingResourceTest.java | 39 +++++
server/src/com/cloud/hypervisor/KVMGuru.java | 50 ++++++
server/test/com/cloud/hypervisor/KVMGuruTest.java | 99 ++++++++++++
test/integration/smoke/test_service_offerings.py | 169 ++++++++++++++++++++-
7 files changed, 419 insertions(+), 3 deletions(-)
diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
index f982e4b..84a6bf5 100644
--- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
+++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java
@@ -70,6 +70,8 @@ public class VirtualMachineTO {
String configDriveIsoRootFolder = null;
String configDriveIsoFile = null;
+ Double cpuQuotaPercentage = null;
+
Map<String, String> guestOsDetails = new HashMap<String, String>();
public VirtualMachineTO(long id, String instanceName, VirtualMachine.Type type, int cpus, Integer speed, long minRam, long maxRam, BootloaderType bootloader,
@@ -340,4 +342,12 @@ public class VirtualMachineTO {
public void setGuestOsDetails(Map<String, String> guestOsDetails) {
this.guestOsDetails = guestOsDetails;
}
+
+ public Double getCpuQuotaPercentage() {
+ return cpuQuotaPercentage;
+ }
+
+ public void setCpuQuotaPercentage(Double cpuQuotaPercentage) {
+ this.cpuQuotaPercentage = cpuQuotaPercentage;
+ }
}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index 9b7fb2e..dd039e5 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -1984,6 +1984,31 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return uuid;
}
+ /**
+ * Set quota and period tags on 'ctd' when CPU limit use is set
+ */
+ protected void setQuotaAndPeriod(VirtualMachineTO vmTO, CpuTuneDef ctd) {
+ if (vmTO.getLimitCpuUse() && vmTO.getCpuQuotaPercentage() != null) {
+ Double cpuQuotaPercentage = vmTO.getCpuQuotaPercentage();
+ int period = CpuTuneDef.DEFAULT_PERIOD;
+ int quota = (int) (period * cpuQuotaPercentage);
+ if (quota < CpuTuneDef.MIN_QUOTA) {
+ s_logger.info("Calculated quota (" + quota + ") below the minimum (" + CpuTuneDef.MIN_QUOTA + ") for VM domain " + vmTO.getUuid() + ", setting it to minimum " +
+ "and calculating period instead of using the default");
+ quota = CpuTuneDef.MIN_QUOTA;
+ period = (int) ((double) quota / cpuQuotaPercentage);
+ if (period > CpuTuneDef.MAX_PERIOD) {
+ s_logger.info("Calculated period (" + period + ") exceeds the maximum (" + CpuTuneDef.MAX_PERIOD +
+ "), setting it to the maximum");
+ period = CpuTuneDef.MAX_PERIOD;
+ }
+ }
+ ctd.setQuota(quota);
+ ctd.setPeriod(period);
+ s_logger.info("Setting quota=" + quota + ", period=" + period + " to VM domain " + vmTO.getUuid());
+ }
+ }
+
public LibvirtVMDef createVMFromSpec(final VirtualMachineTO vmTO) {
final LibvirtVMDef vm = new LibvirtVMDef();
vm.setDomainName(vmTO.getName());
@@ -2059,6 +2084,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
} else {
ctd.setShares(vmTO.getCpus() * vmTO.getSpeed());
}
+
+ setQuotaAndPeriod(vmTO, ctd);
+
vm.addComp(ctd);
}
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
index 90674eb..7c12c07 100644
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java
@@ -1171,6 +1171,11 @@ public class LibvirtVMDef {
public static class CpuTuneDef {
private int _shares = 0;
+ private int quota = 0;
+ private int period = 0;
+ static final int DEFAULT_PERIOD = 10000;
+ static final int MIN_QUOTA = 1000;
+ static final int MAX_PERIOD = 1000000;
public void setShares(int shares) {
_shares = shares;
@@ -1180,6 +1185,22 @@ public class LibvirtVMDef {
return _shares;
}
+ public int getQuota() {
+ return quota;
+ }
+
+ public void setQuota(int quota) {
+ this.quota = quota;
+ }
+
+ public int getPeriod() {
+ return period;
+ }
+
+ public void setPeriod(int period) {
+ this.period = period;
+ }
+
@Override
public String toString() {
StringBuilder cpuTuneBuilder = new StringBuilder();
@@ -1187,6 +1208,12 @@ public class LibvirtVMDef {
if (_shares > 0) {
cpuTuneBuilder.append("<shares>" + _shares + "</shares>\n");
}
+ if (quota > 0) {
+ cpuTuneBuilder.append("<quota>" + quota + "</quota>\n");
+ }
+ if (period > 0) {
+ cpuTuneBuilder.append("<period>" + period + "</period>\n");
+ }
cpuTuneBuilder.append("</cputune>\n");
return cpuTuneBuilder.toString();
}
diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
index 2fd7692..795b961 100644
--- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
+++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java
@@ -38,6 +38,7 @@ import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
+import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.CpuTuneDef;
import org.apache.commons.lang.SystemUtils;
import org.joda.time.Duration;
import org.junit.Assert;
@@ -184,6 +185,8 @@ public class LibvirtComputingResourceTest {
@Mock
private LibvirtComputingResource libvirtComputingResource;
+ @Mock
+ VirtualMachineTO vmTO;
String hyperVisorType = "kvm";
Random random = new Random();
@@ -5152,4 +5155,40 @@ public class LibvirtComputingResourceTest {
when(domainMock.memoryStats(2)).thenReturn(mem);
return domainMock;
}
+
+ @Test
+ public void testSetQuotaAndPeriod() {
+ double pct = 0.33d;
+ Mockito.when(vmTO.getLimitCpuUse()).thenReturn(true);
+ Mockito.when(vmTO.getCpuQuotaPercentage()).thenReturn(pct);
+ CpuTuneDef cpuTuneDef = new CpuTuneDef();
+ final LibvirtComputingResource lcr = new LibvirtComputingResource();
+ lcr.setQuotaAndPeriod(vmTO, cpuTuneDef);
+ Assert.assertEquals((int) (CpuTuneDef.DEFAULT_PERIOD * pct), cpuTuneDef.getQuota());
+ Assert.assertEquals(CpuTuneDef.DEFAULT_PERIOD, cpuTuneDef.getPeriod());
+ }
+
+ @Test
+ public void testSetQuotaAndPeriodNoCpuLimitUse() {
+ double pct = 0.33d;
+ Mockito.when(vmTO.getLimitCpuUse()).thenReturn(false);
+ Mockito.when(vmTO.getCpuQuotaPercentage()).thenReturn(pct);
+ CpuTuneDef cpuTuneDef = new CpuTuneDef();
+ final LibvirtComputingResource lcr = new LibvirtComputingResource();
+ lcr.setQuotaAndPeriod(vmTO, cpuTuneDef);
+ Assert.assertEquals(0, cpuTuneDef.getQuota());
+ Assert.assertEquals(0, cpuTuneDef.getPeriod());
+ }
+
+ @Test
+ public void testSetQuotaAndPeriodMinQuota() {
+ double pct = 0.01d;
+ Mockito.when(vmTO.getLimitCpuUse()).thenReturn(true);
+ Mockito.when(vmTO.getCpuQuotaPercentage()).thenReturn(pct);
+ CpuTuneDef cpuTuneDef = new CpuTuneDef();
+ final LibvirtComputingResource lcr = new LibvirtComputingResource();
+ lcr.setQuotaAndPeriod(vmTO, cpuTuneDef);
+ Assert.assertEquals(CpuTuneDef.MIN_QUOTA, cpuTuneDef.getQuota());
+ Assert.assertEquals((int) (CpuTuneDef.MIN_QUOTA / pct), cpuTuneDef.getPeriod());
+ }
}
diff --git a/server/src/com/cloud/hypervisor/KVMGuru.java b/server/src/com/cloud/hypervisor/KVMGuru.java
index 1a476a2..df6038d 100644
--- a/server/src/com/cloud/hypervisor/KVMGuru.java
+++ b/server/src/com/cloud/hypervisor/KVMGuru.java
@@ -28,11 +28,16 @@ import com.cloud.storage.GuestOSVO;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.GuestOSHypervisorDao;
import com.cloud.utils.Pair;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.log4j.Logger;
import javax.inject.Inject;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.util.Map;
public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru {
@@ -43,6 +48,8 @@ public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru {
@Inject
HostDao _hostDao;
+ public static final Logger s_logger = Logger.getLogger(KVMGuru.class);
+
@Override
public HypervisorType getHypervisorType() {
return HypervisorType.KVM;
@@ -52,10 +59,53 @@ public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru {
super();
}
+ /**
+ * Retrieve host max CPU speed
+ */
+ protected double getHostCPUSpeed(HostVO host) {
+ return host.getSpeed();
+ }
+
+ protected double getVmSpeed(VirtualMachineTO to) {
+ return to.getMaxSpeed() != null ? to.getMaxSpeed() : to.getSpeed();
+ }
+
+ /**
+ * Set VM CPU quota percentage with respect to host CPU on 'to' if CPU limit option is set
+ * @param to vm to
+ * @param vmProfile vm profile
+ */
+ protected void setVmQuotaPercentage(VirtualMachineTO to, VirtualMachineProfile vmProfile) {
+ if (to.getLimitCpuUse()) {
+ VirtualMachine vm = vmProfile.getVirtualMachine();
+ HostVO host = _hostDao.findById(vm.getHostId());
+ if (host == null) {
+ throw new CloudRuntimeException("Host with id: " + vm.getHostId() + " not found");
+ }
+ s_logger.debug("Limiting CPU usage for VM: " + vm.getUuid() + " on host: " + host.getUuid());
+ double hostMaxSpeed = getHostCPUSpeed(host);
+ double maxSpeed = getVmSpeed(to);
+ try {
+ BigDecimal percent = new BigDecimal(maxSpeed / hostMaxSpeed);
+ percent = percent.setScale(2, RoundingMode.HALF_DOWN);
+ if (percent.compareTo(new BigDecimal(1)) == 1) {
+ s_logger.debug("VM " + vm.getUuid() + " CPU MHz exceeded host " + host.getUuid() + " CPU MHz, limiting VM CPU to the host maximum");
+ percent = new BigDecimal(1);
+ }
+ to.setCpuQuotaPercentage(percent.doubleValue());
+ s_logger.debug("Host: " + host.getUuid() + " max CPU speed = " + hostMaxSpeed + "MHz, VM: " + vm.getUuid() +
+ "max CPU speed = " + maxSpeed + "MHz. Setting CPU quota percentage as: " + percent.doubleValue());
+ } catch (NumberFormatException e) {
+ s_logger.error("Error calculating VM: " + vm.getUuid() + " quota percentage, it wll not be set. Error: " + e.getMessage(), e);
+ }
+ }
+ }
+
@Override
public VirtualMachineTO implement(VirtualMachineProfile vm) {
VirtualMachineTO to = toVirtualMachineTO(vm);
+ setVmQuotaPercentage(to, vm);
// Determine the VM's OS description
GuestOSVO guestOS = _guestOsDao.findByIdIncludingRemoved(vm.getVirtualMachine().getGuestOSId());
diff --git a/server/test/com/cloud/hypervisor/KVMGuruTest.java b/server/test/com/cloud/hypervisor/KVMGuruTest.java
new file mode 100644
index 0000000..597e20f
--- /dev/null
+++ b/server/test/com/cloud/hypervisor/KVMGuruTest.java
@@ -0,0 +1,99 @@
+// 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 com.cloud.hypervisor;
+
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class KVMGuruTest {
+
+ @Mock
+ HostDao hostDao;
+
+ @Spy
+ @InjectMocks
+ private KVMGuru guru = new KVMGuru();
+
+ @Mock
+ VirtualMachineTO vmTO;
+ @Mock
+ VirtualMachineProfile vmProfile;
+ @Mock
+ VirtualMachine vm;
+ @Mock
+ HostVO host;
+
+ private static final long hostId = 1l;
+
+ @Before
+ public void setup() {
+ Mockito.when(vmTO.getLimitCpuUse()).thenReturn(true);
+ Mockito.when(vmProfile.getVirtualMachine()).thenReturn(vm);
+ Mockito.when(vm.getHostId()).thenReturn(hostId);
+ Mockito.when(hostDao.findById(hostId)).thenReturn(host);
+ Mockito.when(host.getCpus()).thenReturn(3);
+ Mockito.when(host.getSpeed()).thenReturn(1995l);
+ Mockito.when(vmTO.getMaxSpeed()).thenReturn(500);
+ }
+
+ @Test
+ public void testSetVmQuotaPercentage() {
+ guru.setVmQuotaPercentage(vmTO, vmProfile);
+ Mockito.verify(vmTO).setCpuQuotaPercentage(Mockito.anyDouble());
+ }
+
+ @Test(expected = CloudRuntimeException.class)
+ public void testSetVmQuotaPercentageNullHost() {
+ Mockito.when(hostDao.findById(hostId)).thenReturn(null);
+ guru.setVmQuotaPercentage(vmTO, vmProfile);
+ }
+
+ @Test
+ public void testSetVmQuotaPercentageZeroDivision() {
+ Mockito.when(host.getSpeed()).thenReturn(0l);
+ guru.setVmQuotaPercentage(vmTO, vmProfile);
+ Mockito.verify(vmTO, Mockito.never()).setCpuQuotaPercentage(Mockito.anyDouble());
+ }
+
+ @Test
+ public void testSetVmQuotaPercentageNotCPULimit() {
+ Mockito.when(vmTO.getLimitCpuUse()).thenReturn(false);
+ guru.setVmQuotaPercentage(vmTO, vmProfile);
+ Mockito.verify(vmProfile, Mockito.never()).getVirtualMachine();
+ Mockito.verify(vmTO, Mockito.never()).setCpuQuotaPercentage(Mockito.anyDouble());
+ }
+
+ @Test
+ public void testSetVmQuotaPercentageOverProvision() {
+ Mockito.when(vmTO.getMaxSpeed()).thenReturn(3000);
+ guru.setVmQuotaPercentage(vmTO, vmProfile);
+ Mockito.verify(vmTO).setCpuQuotaPercentage(1d);
+ }
+}
\ No newline at end of file
diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py
index 50c69d7..2788d0e 100644
--- a/test/integration/smoke/test_service_offerings.py
+++ b/test/integration/smoke/test_service_offerings.py
@@ -31,9 +31,13 @@ from marvin.lib.common import (list_service_offering,
list_virtual_machines,
get_domain,
get_zone,
- get_test_template)
+ get_template,
+ list_hosts)
from nose.plugins.attrib import attr
+import time
+from marvin.sshClient import SshClient
+from marvin.lib.decoratorGenerators import skipTestIf
_multiprocess_shared_ = True
@@ -163,13 +167,13 @@ class TestServiceOfferings(cloudstackTestCase):
cls.apiclient,
cls.services["service_offerings"]["tiny"]
)
- template = get_test_template(
+ template = get_template(
cls.apiclient,
cls.zone.id,
cls.hypervisor
)
if template == FAILED:
- assert False, "get_test_template() failed to return template"
+ assert False, "get_template() failed to return template"
# Set Zones and disk offerings
cls.services["small"]["zoneid"] = cls.zone.id
@@ -400,3 +404,162 @@ class TestServiceOfferings(cloudstackTestCase):
"Check Memory(kb) for small offering"
)
return
+
+class TestCpuCapServiceOfferings(cloudstackTestCase):
+
+ def setUp(self):
+ self.apiclient = self.testClient.getApiClient()
+ self.dbclient = self.testClient.getDbConnection()
+ self.cleanup = []
+
+ def tearDown(self):
+ try:
+ # Clean up, terminate the created templates
+ cleanup_resources(self.apiclient, self.cleanup)
+
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+
+ return
+
+ def get_ssh_client(self, id, public_ip, username, password, retries):
+ """ Setup ssh client connection and return connection
+ vm requires attributes public_ip, public_port, username, password """
+
+ try:
+ ssh_client = SshClient(
+ public_ip,
+ 22,
+ username,
+ password,
+ retries)
+
+ except Exception as e:
+ self.fail("Unable to create ssh connection: " % e)
+
+ self.assertIsNotNone(
+ ssh_client, "Failed to setup ssh connection to host=%s on public_ip=%s" % (id, public_ip))
+
+ return ssh_client
+
+ @classmethod
+ def setUpClass(cls):
+ testClient = super(TestCpuCapServiceOfferings, cls).getClsTestClient()
+ cls.apiclient = testClient.getApiClient()
+ cls.services = testClient.getParsedTestDataConfig()
+ cls.hypervisor = testClient.getHypervisorInfo()
+
+ cls.hypervisorNotSupported = False
+ if cls.hypervisor.lower() not in ["kvm"]:
+ cls.hypervisorNotSupported = True
+ return
+
+ domain = get_domain(cls.apiclient)
+ cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
+ cls.services['mode'] = cls.zone.networktype
+
+ template = get_template(cls.apiclient, cls.zone.id, cls.hypervisor)
+ if template == FAILED:
+ assert False, "get_template() failed to return template"
+
+ cls.services["small"]["zoneid"] = cls.zone.id
+ cls.services["small"]["template"] = template.id
+ cls.services["small"]["hypervisor"] = cls.hypervisor
+ cls.hostConfig = cls.config.__dict__["zones"][0].__dict__["pods"][0].__dict__["clusters"][0].__dict__["hosts"][0].__dict__
+
+ cls.account = Account.create(
+ cls.apiclient,
+ cls.services["account"],
+ domainid=domain.id
+ )
+
+ offering_data = {
+ 'displaytext': 'TestOffering',
+ 'cpuspeed': 512,
+ 'cpunumber': 2,
+ 'name': 'TestOffering',
+ 'memory': 1024
+ }
+
+ cls.offering = ServiceOffering.create(
+ cls.apiclient,
+ offering_data,
+ limitcpuuse=True
+ )
+
+ def getHost(self, hostId=None):
+ response = list_hosts(
+ self.apiclient,
+ type='Routing',
+ hypervisor='kvm',
+ id=hostId
+ )
+ # Check if more than one kvm hosts are available in order to successfully configure host-ha
+ if response and len(response) > 0:
+ self.host = response[0]
+ return self.host
+ raise self.skipTest("Not enough KVM hosts found, skipping host-ha test")
+
+ cls.host = getHost(cls)
+
+ cls.vm = VirtualMachine.create(
+ cls.apiclient,
+ cls.services["small"],
+ accountid=cls.account.name,
+ domainid=cls.account.domainid,
+ serviceofferingid=cls.offering.id,
+ mode=cls.services["mode"],
+ hostid=cls.host.id
+
+ )
+ cls._cleanup = [
+ cls.offering,
+ cls.account
+ ]
+ return
+
+ @classmethod
+ def tearDownClass(cls):
+ try:
+ cls.apiclient = super(
+ TestCpuCapServiceOfferings,
+ cls).getClsTestClient().getApiClient()
+ # Clean up, terminate the created templates
+ cleanup_resources(cls.apiclient, cls._cleanup)
+
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
+ return
+
+ @skipTestIf("hypervisorNotSupported")
+ @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true")
+ def test_01_service_offering_cpu_limit_use(self):
+ """
+ Test CPU Cap on KVM
+ """
+
+ ssh_host = self.get_ssh_client(self.host.id, self.host.ipaddress, self.hostConfig["username"], self.hostConfig["password"], 10)
+
+ #Get host CPU usage from top command before and after VM consuming 100% CPU
+ find_pid_cmd = "ps -ax | grep '%s' | head -1 | awk '{print $1}'" % self.vm.id
+ pid = ssh_host.execute(find_pid_cmd)[0]
+ cpu_usage_cmd = "top -b n 1 p %s | tail -1 | awk '{print $9}'" % pid
+ host_cpu_usage_before_str = ssh_host.execute(cpu_usage_cmd)[0]
+
+ host_cpu_usage_before = round(float(host_cpu_usage_before_str))
+ self.debug("Host CPU usage before the infinite loop on the VM: " + str(host_cpu_usage_before))
+
+ #Execute loop command in background on the VM
+ ssh_vm = self.vm.get_ssh_client(reconnect=True)
+ ssh_vm.execute("echo 'while true; do x=$(($x+1)); done' > cputest.sh")
+ ssh_vm.execute("sh cputest.sh > /dev/null 2>&1 &")
+
+ time.sleep(5)
+ host_cpu_usage_after_str = ssh_host.execute(cpu_usage_cmd)[0]
+ host_cpu_usage_after = round(float(host_cpu_usage_after_str))
+ self.debug("Host CPU usage after the infinite loop on the VM: " + str(host_cpu_usage_after))
+
+ limit = 95
+ self.assertTrue(host_cpu_usage_after < limit, "Host CPU usage after VM usage increased is high")
+
+ return
--
To stop receiving notification emails like this one, please contact
dahn@apache.org.