Virtualization development is a cold direction compared with ordinary development, most of which use Python development, and the use of Java to do virtualization is even less, the data is even less poor, in order to achieve the requirements I also stepped on a lot of pits, Libvirt-java is used to collect resource usage information for KVM virtual machines.
CPU utilization
Libvirt does not directly provide an interface to obtain VM CPU usage, so we need to calculate it ourselves. There are various codes and formulas shared online, most of which are wrong. After testing, I found a relatively accurate calculation formula.
cpu_usage = (cpu_time_now - cpu_time_t_second_ago) * 100 / (t * vCpus * 10^9)
Copy the code
The Java code is as follows
// The CPU time of t seconds ago
long c1 = domain.getInfo().cpuTime;
Thread.sleep(1000);
// The current CPU time
long c2 = domain.getInfo().cpuTime;
// Number of virtual cpus
int vCpus = domain.getMaxVcpus();
// t is 1 second
Double cpuUsage = 100 * (c2 - c1) / (1 * vCpus * Math.pow(10.9));
log.debug("Vm [{}]CPU usage is: {}", uuid, cpuUsage);
Copy the code
Memory usage
Do not use the memory field returned by domain.getInfo(). Although it says the memory in KBytes used by the domain, it really does not mean the amount of memory used by the processes inside the virtual machine. It’s how much memory is allocated to the virtual machine from the perspective of the host machine, and if it’s not configured, it will be the same value as the maxMem field.
The correct way to do this is to use domain-.memoryStats (10), so why enter a 10 for the parameter? This is because 10 represents the amount of information to be returned, and I manually performed the virsh dommemstat uUID test and found that 10 parameters were returned, so I needed to fill in 10. In addition, the unused field value returned by the command is the same as the value of the array tag=8. Finally, we get the unused memory size, making it easier to calculate the memory usage.
The Java code is as follows
MemoryStatistic[] memoryStatistics = domain.memoryStats(10);
Optional<MemoryStatistic> first = Arrays.stream(memoryStatistics).filter(x -> x.getTag() == 8).findFirst();
if (first.isPresent()) {
MemoryStatistic memoryStatistic = first.get();
long unusedMemory = memoryStatistic.getValue();
long maxMemory = domain.getMaxMemory();
double memoryUsage = (maxMemory - unusedMemory) * 100.0 / maxMemory;
log.debug("Vm [{}] memory usage is: {}", uuid, memoryUsage);
}
Copy the code
Nic packet information
Libvirt also does not provide an interface to obtain the VM NETWORK adapter. Therefore, you need to obtain the VM XML file to query the VM NETWORK adapter.
XML is a relative of HTML. It is written much more strictly than HTML. It is more convenient to parse data.
After obtaining the nic name, you can obtain the following statistics:
field | meaning |
---|---|
rx_bytes | Received packet size |
rx_packets | Number of received packets |
rx_errs | Number of received incorrect packets |
rx_drop | Number of discarded packets received |
tx_bytes | Sent packet size |
tx_packets | Number of packets sent |
tx_errs | Number of incorrect packets sent |
tx_drop | Number of discarded packets sent |
The Java code is as follows
String xmlDesc = domain.getXMLDesc(0);
Document document = Jsoup.parse(xmlDesc);
/ / network card
Elements interfaces = document.getElementsByTag("devices").get(0).getElementsByTag("interface");
for (Element inter : interfaces) {
String interName = inter.getElementsByTag("target").get(0).attr("dev");
DomainInterfaceStats domainInterfaceStats = domain.interfaceStats(interName);
log.debug("dev {} stats {}", interName, Json.toJsonString(domainInterfaceStats));
}
Copy the code
Disk IO Information
Libvirt also does not provide an interface to obtain vm disks. You need to obtain the VM XML file to obtain the disk name and statistics. The following data can be obtained:
field | meaning |
---|---|
rd_req | Total read requests |
rd_bytes | The size of the data read |
wr_req | Total number of write requests |
wr_bytes | Size of the data to be written |
errs | Number of failures |
The Java code is as follows
String xmlDesc = domain.getXMLDesc(0);
Document document = Jsoup.parse(xmlDesc);
/ / disk
Elements disks = document.getElementsByTag("devices").get(0).getElementsByTag("disk");
for (Element disk : disks) {
String dev = disk.getElementsByTag("target").get(0).attr("dev");
DomainBlockStats domainBlockStats = domain.blockStats(dev);
log.debug("dev {} stats {}", dev, Json.toJsonString(domainBlockStats));
}
Copy the code
This is the end of collecting VM status information. The more you learn, the more you learn.