Node Management - FreshPerf/PVE4J GitHub Wiki

Node Management

This guide covers node-specific operations in PVE4J.

Table of Contents

Listing Nodes

List All Nodes in Cluster

import fr.freshperf.pve4j.entities.nodes.PveNodesIndex;
import java.util.List;

try {
    List<PveNodesIndex> nodes = proxmox.getNodes()
            .getIndex()
            .execute();
    
    for (PveNodesIndex node : nodes) {
        System.out.println("Node: " + node.getNode());
        System.out.println("Status: " + node.getStatus());
        System.out.println("CPU: " + node.getCpu());
        System.out.println("Memory: " + node.getMem() + " / " + node.getMaxmem());
        System.out.println("Uptime: " + node.getUptime());
        System.out.println("---");
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Node Information

Get Node Status

import fr.freshperf.pve4j.entities.nodes.node.PveNodeStatus;

try {
    PveNodeStatus status = proxmox.getNodes()
            .get("pve-node-01")
            .getStatus()
            .execute();
    
    System.out.println("PVE Version: " + status.getPveversion());
    System.out.println("CPU Usage: " + status.getCpu());
    System.out.println("Uptime: " + status.getUptime());
    System.out.println("Load Average: " + String.join(", ", status.getLoadavg()));
    
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

The PveNodeStatus object contains several nested objects described below.

Memory (PveNodeMemory)

PveNodeMemory memory = status.getMemory();
System.out.println("Total: " + memory.getTotal());
System.out.println("Used:  " + memory.getUsed());
System.out.println("Free:  " + memory.getFree());
System.out.println("Available: " + memory.getAvailable());
Method Return type Description
getTotal() long Total memory in bytes
getUsed() long Used memory in bytes
getFree() long Free memory in bytes
getAvailable() long Available memory in bytes

Swap (PveNodeSwap)

PveNodeSwap swap = status.getSwap();
System.out.println("Total: " + swap.getTotal());
System.out.println("Used:  " + swap.getUsed());
System.out.println("Free:  " + swap.getFree());
Method Return type Description
getTotal() long Total swap in bytes
getUsed() long Used swap in bytes
getFree() long Free swap in bytes

Root Filesystem (PveNodeRootfs)

PveNodeRootfs rootfs = status.getRootfs();
System.out.println("Total: " + rootfs.getTotal());
System.out.println("Used:  " + rootfs.getUsed());
System.out.println("Free:  " + rootfs.getFree());
System.out.println("Avail: " + rootfs.getAvail());
Method Return type Description
getTotal() long Total root filesystem size in bytes
getUsed() long Used bytes on root filesystem
getFree() long Free bytes on root filesystem
getAvail() long Available bytes on root filesystem

CPU Info (PveNodeCpuInfo)

PveNodeCpuInfo cpuinfo = status.getCpuinfo();
System.out.println("Model:   " + cpuinfo.getModel());
System.out.println("Cores:   " + cpuinfo.getCores());
System.out.println("CPUs:    " + cpuinfo.getCpus());
System.out.println("Sockets: " + cpuinfo.getSockets());
Method Return type Description
getModel() String CPU model name
getCores() int Number of physical cores
getCpus() int Number of logical threads
getSockets() int Number of CPU sockets

Boot Info (PveNodeBootInfo)

PveNodeBootInfo bootInfo = status.getBootInfo();
System.out.println("Mode: " + bootInfo.getMode());
System.out.println("Secure Boot: " + bootInfo.getSecureboot());
Method Return type Description
getMode() String Boot firmware mode ("efi" or "legacy-bios")
getSecureboot() Boolean Whether secure boot is enabled (only applicable for EFI mode)

Current Kernel (PveNodeCurrentKernel)

PveNodeCurrentKernel kernel = status.getCurrentKernel();
System.out.println("Sysname: " + kernel.getSysname());
System.out.println("Release: " + kernel.getRelease());
System.out.println("Version: " + kernel.getVersion());
System.out.println("Machine: " + kernel.getMachine());
Method Return type Description
getSysname() String OS kernel name (e.g. "Linux")
getRelease() String OS kernel release (e.g. "6.8.0")
getVersion() String OS kernel version with build info
getMachine() String Hardware architecture type

Get Node Version

import fr.freshperf.pve4j.entities.nodes.node.PveNodeVersion;

try {
    PveNodeVersion version = proxmox.getNodes()
            .get("pve-node-01")
            .getVersion()
            .execute();
    
    System.out.println("Proxmox Version: " + version.getVersion());
    System.out.println("Release: " + version.getRelease());
    System.out.println("Kernel: " + version.getKversion());
    
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Get Node Index

import fr.freshperf.pve4j.entities.nodes.node.PveNodeIndex;
import java.util.List;

try {
    List<PveNodeIndex> index = proxmox.getNodes()
            .get("pve-node-01")
            .getIndex()
            .execute();
    
    for (PveNodeIndex item : index) {
        System.out.println("Available endpoint: " + item);
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Node Resources

Access Node Resources

// Access QEMU VMs on a node
var qemu = proxmox.getNodes().get("pve-node-01").getQemu();

// Access LXC containers on a node
var lxc = proxmox.getNodes().get("pve-node-01").getLxc();

// Access storage on a node
var storage = proxmox.getNodes().get("pve-node-01").getStorage();

Node Monitoring

Monitor Node Health

public class NodeHealthMonitor {
    
    public void checkNodeHealth(Proxmox proxmox, String nodeName) {
        try {
            PveNodeStatus status = proxmox.getNodes()
                    .get(nodeName)
                    .getStatus()
                    .execute();
            
            // Check CPU
            if (status.getCpu() != null) {
                double cpuPercent = status.getCpu() * 100;
                if (cpuPercent > 90) {
                    System.err.println("WARNING: Node " + nodeName + 
                            " CPU usage is high: " + String.format("%.2f%%", cpuPercent));
                }
            }
            
            // Check Memory
            if (status.getMemory() != null) {
                long total = status.getMemory().getTotal();
                long used = status.getMemory().getUsed();
                double memPercent = (double) used / total * 100;
                
                if (memPercent > 90) {
                    System.err.println("WARNING: Node " + nodeName + 
                            " memory usage is high: " + String.format("%.2f%%", memPercent));
                }
            }
            
            System.out.println("Node " + nodeName + " health check completed");
            
        } catch (ProxmoxAPIError | InterruptedException e) {
            System.err.println("Health check failed for node " + nodeName + ": " + e.getMessage());
        }
    }
}

Generate Node Report

public class NodeReporter {
    
    public void generateNodeReport(Proxmox proxmox) {
        try {
            List<PveNodesIndex> nodes = proxmox.getNodes()
                    .getIndex()
                    .execute();
            
            System.out.println("=== Node Report ===\n");
            
            for (PveNodesIndex node : nodes) {
                System.out.println("Node: " + node.getNode());
                System.out.println("Status: " + node.getStatus());
                
                if (node.getCpu() != null) {
                    System.out.printf("CPU: %.2f%%%n", node.getCpu() * 100);
                }
                
                if (node.getMem() != null && node.getMaxmem() != null) {
                    double memPercent = (double) node.getMem() / node.getMaxmem() * 100;
                    long memGB = node.getMem() / (1024 * 1024 * 1024);
                    long maxMemGB = node.getMaxmem() / (1024 * 1024 * 1024);
                    System.out.printf("Memory: %d GB / %d GB (%.2f%%)%n", 
                            memGB, maxMemGB, memPercent);
                }
                
                if (node.getUptime() != null) {
                    long days = node.getUptime() / 86400;
                    long hours = (node.getUptime() % 86400) / 3600;
                    System.out.printf("Uptime: %d days, %d hours%n", days, hours);
                }
                
                System.out.println("---\n");
            }
            
        } catch (ProxmoxAPIError | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Check Node Availability

public boolean isNodeOnline(Proxmox proxmox, String nodeName) {
    try {
        List<PveNodesIndex> nodes = proxmox.getNodes()
                .getIndex()
                .execute();
        
        return nodes.stream()
                .filter(node -> nodeName.equals(node.getNode()))
                .anyMatch(node -> "online".equals(node.getStatus()));
        
    } catch (Exception e) {
        return false;
    }
}

Select Node with Lowest Load

public String selectBestNode(Proxmox proxmox) 
        throws ProxmoxAPIError, InterruptedException {
    
    List<PveNodesIndex> nodes = proxmox.getNodes()
            .getIndex()
            .execute();
    
    return nodes.stream()
            .filter(node -> "online".equals(node.getStatus()))
            .min(Comparator.comparingDouble(node -> {
                if (node.getCpu() != null) {
                    return node.getCpu();
                }
                return Double.MAX_VALUE;
            }))
            .map(PveNodesIndex::getNode)
            .orElse(null);
}

Next Steps