diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index c7a176e6c1b..164fabce17a 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -77,6 +77,9 @@ import org.libvirt.DomainSnapshot;
import org.libvirt.LibvirtException;
import org.libvirt.MemoryStatistic;
import org.libvirt.Network;
+import org.libvirt.SchedParameter;
+import org.libvirt.SchedUlongParameter;
+import org.libvirt.VcpuInfo;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -186,7 +189,6 @@ import com.cloud.vm.VirtualMachine.PowerState;
import com.cloud.vm.VmDetailConstants;
import org.apache.commons.lang3.StringUtils;
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
-import org.libvirt.VcpuInfo;
/**
* LibvirtComputingResource execute requests on the computing/routing host using
@@ -4621,4 +4623,35 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
VcpuInfo vcpus[] = dm.getVcpusInfo();
return Arrays.stream(vcpus).filter(vcpu -> vcpu.state.equals(VcpuInfo.VcpuState.VIR_VCPU_RUNNING)).count();
}
+
+ /**
+ * Retrieves the cpu_shares (priority) of the running VM
+ * @param dm domain of the VM.
+ * @return the value of cpu_shares of the running VM.
+ * @throws org.libvirt.LibvirtException
+ **/
+ public static Integer getCpuShares(Domain dm) throws LibvirtException {
+ for (SchedParameter c : dm.getSchedulerParameters()) {
+ if (c.field.equals("cpu_shares")) {
+ return Integer.parseInt(c.getValueAsString());
+ }
+ }
+ s_logger.warn(String.format("Could not get cpu_shares of domain: [%s]. Returning default value of 0. ", dm.getName()));
+ return 0;
+ }
+
+ /**
+ * Sets the cpu_shares (priority) of the running VM
+ * @param dm domain of the VM.
+ * @param cpuShares new priority of the running VM.
+ * @throws org.libvirt.LibvirtException
+ **/
+ public static void setCpuShares(Domain dm, Integer cpuShares) throws LibvirtException {
+ SchedUlongParameter[] params = new SchedUlongParameter[1];
+ params[0] = new SchedUlongParameter();
+ params[0].field = "cpu_shares";
+ params[0].value = cpuShares;
+
+ dm.setSchedulerParameters(params);
+ }
}
diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapper.java
index 384d5cc8b15..96c3e844abf 100644
--- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapper.java
+++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapper.java
@@ -39,8 +39,10 @@ public class LibvirtScaleVmCommandWrapper extends CommandWrapper {
+ if (schedParameters == null || schedParameters.length > 1 || !(schedParameters[0] instanceof SchedUlongParameter)) {
+ return false;
+ }
+ SchedUlongParameter param = (SchedUlongParameter) schedParameters[0];
+ if (param.field != "cpu_shares" || param.value != 2000) {
+ return false;
+ }
+ return true;
+ }));
+ }
}
diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapperTest.java
index a0851e747f1..6079a70ddd1 100644
--- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapperTest.java
+++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtScaleVmCommandWrapperTest.java
@@ -78,7 +78,8 @@ public class LibvirtScaleVmCommandWrapperTest extends TestCase {
long memory = ByteScaleUtils.bytesToKib(vmTo.getMaxRam());
int vcpus = vmTo.getCpus();
- scalingDetails = String.format("%s memory to [%s KiB] and CPU cores to [%s]", vmTo.toString(), memory, vcpus);
+ int cpuShares = vcpus * vmTo.getSpeed();
+ scalingDetails = String.format("%s memory to [%s KiB], CPU cores to [%s] and cpu_shares to [%s]", vmTo.toString(), memory, vcpus, cpuShares);
PowerMockito.mockStatic(LibvirtComputingResource.class);
}
@@ -241,4 +242,40 @@ public class LibvirtScaleVmCommandWrapperTest extends TestCase {
libvirtScaleVmCommandWrapperSpy.execute(scaleVmCommandMock, libvirtComputingResourceMock);
}
+
+ @Test
+ public void updateCpuSharesTestOldSharesLessThanNewSharesUpdateShares() throws LibvirtException {
+ int oldShares = 2000;
+ int newShares = 3000;
+
+ PowerMockito.when(LibvirtComputingResource.getCpuShares(Mockito.any())).thenReturn(oldShares);
+ libvirtScaleVmCommandWrapperSpy.updateCpuShares(domainMock, newShares);
+
+ PowerMockito.verifyStatic(LibvirtComputingResource.class, Mockito.times(1));
+ libvirtComputingResourceMock.setCpuShares(domainMock, newShares);
+ }
+
+ @Test
+ public void updateCpuSharesTestOldSharesHigherThanNewSharesDoNothing() throws LibvirtException {
+ int oldShares = 3000;
+ int newShares = 2000;
+
+ PowerMockito.when(LibvirtComputingResource.getCpuShares(Mockito.any())).thenReturn(oldShares);
+ libvirtScaleVmCommandWrapperSpy.updateCpuShares(domainMock, newShares);
+
+ PowerMockito.verifyStatic(LibvirtComputingResource.class, Mockito.times(0));
+ libvirtComputingResourceMock.setCpuShares(domainMock, newShares);
+ }
+
+ @Test
+ public void updateCpuSharesTestOldSharesEqualsNewSharesDoNothing() throws LibvirtException {
+ int oldShares = 2000;
+ int newShares = 2000;
+
+ PowerMockito.when(LibvirtComputingResource.getCpuShares(Mockito.any())).thenReturn(oldShares);
+ libvirtScaleVmCommandWrapperSpy.updateCpuShares(domainMock, newShares);
+
+ PowerMockito.verifyStatic(LibvirtComputingResource.class, Mockito.times(0));
+ libvirtComputingResourceMock.setCpuShares(domainMock, newShares);
+ }
}