mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-02 20:02:29 +01:00
Add logs to LibvirtComputingResource's metrics collection process (#8511)
* Add logs to LibvirtComputingResource's metrics collecting process * Apply Joao's suggestions Co-authored-by: João Jandre <48719461+JoaoJandre@users.noreply.github.com> * Adjust some logs * Print memory statistics log in one line --------- Co-authored-by: João Jandre <48719461+JoaoJandre@users.noreply.github.com>
This commit is contained in:
parent
82f113b1e1
commit
b11897cdfa
@ -44,6 +44,8 @@ import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
@ -76,6 +78,8 @@ import org.apache.commons.lang.BooleanUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.xerces.impl.xpath.regex.Match;
|
||||
@ -446,7 +450,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
protected WatchDogModel watchDogModel = WatchDogModel.I6300ESB;
|
||||
|
||||
private final Map <String, String> pifs = new HashMap<String, String>();
|
||||
private final Map<String, VmStats> vmStats = new ConcurrentHashMap<String, VmStats>();
|
||||
private final Map<String, LibvirtExtendedVmStatsEntry> vmStats = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<String, DomainBlockStats> vmDiskStats = new ConcurrentHashMap<>();
|
||||
|
||||
@ -2346,7 +2350,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
final PowerState s = convertToPowerState(vms.getInfo().state);
|
||||
return s;
|
||||
} catch (final LibvirtException e) {
|
||||
LOGGER.warn("Can't get vm state " + vmName + e.getMessage() + "retry:" + retry);
|
||||
LOGGER.error("Could not get state for VM [{}] (retry={}) due to:", vmName, retry, e);
|
||||
} finally {
|
||||
try {
|
||||
if (vms != null) {
|
||||
@ -4414,122 +4418,34 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
return null;
|
||||
}
|
||||
|
||||
private class VmStats {
|
||||
long usedTime;
|
||||
long tx;
|
||||
long rx;
|
||||
long ioRead;
|
||||
long ioWrote;
|
||||
long bytesRead;
|
||||
long bytesWrote;
|
||||
Calendar timestamp;
|
||||
private String vmToString(Domain dm) throws LibvirtException {
|
||||
return String.format("{\"name\":\"%s\",\"uuid\":\"%s\"}", dm.getName(), dm.getUUIDString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns metrics for the period since this function was last called for the specified VM.
|
||||
* @param conn the Libvirt connection.
|
||||
* @param vmName name of the VM.
|
||||
* @return metrics for the period since last time this function was called for the VM.
|
||||
* @throws LibvirtException
|
||||
*/
|
||||
public VmStatsEntry getVmStat(final Connect conn, final String vmName) throws LibvirtException {
|
||||
Domain dm = null;
|
||||
try {
|
||||
LOGGER.debug("Trying to get VM with name [{}].", vmName);
|
||||
dm = getDomain(conn, vmName);
|
||||
if (dm == null) {
|
||||
LOGGER.warn("Could not get VM with name [{}].", vmName);
|
||||
return null;
|
||||
}
|
||||
DomainInfo info = dm.getInfo();
|
||||
final VmStatsEntry stats = new VmStatsEntry();
|
||||
|
||||
stats.setNumCPUs(info.nrVirtCpu);
|
||||
stats.setEntityType("vm");
|
||||
LibvirtExtendedVmStatsEntry newStats = getVmCurrentStats(dm);
|
||||
LibvirtExtendedVmStatsEntry oldStats = vmStats.get(vmName);
|
||||
|
||||
stats.setMemoryKBs(info.maxMem);
|
||||
stats.setTargetMemoryKBs(info.memory);
|
||||
stats.setIntFreeMemoryKBs(getMemoryFreeInKBs(dm));
|
||||
VmStatsEntry metrics = calculateVmMetrics(dm, oldStats, newStats);
|
||||
vmStats.put(vmName, newStats);
|
||||
|
||||
/* get cpu utilization */
|
||||
VmStats oldStats = null;
|
||||
|
||||
final Calendar now = Calendar.getInstance();
|
||||
|
||||
oldStats = vmStats.get(vmName);
|
||||
|
||||
long elapsedTime = 0;
|
||||
if (oldStats != null) {
|
||||
elapsedTime = now.getTimeInMillis() - oldStats.timestamp.getTimeInMillis();
|
||||
double utilization = (info.cpuTime - oldStats.usedTime) / ((double)elapsedTime * 1000000);
|
||||
|
||||
utilization = utilization / info.nrVirtCpu;
|
||||
if (utilization > 0) {
|
||||
stats.setCPUUtilization(utilization * 100);
|
||||
}
|
||||
}
|
||||
|
||||
/* get network stats */
|
||||
|
||||
final List<InterfaceDef> vifs = getInterfaces(conn, vmName);
|
||||
long rx = 0;
|
||||
long tx = 0;
|
||||
for (final InterfaceDef vif : vifs) {
|
||||
final DomainInterfaceStats ifStats = dm.interfaceStats(vif.getDevName());
|
||||
rx += ifStats.rx_bytes;
|
||||
tx += ifStats.tx_bytes;
|
||||
}
|
||||
|
||||
if (oldStats != null) {
|
||||
final double deltarx = rx - oldStats.rx;
|
||||
if (deltarx > 0) {
|
||||
stats.setNetworkReadKBs(deltarx / 1024);
|
||||
}
|
||||
final double deltatx = tx - oldStats.tx;
|
||||
if (deltatx > 0) {
|
||||
stats.setNetworkWriteKBs(deltatx / 1024);
|
||||
}
|
||||
}
|
||||
|
||||
/* get disk stats */
|
||||
final List<DiskDef> disks = getDisks(conn, vmName);
|
||||
long io_rd = 0;
|
||||
long io_wr = 0;
|
||||
long bytes_rd = 0;
|
||||
long bytes_wr = 0;
|
||||
for (final DiskDef disk : disks) {
|
||||
if (disk.getDeviceType() == DeviceType.CDROM || disk.getDeviceType() == DeviceType.FLOPPY) {
|
||||
continue;
|
||||
}
|
||||
final DomainBlockStats blockStats = dm.blockStats(disk.getDiskLabel());
|
||||
io_rd += blockStats.rd_req;
|
||||
io_wr += blockStats.wr_req;
|
||||
bytes_rd += blockStats.rd_bytes;
|
||||
bytes_wr += blockStats.wr_bytes;
|
||||
}
|
||||
|
||||
if (oldStats != null) {
|
||||
final long deltaiord = io_rd - oldStats.ioRead;
|
||||
if (deltaiord > 0) {
|
||||
stats.setDiskReadIOs(deltaiord);
|
||||
}
|
||||
final long deltaiowr = io_wr - oldStats.ioWrote;
|
||||
if (deltaiowr > 0) {
|
||||
stats.setDiskWriteIOs(deltaiowr);
|
||||
}
|
||||
final double deltabytesrd = bytes_rd - oldStats.bytesRead;
|
||||
if (deltabytesrd > 0) {
|
||||
stats.setDiskReadKBs(deltabytesrd / 1024);
|
||||
}
|
||||
final double deltabyteswr = bytes_wr - oldStats.bytesWrote;
|
||||
if (deltabyteswr > 0) {
|
||||
stats.setDiskWriteKBs(deltabyteswr / 1024);
|
||||
}
|
||||
}
|
||||
|
||||
/* save to Hashmap */
|
||||
final VmStats newStat = new VmStats();
|
||||
newStat.usedTime = info.cpuTime;
|
||||
newStat.rx = rx;
|
||||
newStat.tx = tx;
|
||||
newStat.ioRead = io_rd;
|
||||
newStat.ioWrote = io_wr;
|
||||
newStat.bytesRead = bytes_rd;
|
||||
newStat.bytesWrote = bytes_wr;
|
||||
newStat.timestamp = now;
|
||||
vmStats.put(vmName, newStat);
|
||||
return stats;
|
||||
return metrics;
|
||||
} finally {
|
||||
if (dm != null) {
|
||||
dm.free();
|
||||
@ -4537,6 +4453,156 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a VM's current statistics.
|
||||
* @param dm domain of the VM.
|
||||
* @return current statistics of the VM.
|
||||
* @throws LibvirtException
|
||||
*/
|
||||
protected LibvirtExtendedVmStatsEntry getVmCurrentStats(final Domain dm) throws LibvirtException {
|
||||
final LibvirtExtendedVmStatsEntry stats = new LibvirtExtendedVmStatsEntry();
|
||||
|
||||
getVmCurrentCpuStats(dm, stats);
|
||||
getVmCurrentNetworkStats(dm, stats);
|
||||
getVmCurrentDiskStats(dm, stats);
|
||||
|
||||
LOGGER.debug("Retrieved statistics for VM [{}]: [{}].", vmToString(dm), stats);
|
||||
stats.setTimestamp(Calendar.getInstance());
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes a VM's current CPU statistics into the provided LibvirtExtendedVmStatsEntry.
|
||||
* @param dm domain of the VM.
|
||||
* @param stats LibvirtExtendedVmStatsEntry that will receive the current CPU statistics.
|
||||
* @throws LibvirtException
|
||||
*/
|
||||
protected void getVmCurrentCpuStats(final Domain dm, final LibvirtExtendedVmStatsEntry stats) throws LibvirtException {
|
||||
LOGGER.trace("Getting CPU stats for VM [{}].", vmToString(dm));
|
||||
stats.setCpuTime(dm.getInfo().cpuTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes a VM's current network statistics into the provided LibvirtExtendedVmStatsEntry.
|
||||
* @param dm domain of the VM.
|
||||
* @param stats LibvirtExtendedVmStatsEntry that will receive the current network statistics.
|
||||
* @throws LibvirtException
|
||||
*/
|
||||
protected void getVmCurrentNetworkStats(final Domain dm, final LibvirtExtendedVmStatsEntry stats) throws LibvirtException {
|
||||
final String vmAsString = vmToString(dm);
|
||||
LOGGER.trace("Getting network stats for VM [{}].", vmAsString);
|
||||
final List<InterfaceDef> vifs = getInterfaces(dm.getConnect(), dm.getName());
|
||||
LOGGER.debug("Found [{}] network interface(s) for VM [{}].", vifs.size(), vmAsString);
|
||||
double rx = 0;
|
||||
double tx = 0;
|
||||
for (final InterfaceDef vif : vifs) {
|
||||
final DomainInterfaceStats ifStats = dm.interfaceStats(vif.getDevName());
|
||||
rx += ifStats.rx_bytes;
|
||||
tx += ifStats.tx_bytes;
|
||||
}
|
||||
stats.setNetworkReadKBs(rx / 1024);
|
||||
stats.setNetworkWriteKBs(tx / 1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* Passes a VM's current disk statistics into the provided LibvirtExtendedVmStatsEntry.
|
||||
* @param dm domain of the VM.
|
||||
* @param stats LibvirtExtendedVmStatsEntry that will receive the current disk statistics.
|
||||
* @throws LibvirtException
|
||||
*/
|
||||
protected void getVmCurrentDiskStats(final Domain dm, final LibvirtExtendedVmStatsEntry stats) throws LibvirtException {
|
||||
final String vmAsString = vmToString(dm);
|
||||
LOGGER.trace("Getting disk stats for VM [{}].", vmAsString);
|
||||
final List<DiskDef> disks = getDisks(dm.getConnect(), dm.getName());
|
||||
LOGGER.debug("Found [{}] disk(s) for VM [{}].", disks.size(), vmAsString);
|
||||
long io_rd = 0;
|
||||
long io_wr = 0;
|
||||
double bytes_rd = 0;
|
||||
double bytes_wr = 0;
|
||||
for (final DiskDef disk : disks) {
|
||||
if (disk.getDeviceType() == DeviceType.CDROM || disk.getDeviceType() == DeviceType.FLOPPY) {
|
||||
LOGGER.debug("Ignoring disk [{}] in VM [{}]'s stats since its deviceType is [{}].", disk.toString().replace("\n", ""), vmAsString, disk.getDeviceType());
|
||||
continue;
|
||||
}
|
||||
final DomainBlockStats blockStats = dm.blockStats(disk.getDiskLabel());
|
||||
io_rd += blockStats.rd_req;
|
||||
io_wr += blockStats.wr_req;
|
||||
bytes_rd += blockStats.rd_bytes;
|
||||
bytes_wr += blockStats.wr_bytes;
|
||||
}
|
||||
stats.setDiskReadIOs(io_rd);
|
||||
stats.setDiskWriteIOs(io_wr);
|
||||
stats.setDiskReadKBs(bytes_rd / 1024);
|
||||
stats.setDiskWriteKBs(bytes_wr / 1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a VM's metrics for the period between the two statistics given as parameters.
|
||||
* @param dm domain of the VM.
|
||||
* @param oldStats old statistics. If null, the CPU, network and disk utilization won't be calculated.
|
||||
* @param newStats new statistics.
|
||||
* @return metrics for the period between the two statistics.
|
||||
* @throws LibvirtException
|
||||
*/
|
||||
protected VmStatsEntry calculateVmMetrics(final Domain dm, final LibvirtExtendedVmStatsEntry oldStats, final LibvirtExtendedVmStatsEntry newStats) throws LibvirtException {
|
||||
final VmStatsEntry metrics = new VmStatsEntry();
|
||||
final DomainInfo info = dm.getInfo();
|
||||
final String vmAsString = vmToString(dm);
|
||||
|
||||
metrics.setEntityType("vm");
|
||||
LOGGER.trace("Writing VM [{}]'s CPU and memory information into the metrics.", vmAsString);
|
||||
metrics.setNumCPUs(info.nrVirtCpu);
|
||||
metrics.setMemoryKBs(info.maxMem);
|
||||
metrics.setTargetMemoryKBs(info.memory);
|
||||
LOGGER.trace("Trying to get free memory for VM [{}].", vmAsString);
|
||||
metrics.setIntFreeMemoryKBs(getMemoryFreeInKBs(dm));
|
||||
|
||||
if (oldStats != null) {
|
||||
LOGGER.debug("Old stats exist for VM [{}]; therefore, the utilization will be calculated.", vmAsString);
|
||||
|
||||
LOGGER.trace("Calculating CPU utilization for VM [{}].", vmAsString);
|
||||
final Calendar now = Calendar.getInstance();
|
||||
long elapsedTime = now.getTimeInMillis() - oldStats.getTimestamp().getTimeInMillis();
|
||||
double utilization = (info.cpuTime - oldStats.getCpuTime()) / ((double) elapsedTime * 1000000 * info.nrVirtCpu);
|
||||
if (utilization > 0) {
|
||||
metrics.setCPUUtilization(utilization * 100);
|
||||
}
|
||||
|
||||
LOGGER.trace("Calculating network utilization for VM [{}].", vmAsString);
|
||||
final double deltarx = newStats.getNetworkReadKBs() - oldStats.getNetworkReadKBs();
|
||||
if (deltarx > 0) {
|
||||
metrics.setNetworkReadKBs(deltarx);
|
||||
}
|
||||
final double deltatx = newStats.getNetworkWriteKBs() - oldStats.getNetworkWriteKBs();
|
||||
if (deltatx > 0) {
|
||||
metrics.setNetworkWriteKBs(deltatx);
|
||||
}
|
||||
|
||||
LOGGER.trace("Calculating disk utilization for VM [{}].", vmAsString);
|
||||
final double deltaiord = newStats.getDiskReadIOs() - oldStats.getDiskReadIOs();
|
||||
if (deltaiord > 0) {
|
||||
metrics.setDiskReadIOs(deltaiord);
|
||||
}
|
||||
final double deltaiowr = newStats.getDiskWriteIOs() - oldStats.getDiskWriteIOs();
|
||||
if (deltaiowr > 0) {
|
||||
metrics.setDiskWriteIOs(deltaiowr);
|
||||
}
|
||||
final double deltabytesrd = newStats.getDiskReadKBs() - oldStats.getDiskReadKBs();
|
||||
if (deltabytesrd > 0) {
|
||||
metrics.setDiskReadKBs(deltabytesrd);
|
||||
}
|
||||
final double deltabyteswr = newStats.getDiskWriteKBs() - oldStats.getDiskWriteKBs();
|
||||
if (deltabyteswr > 0) {
|
||||
metrics.setDiskWriteKBs(deltabyteswr);
|
||||
}
|
||||
}
|
||||
|
||||
String metricsAsString = new ReflectionToStringBuilder(metrics, ToStringStyle.JSON_STYLE).setExcludeFieldNames("vmId", "vmUuid").toString();
|
||||
LOGGER.debug("Calculated metrics for VM [{}]: [{}].", vmAsString, metricsAsString);
|
||||
|
||||
return metrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method retrieves the memory statistics from the domain given as parameters.
|
||||
* If no memory statistic is found, it will return {@link NumberUtils#LONG_MINUS_ONE} as the value of free memory in the domain.
|
||||
@ -4546,10 +4612,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
||||
*/
|
||||
protected long getMemoryFreeInKBs(Domain dm) throws LibvirtException {
|
||||
MemoryStatistic[] memoryStats = dm.memoryStats(NUMMEMSTATS);
|
||||
|
||||
if(LOGGER.isTraceEnabled()){
|
||||
LOGGER.trace(String.format("Retrieved memory statistics (information about tags can be found on the libvirt documentation):", ArrayUtils.toString(memoryStats)));
|
||||
}
|
||||
LOGGER.trace("Retrieved memory statistics (information about tags can be found on the libvirt documentation): {}.",
|
||||
() -> Stream.of(memoryStats).map(stat -> stat.toString().trim().replace("\n", ",")).collect(Collectors.joining("},{", "[{", "}]")));
|
||||
|
||||
long freeMemory = NumberUtils.LONG_MINUS_ONE;
|
||||
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
// 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.kvm.resource;
|
||||
|
||||
import com.cloud.agent.api.VmStatsEntry;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
public class LibvirtExtendedVmStatsEntry extends VmStatsEntry {
|
||||
private long cpuTime;
|
||||
private Calendar timestamp;
|
||||
|
||||
public LibvirtExtendedVmStatsEntry() {
|
||||
}
|
||||
|
||||
public long getCpuTime() {
|
||||
return cpuTime;
|
||||
}
|
||||
|
||||
public void setCpuTime(long cpuTime) {
|
||||
this.cpuTime = cpuTime;
|
||||
}
|
||||
|
||||
public Calendar getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(Calendar timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "cpuTime", "networkWriteKBs", "networkReadKBs", "diskReadIOs", "diskWriteIOs", "diskReadKBs", "diskWriteKBs");
|
||||
}
|
||||
}
|
||||
@ -82,6 +82,7 @@ import org.libvirt.DomainInfo.DomainState;
|
||||
import org.libvirt.DomainInterfaceStats;
|
||||
import org.libvirt.LibvirtException;
|
||||
import org.libvirt.MemoryStatistic;
|
||||
import org.libvirt.NodeInfo;
|
||||
import org.libvirt.SchedUlongParameter;
|
||||
import org.libvirt.StorageVol;
|
||||
import org.libvirt.VcpuInfo;
|
||||
@ -93,7 +94,6 @@ import org.mockito.MockedConstruction;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
@ -243,10 +243,18 @@ public class LibvirtComputingResourceTest {
|
||||
|
||||
@Mock
|
||||
Domain domainMock;
|
||||
@Mock
|
||||
DomainInfo domainInfoMock;
|
||||
@Mock
|
||||
DomainInterfaceStats domainInterfaceStatsMock;
|
||||
@Mock
|
||||
DomainBlockStats domainBlockStatsMock;
|
||||
|
||||
private final static long HYPERVISOR_LIBVIRT_VERSION_SUPPORTS_IOURING = 6003000;
|
||||
private final static long HYPERVISOR_QEMU_VERSION_SUPPORTS_IOURING = 5000000;
|
||||
|
||||
private final static String VM_NAME = "test";
|
||||
|
||||
String hyperVisorType = "kvm";
|
||||
Random random = new Random();
|
||||
final String memInfo = "MemTotal: 5830236 kB\n" +
|
||||
@ -922,86 +930,6 @@ public class LibvirtComputingResourceTest {
|
||||
assertEquals(uuid, oldUuid);
|
||||
}
|
||||
|
||||
private static final String VMNAME = "test";
|
||||
|
||||
@Test
|
||||
public void testGetVmStat() throws LibvirtException {
|
||||
final Connect connect = Mockito.mock(Connect.class);
|
||||
final Domain domain = Mockito.mock(Domain.class);
|
||||
final DomainInfo domainInfo = new DomainInfo();
|
||||
final MemoryStatistic[] domainMem = new MemoryStatistic[2];
|
||||
domainMem[0] = Mockito.mock(MemoryStatistic.class);
|
||||
Mockito.when(domain.getInfo()).thenReturn(domainInfo);
|
||||
Mockito.when(domain.memoryStats(20)).thenReturn(domainMem);
|
||||
Mockito.when(domainMem[0].getTag()).thenReturn(4);
|
||||
Mockito.when(connect.domainLookupByName(VMNAME)).thenReturn(domain);
|
||||
|
||||
// this is testing the interface stats, returns an increasing number of sent and received bytes
|
||||
|
||||
Mockito.when(domain.interfaceStats(nullable(String.class))).thenAnswer(new org.mockito.stubbing.Answer<DomainInterfaceStats>() {
|
||||
// increment with less than a KB, so this should be less than 1 KB
|
||||
final static int increment = 1000;
|
||||
int rxBytes = 1000;
|
||||
int txBytes = 1000;
|
||||
|
||||
@Override
|
||||
public DomainInterfaceStats answer(final InvocationOnMock invocation) throws Throwable {
|
||||
final DomainInterfaceStats domainInterfaceStats = new DomainInterfaceStats();
|
||||
domainInterfaceStats.rx_bytes = rxBytes += increment;
|
||||
domainInterfaceStats.tx_bytes = txBytes += increment;
|
||||
return domainInterfaceStats;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
Mockito.when(domain.blockStats(nullable(String.class))).thenAnswer(new org.mockito.stubbing.Answer<DomainBlockStats>() {
|
||||
// a little less than a KB
|
||||
final static int increment = 1000;
|
||||
|
||||
int rdBytes = 0;
|
||||
int wrBytes = 1024;
|
||||
|
||||
@Override
|
||||
public DomainBlockStats answer(final InvocationOnMock invocation) throws Throwable {
|
||||
final DomainBlockStats domainBlockStats = new DomainBlockStats();
|
||||
|
||||
domainBlockStats.rd_bytes = rdBytes += increment;
|
||||
domainBlockStats.wr_bytes = wrBytes += increment;
|
||||
return domainBlockStats;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
final LibvirtComputingResource libvirtComputingResource = new LibvirtComputingResource() {
|
||||
@Override
|
||||
public List<InterfaceDef> getInterfaces(final Connect conn, final String vmName) {
|
||||
final InterfaceDef interfaceDef = new InterfaceDef();
|
||||
return Arrays.asList(interfaceDef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DiskDef> getDisks(final Connect conn, final String vmName) {
|
||||
final DiskDef diskDef = new DiskDef();
|
||||
return Arrays.asList(diskDef);
|
||||
}
|
||||
|
||||
};
|
||||
libvirtComputingResource.getVmStat(connect, VMNAME);
|
||||
final VmStatsEntry vmStat = libvirtComputingResource.getVmStat(connect, VMNAME);
|
||||
// network traffic as generated by the logic above, must be greater than zero
|
||||
Assert.assertTrue(vmStat.getNetworkReadKBs() > 0);
|
||||
Assert.assertTrue(vmStat.getNetworkWriteKBs() > 0);
|
||||
// IO traffic as generated by the logic above, must be greater than zero
|
||||
Assert.assertTrue(vmStat.getDiskReadKBs() > 0);
|
||||
Assert.assertTrue(vmStat.getDiskWriteKBs() > 0);
|
||||
// Memory limit of VM must be greater than zero
|
||||
Assert.assertTrue(vmStat.getIntFreeMemoryKBs() >= 0);
|
||||
Assert.assertTrue(vmStat.getMemoryKBs() >= 0);
|
||||
Assert.assertTrue(vmStat.getTargetMemoryKBs() >= vmStat.getMemoryKBs());
|
||||
}
|
||||
|
||||
/*
|
||||
* New Tests
|
||||
*/
|
||||
@ -6331,4 +6259,160 @@ public class LibvirtComputingResourceTest {
|
||||
Assert.assertEquals("", StringUtils.join(hostTagsList, ","));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVmStatTestVmIsNullReturnsNull() throws LibvirtException {
|
||||
doReturn(null).when(libvirtComputingResourceSpy).getDomain(connMock, VM_NAME);
|
||||
|
||||
VmStatsEntry stat = libvirtComputingResourceSpy.getVmStat(connMock, VM_NAME);
|
||||
|
||||
verify(libvirtComputingResourceSpy).getDomain(connMock, VM_NAME);
|
||||
verify(libvirtComputingResourceSpy, never()).getVmCurrentStats(domainMock);
|
||||
verify(libvirtComputingResourceSpy, never()).calculateVmMetrics(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Assert.assertNull(stat);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVmStatTestVmIsNotNullReturnsMetrics() throws LibvirtException {
|
||||
doReturn(domainMock).when(libvirtComputingResourceSpy).getDomain(connMock, VM_NAME);
|
||||
doReturn(Mockito.mock(LibvirtExtendedVmStatsEntry.class)).when(libvirtComputingResourceSpy).getVmCurrentStats(domainMock);
|
||||
doReturn(Mockito.mock(VmStatsEntry.class)).when(libvirtComputingResourceSpy).calculateVmMetrics(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
VmStatsEntry stat = libvirtComputingResourceSpy.getVmStat(connMock, VM_NAME);
|
||||
|
||||
verify(libvirtComputingResourceSpy).getDomain(connMock, VM_NAME);
|
||||
verify(libvirtComputingResourceSpy).getVmCurrentStats(domainMock);
|
||||
verify(libvirtComputingResourceSpy).calculateVmMetrics(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Assert.assertNotNull(stat);
|
||||
}
|
||||
|
||||
private void prepareVmInfoForGetVmCurrentStats() throws LibvirtException {
|
||||
final NodeInfo nodeInfo = new NodeInfo();
|
||||
nodeInfo.cpus = 8;
|
||||
nodeInfo.memory = 8 * 1024 * 1024;
|
||||
nodeInfo.sockets = 2;
|
||||
nodeInfo.threads = 2;
|
||||
nodeInfo.model = "Foo processor";
|
||||
|
||||
Mockito.when(domainMock.getName()).thenReturn(VM_NAME);
|
||||
Mockito.when(domainMock.getConnect()).thenReturn(connMock);
|
||||
domainInfoMock.cpuTime = 500L;
|
||||
domainInfoMock.nrVirtCpu = 4;
|
||||
domainInfoMock.memory = 2048;
|
||||
domainInfoMock.maxMem = 4096;
|
||||
Mockito.when(domainMock.getInfo()).thenReturn(domainInfoMock);
|
||||
final MemoryStatistic[] domainMem = new MemoryStatistic[2];
|
||||
domainMem[0] = Mockito.mock(MemoryStatistic.class);
|
||||
doReturn(1024L).when(libvirtComputingResourceSpy).getMemoryFreeInKBs(domainMock);
|
||||
|
||||
domainInterfaceStatsMock.rx_bytes = 1000L;
|
||||
domainInterfaceStatsMock.tx_bytes = 2000L;
|
||||
doReturn(domainInterfaceStatsMock).when(domainMock).interfaceStats(Mockito.any());
|
||||
doReturn(List.of(new InterfaceDef())).when(libvirtComputingResourceSpy).getInterfaces(connMock, VM_NAME);
|
||||
|
||||
domainBlockStatsMock.rd_req = 3000L;
|
||||
domainBlockStatsMock.rd_bytes = 4000L;
|
||||
domainBlockStatsMock.wr_req = 5000L;
|
||||
domainBlockStatsMock.wr_bytes = 6000L;
|
||||
doReturn(domainBlockStatsMock).when(domainMock).blockStats(Mockito.any());
|
||||
doReturn(List.of(new DiskDef())).when(libvirtComputingResourceSpy).getDisks(connMock, VM_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVmCurrentStatsTestIfStatsAreAsExpected() throws LibvirtException {
|
||||
prepareVmInfoForGetVmCurrentStats();
|
||||
|
||||
LibvirtExtendedVmStatsEntry vmStatsEntry = libvirtComputingResourceSpy.getVmCurrentStats(domainMock);
|
||||
|
||||
Assert.assertEquals(domainInfoMock.cpuTime, vmStatsEntry.getCpuTime());
|
||||
Assert.assertEquals((double) domainInterfaceStatsMock.rx_bytes / 1024, vmStatsEntry.getNetworkReadKBs(), 0);
|
||||
Assert.assertEquals((double) domainInterfaceStatsMock.tx_bytes / 1024, vmStatsEntry.getNetworkWriteKBs(), 0);
|
||||
Assert.assertEquals(domainBlockStatsMock.rd_req, vmStatsEntry.getDiskReadIOs(), 0);
|
||||
Assert.assertEquals((double) domainBlockStatsMock.rd_bytes / 1024, vmStatsEntry.getDiskReadKBs(), 0);
|
||||
Assert.assertEquals(domainBlockStatsMock.wr_req, vmStatsEntry.getDiskWriteIOs(), 0);
|
||||
Assert.assertEquals((double) domainBlockStatsMock.wr_bytes / 1024, vmStatsEntry.getDiskWriteKBs(), 0);
|
||||
Assert.assertNotNull(vmStatsEntry.getTimestamp());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVmCurrentCpuStatsTestIfStatsAreAsExpected() throws LibvirtException {
|
||||
prepareVmInfoForGetVmCurrentStats();
|
||||
|
||||
LibvirtExtendedVmStatsEntry vmStatsEntry = new LibvirtExtendedVmStatsEntry();
|
||||
libvirtComputingResourceSpy.getVmCurrentCpuStats(domainMock, vmStatsEntry);
|
||||
|
||||
Assert.assertEquals(domainInfoMock.cpuTime, vmStatsEntry.getCpuTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVmCurrentNetworkStatsTestIfStatsAreAsExpected() throws LibvirtException {
|
||||
prepareVmInfoForGetVmCurrentStats();
|
||||
|
||||
LibvirtExtendedVmStatsEntry vmStatsEntry = new LibvirtExtendedVmStatsEntry();
|
||||
libvirtComputingResourceSpy.getVmCurrentNetworkStats(domainMock, vmStatsEntry);
|
||||
|
||||
Assert.assertEquals((double) domainInterfaceStatsMock.rx_bytes / 1024, vmStatsEntry.getNetworkReadKBs(), 0);
|
||||
Assert.assertEquals((double) domainInterfaceStatsMock.tx_bytes / 1024, vmStatsEntry.getNetworkWriteKBs(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getVmCurrentDiskStatsTestIfStatsAreAsExpected() throws LibvirtException {
|
||||
prepareVmInfoForGetVmCurrentStats();
|
||||
|
||||
LibvirtExtendedVmStatsEntry vmStatsEntry = new LibvirtExtendedVmStatsEntry();
|
||||
libvirtComputingResourceSpy.getVmCurrentDiskStats(domainMock, vmStatsEntry);
|
||||
|
||||
Assert.assertEquals(domainBlockStatsMock.rd_req, vmStatsEntry.getDiskReadIOs(), 0);
|
||||
Assert.assertEquals((double) domainBlockStatsMock.rd_bytes / 1024, vmStatsEntry.getDiskReadKBs(), 0);
|
||||
Assert.assertEquals(domainBlockStatsMock.wr_req, vmStatsEntry.getDiskWriteIOs(), 0);
|
||||
Assert.assertEquals((double) domainBlockStatsMock.wr_bytes / 1024, vmStatsEntry.getDiskWriteKBs(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateVmMetricsTestOldStatsIsNullDoesNotCalculateUtilization() throws LibvirtException {
|
||||
prepareVmInfoForGetVmCurrentStats();
|
||||
|
||||
LibvirtExtendedVmStatsEntry vmStatsEntry = libvirtComputingResourceSpy.getVmCurrentStats(domainMock);
|
||||
VmStatsEntry metrics = libvirtComputingResourceSpy.calculateVmMetrics(domainMock, null, vmStatsEntry);
|
||||
|
||||
Assert.assertEquals(domainInfoMock.nrVirtCpu, metrics.getNumCPUs());
|
||||
Assert.assertEquals(domainInfoMock.maxMem, (long) metrics.getMemoryKBs());
|
||||
Assert.assertEquals(libvirtComputingResourceSpy.getMemoryFreeInKBs(domainMock), (long) metrics.getIntFreeMemoryKBs());
|
||||
Assert.assertEquals(domainInfoMock.memory, (long) metrics.getTargetMemoryKBs());
|
||||
Assert.assertEquals(0, metrics.getCPUUtilization(), 0);
|
||||
Assert.assertEquals(0, metrics.getNetworkReadKBs(), 0);
|
||||
Assert.assertEquals(0, metrics.getNetworkWriteKBs(), 0);
|
||||
Assert.assertEquals(0, metrics.getDiskReadKBs(), 0);
|
||||
Assert.assertEquals(0, metrics.getDiskReadIOs(), 0);
|
||||
Assert.assertEquals(0, metrics.getDiskWriteKBs(), 0);
|
||||
Assert.assertEquals(0, metrics.getDiskWriteIOs(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculateVmMetricsTestOldStatsIsNotNullCalculatesUtilization() throws LibvirtException {
|
||||
prepareVmInfoForGetVmCurrentStats();
|
||||
LibvirtExtendedVmStatsEntry oldStats = libvirtComputingResourceSpy.getVmCurrentStats(domainMock);
|
||||
domainInfoMock.cpuTime *= 3;
|
||||
domainInterfaceStatsMock.rx_bytes *= 3;
|
||||
domainInterfaceStatsMock.tx_bytes *= 3;
|
||||
domainBlockStatsMock.rd_req *= 3;
|
||||
domainBlockStatsMock.rd_bytes *= 3;
|
||||
domainBlockStatsMock.wr_req *= 3;
|
||||
domainBlockStatsMock.wr_bytes *= 3;
|
||||
LibvirtExtendedVmStatsEntry newStats = libvirtComputingResourceSpy.getVmCurrentStats(domainMock);
|
||||
|
||||
VmStatsEntry metrics = libvirtComputingResourceSpy.calculateVmMetrics(domainMock, oldStats, newStats);
|
||||
|
||||
Assert.assertEquals(domainInfoMock.nrVirtCpu, metrics.getNumCPUs());
|
||||
Assert.assertEquals(domainInfoMock.maxMem, (long) metrics.getMemoryKBs());
|
||||
Assert.assertEquals(libvirtComputingResourceSpy.getMemoryFreeInKBs(domainMock), (long) metrics.getIntFreeMemoryKBs());
|
||||
Assert.assertEquals(domainInfoMock.memory, (long) metrics.getTargetMemoryKBs());
|
||||
Assert.assertTrue(metrics.getCPUUtilization() > 0);
|
||||
Assert.assertEquals(newStats.getNetworkReadKBs() - oldStats.getNetworkReadKBs(), metrics.getNetworkReadKBs(), 0);
|
||||
Assert.assertEquals(newStats.getNetworkWriteKBs() - oldStats.getNetworkWriteKBs(), metrics.getNetworkWriteKBs(), 0);
|
||||
Assert.assertEquals(newStats.getDiskReadIOs() - oldStats.getDiskReadIOs(), metrics.getDiskReadIOs(), 0);
|
||||
Assert.assertEquals(newStats.getDiskWriteIOs() - oldStats.getDiskWriteIOs(), metrics.getDiskWriteIOs(), 0);
|
||||
Assert.assertEquals(newStats.getDiskReadKBs() - oldStats.getDiskReadKBs(), metrics.getDiskReadKBs(), 0);
|
||||
Assert.assertEquals(newStats.getDiskWriteKBs() - oldStats.getDiskWriteKBs(), metrics.getDiskWriteKBs(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user