Skip to content

Commit 9a02190

Browse files
committed
Bug-ID: CLOUDSTACK-8880: calculate free memory on host before deploying Vm. free memory = total memory - (all vm memory)
1 parent 8bd33d3 commit 9a02190

3 files changed

Lines changed: 96 additions & 3 deletions

File tree

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
268268
protected int _rngRateBytes = 2048;
269269
private File _qemuSocketsPath;
270270
private final String _qemuGuestAgentSocketName = "org.qemu.guest_agent.0";
271+
private long _totalMemory;
271272

272273
private final Map <String, String> _pifs = new HashMap<String, String>();
273274
private final Map<String, VmStats> _vmStats = new ConcurrentHashMap<String, VmStats>();
@@ -2453,6 +2454,7 @@ private Map<String, String> getVersionStrings() {
24532454
public StartupCommand[] initialize() {
24542455

24552456
final List<Object> info = getHostInfo();
2457+
_totalMemory = (Long)info.get(2);
24562458

24572459
final StartupRoutingCommand cmd =
24582460
new StartupRoutingCommand((Integer)info.get(0), (Long)info.get(1), (Long)info.get(2), (Long)info.get(4), (String)info.get(3), _hypervisorType,
@@ -3586,4 +3588,8 @@ public void restoreVMSnapshotMetadata(Domain dm, String vmName, List<Ternary<Str
35863588
}
35873589
}
35883590
}
3591+
3592+
public long getTotalMemory() {
3593+
return _totalMemory;
3594+
}
35893595
}

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtStartCommandWrapper.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.apache.log4j.Logger;
2626
import org.libvirt.Connect;
27+
import org.libvirt.Domain;
2728
import org.libvirt.DomainInfo.DomainState;
2829
import org.libvirt.LibvirtException;
2930

@@ -60,6 +61,17 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource
6061
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = libvirtComputingResource.getLibvirtUtilitiesHelper();
6162
Connect conn = null;
6263
try {
64+
65+
vm = libvirtComputingResource.createVMFromSpec(vmSpec);
66+
conn = libvirtUtilitiesHelper.getConnectionByType(vm.getHvsType());
67+
68+
Long remainingMem = getFreeMemory(conn, libvirtComputingResource);
69+
if (remainingMem == null){
70+
return new StartAnswer(command, "failed to get free memory");
71+
} else if (remainingMem < vmSpec.getMinRam()) {
72+
return new StartAnswer(command, "Not enough memory on the host, remaining: " + remainingMem + ", asking: " + vmSpec.getMinRam());
73+
}
74+
6375
final NicTO[] nics = vmSpec.getNics();
6476

6577
for (final NicTO nic : nics) {
@@ -68,8 +80,6 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource
6880
}
6981
}
7082

71-
vm = libvirtComputingResource.createVMFromSpec(vmSpec);
72-
conn = libvirtUtilitiesHelper.getConnectionByType(vm.getHvsType());
7383
libvirtComputingResource.createVbd(conn, vmSpec, vmName, vm);
7484

7585
if (!storagePoolMgr.connectPhysicalDisksViaVmSpec(vmSpec)) {
@@ -150,4 +160,22 @@ public Answer execute(final StartCommand command, final LibvirtComputingResource
150160
}
151161
}
152162
}
153-
}
163+
164+
private Long getFreeMemory(final Connect conn, final LibvirtComputingResource libvirtComputingResource){
165+
try {
166+
long allocatedMem = 0;
167+
int[] ids = conn.listDomains();
168+
for(int id :ids) {
169+
Domain dm = conn.domainLookupByID(id);
170+
allocatedMem += dm.getMaxMemory() * 1024L;
171+
s_logger.debug("vm: " + dm.getName() + " mem: " + dm.getMaxMemory() * 1024L);
172+
}
173+
Long remainingMem = libvirtComputingResource.getTotalMemory() - allocatedMem;
174+
s_logger.debug("remaining mem" + remainingMem);
175+
return remainingMem;
176+
} catch (Exception e) {
177+
s_logger.debug("failed to get free memory", e);
178+
return null;
179+
}
180+
}
181+
}

plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4855,6 +4855,7 @@ public void testStartCommand() {
48554855

48564856
final NicTO nic = Mockito.mock(NicTO.class);
48574857
final NicTO[] nics = new NicTO[]{nic};
4858+
final int[] vms = new int[0];
48584859

48594860
final String vmName = "Test";
48604861
final String controlIp = "127.0.0.1";
@@ -4868,6 +4869,7 @@ public void testStartCommand() {
48684869
when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper);
48694870
try {
48704871
when(libvirtUtilitiesHelper.getConnectionByType(vmDef.getHvsType())).thenReturn(conn);
4872+
when(conn.listDomains()).thenReturn(vms);
48714873
doNothing().when(libvirtComputingResource).createVbd(conn, vmSpec, vmName, vmDef);
48724874
} catch (final LibvirtException e) {
48734875
fail(e.getMessage());
@@ -4927,6 +4929,7 @@ public void testStartCommandIsolationEc2() {
49274929

49284930
final NicTO nic = Mockito.mock(NicTO.class);
49294931
final NicTO[] nics = new NicTO[]{nic};
4932+
final int[] vms = new int[0];
49304933

49314934
final String vmName = "Test";
49324935
final String controlIp = "127.0.0.1";
@@ -4940,6 +4943,7 @@ public void testStartCommandIsolationEc2() {
49404943
when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper);
49414944
try {
49424945
when(libvirtUtilitiesHelper.getConnectionByType(vmDef.getHvsType())).thenReturn(conn);
4946+
when(conn.listDomains()).thenReturn(vms);
49434947
doNothing().when(libvirtComputingResource).createVbd(conn, vmSpec, vmName, vmDef);
49444948
} catch (final LibvirtException e) {
49454949
fail(e.getMessage());
@@ -4989,6 +4993,61 @@ public void testStartCommandIsolationEc2() {
49894993
}
49904994
}
49914995

4996+
@Test
4997+
public void testStartCommandHostMemory() {
4998+
final VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class);
4999+
final com.cloud.host.Host host = Mockito.mock(com.cloud.host.Host.class);
5000+
final boolean executeInSequence = false;
5001+
5002+
final StartCommand command = new StartCommand(vmSpec, host, executeInSequence);
5003+
5004+
final KVMStoragePoolManager storagePoolMgr = Mockito.mock(KVMStoragePoolManager.class);
5005+
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class);
5006+
final Connect conn = Mockito.mock(Connect.class);
5007+
final LibvirtVMDef vmDef = Mockito.mock(LibvirtVMDef.class);
5008+
5009+
final NicTO nic = Mockito.mock(NicTO.class);
5010+
final NicTO[] nics = new NicTO[]{nic};
5011+
int vmId = 1;
5012+
final int[] vms = new int[]{vmId};
5013+
final Domain dm = Mockito.mock(Domain.class);
5014+
5015+
final String vmName = "Test";
5016+
5017+
when(libvirtComputingResource.getStoragePoolMgr()).thenReturn(storagePoolMgr);
5018+
when(vmSpec.getNics()).thenReturn(nics);
5019+
when(vmSpec.getType()).thenReturn(VirtualMachine.Type.User);
5020+
when(vmSpec.getName()).thenReturn(vmName);
5021+
when(vmSpec.getMaxRam()).thenReturn(512L);
5022+
when(libvirtComputingResource.createVMFromSpec(vmSpec)).thenReturn(vmDef);
5023+
5024+
when(libvirtComputingResource.getLibvirtUtilitiesHelper()).thenReturn(libvirtUtilitiesHelper);
5025+
try {
5026+
when(libvirtUtilitiesHelper.getConnectionByType(vmDef.getHvsType())).thenReturn(conn);
5027+
when(conn.listDomains()).thenReturn(vms);
5028+
when(conn.domainLookupByID(vmId)).thenReturn(dm);
5029+
when(dm.getMaxMemory()).thenReturn(1024L);
5030+
when(dm.getName()).thenReturn(vmName);
5031+
when(libvirtComputingResource.getTotalMemory()).thenReturn(2048*1024L);
5032+
doNothing().when(libvirtComputingResource).createVbd(conn, vmSpec, vmName, vmDef);
5033+
} catch (final LibvirtException e) {
5034+
fail(e.getMessage());
5035+
} catch (final InternalErrorException e) {
5036+
fail(e.getMessage());
5037+
} catch (final URISyntaxException e) {
5038+
fail(e.getMessage());
5039+
}
5040+
5041+
when(storagePoolMgr.connectPhysicalDisksViaVmSpec(vmSpec)).thenReturn(true);
5042+
5043+
final LibvirtRequestWrapper wrapper = LibvirtRequestWrapper.getInstance();
5044+
assertNotNull(wrapper);
5045+
5046+
final Answer answer = wrapper.execute(command, libvirtComputingResource);
5047+
assertTrue(answer.getResult());
5048+
}
5049+
5050+
49925051
@Test
49935052
public void testUpdateHostPasswordCommand() {
49945053
final LibvirtUtilitiesHelper libvirtUtilitiesHelper = Mockito.mock(LibvirtUtilitiesHelper.class);

0 commit comments

Comments
 (0)