Cluster Operations - FreshPerf/PVE4J GitHub Wiki
Cluster Operations
This guide covers cluster-wide operations in PVE4J.
Table of Contents
- Cluster Information
- Cluster Resources
- Resource Filtering
- VMID Management
- High Availability
- Resource Monitoring
- Load Balancing
Cluster Information
Get Cluster Index
import fr.freshperf.pve4j.entities.cluster.PveClusterIndex;
import java.util.List;
try {
List<PveClusterIndex> index = proxmox.getCluster()
.getIndex()
.execute();
for (PveClusterIndex item : index) {
System.out.println("Available endpoint: " + item);
}
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Get Cluster Status
import fr.freshperf.pve4j.entities.cluster.PveClusterStatus;
import java.util.List;
try {
List<PveClusterStatus> status = proxmox.getCluster()
.getStatus()
.execute();
for (PveClusterStatus member : status) {
System.out.println("Name: " + member.getName());
System.out.println("Type: " + member.getType());
System.out.println("Online: " + member.getOnline());
System.out.println("---");
}
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Cluster Resources
List All Resources
import fr.freshperf.pve4j.entities.cluster.resources.PveClusterResources;
import java.util.List;
try {
List<PveClusterResources> resources = proxmox.getCluster()
.getResources()
.execute();
for (PveClusterResources resource : resources) {
System.out.println("Type: " + resource.getType());
System.out.println("ID: " + resource.getId());
System.out.println("Status: " + resource.getStatus());
if (resource.getVmid() != null) {
System.out.println("VMID: " + resource.getVmid());
System.out.println("Name: " + resource.getName());
}
if (resource.getNode() != null) {
System.out.println("Node: " + resource.getNode());
}
System.out.println("---");
}
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Resource Filtering
Filter by Type: Virtual Machines
try {
List<PveClusterResources> vms = proxmox.getCluster()
.getResources("vm")
.execute();
System.out.println("Total VMs: " + vms.size());
for (PveClusterResources vm : vms) {
System.out.printf("VMID: %d, Name: %s, Node: %s, Status: %s%n",
vm.getVmid(), vm.getName(), vm.getNode(), vm.getStatus());
}
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Filter by Type: Nodes
try {
List<PveClusterResources> nodes = proxmox.getCluster()
.getResources("node")
.execute();
System.out.println("Cluster Nodes: " + nodes.size());
for (PveClusterResources 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("---");
}
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Filter by Type: Storage
try {
List<PveClusterResources> storage = proxmox.getCluster()
.getResources("storage")
.execute();
System.out.println("Storage Pools: " + storage.size());
for (PveClusterResources pool : storage) {
System.out.println("Storage: " + pool.getStorage());
System.out.println("Node: " + pool.getNode());
System.out.println("Status: " + pool.getStatus());
if (pool.getDisk() != null && pool.getMaxdisk() != null) {
double usage = (double) pool.getDisk() / pool.getMaxdisk() * 100;
System.out.printf("Usage: %.2f%%%n", usage);
}
System.out.println("---");
}
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
VMID Management
Get Next Available VMID
try {
Integer nextId = proxmox.getCluster()
.getNextId()
.execute();
System.out.println("Next available VMID: " + nextId);
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Use Next VMID for VM Creation
try {
Integer vmid = proxmox.getCluster().getNextId().execute();
PveTask task = proxmox.getNodes()
.get("pve-node-01")
.getQemu()
.create(vmid, PveQemuCreateOptions.builder()
.name("new-vm")
.memory(2048)
.cores(2)
.build())
.waitForCompletion(proxmox)
.execute();
System.out.println("Created VM with VMID: " + vmid);
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
High Availability
PVE4J supports managing Proxmox HA (High Availability) resources.
List HA Resources
import fr.freshperf.pve4j.entities.cluster.ha.PveHaResource;
try {
List<PveHaResource> resources = proxmox.getCluster()
.getHa()
.listResources()
.execute();
for (PveHaResource resource : resources) {
System.out.println("HA Resource: " + resource);
}
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Get a Specific HA Resource
try {
PveHaResource resource = proxmox.getCluster()
.getHa()
.getResource("vm:100")
.execute();
System.out.println("HA Resource: " + resource);
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Create an HA Resource
try {
// Simple creation
proxmox.getCluster()
.getHa()
.createResource("vm:100")
.execute();
System.out.println("HA resource created!");
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Create with Options
import fr.freshperf.pve4j.entities.cluster.ha.PveHaResourceCreateOptions;
try {
PveHaResourceCreateOptions options = PveHaResourceCreateOptions.builder()
// configure options as needed
.build();
proxmox.getCluster()
.getHa()
.createResource("vm:100", options)
.execute();
System.out.println("HA resource created with options!");
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Set HA Resource State
try {
// Possible states: "started", "stopped", "disabled", "ignored"
proxmox.getCluster()
.getHa()
.setResourceState("vm:100", "started")
.execute();
System.out.println("HA resource state updated!");
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Delete an HA Resource
try {
proxmox.getCluster()
.getHa()
.deleteResource("vm:100")
.execute();
System.out.println("HA resource deleted!");
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
Resource Monitoring
Cluster-Wide Resource Overview
public class ClusterMonitor {
public void printClusterOverview(Proxmox proxmox) {
try {
List<PveClusterResources> resources = proxmox.getCluster()
.getResources()
.execute();
Map<String, Integer> typeCounts = new HashMap<>();
for (PveClusterResources resource : resources) {
String type = resource.getType();
typeCounts.put(type, typeCounts.getOrDefault(type, 0) + 1);
}
System.out.println("=== Cluster Overview ===");
typeCounts.forEach((type, count) ->
System.out.println(type + ": " + count));
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
}
}
Find Resources by Criteria
public List<PveClusterResources> findRunningVMs(Proxmox proxmox)
throws ProxmoxAPIError, InterruptedException {
List<PveClusterResources> allVMs = proxmox.getCluster()
.getResources("vm")
.execute();
return allVMs.stream()
.filter(vm -> "running".equals(vm.getStatus()))
.collect(Collectors.toList());
}
public List<PveClusterResources> findVMsByNode(Proxmox proxmox, String nodeName)
throws ProxmoxAPIError, InterruptedException {
List<PveClusterResources> allVMs = proxmox.getCluster()
.getResources("vm")
.execute();
return allVMs.stream()
.filter(vm -> nodeName.equals(vm.getNode()))
.collect(Collectors.toList());
}
Calculate Cluster Statistics
public class ClusterStats {
public void printClusterStats(Proxmox proxmox) {
try {
List<PveClusterResources> vms = proxmox.getCluster()
.getResources("vm")
.execute();
long runningVMs = vms.stream()
.filter(vm -> "running".equals(vm.getStatus()))
.count();
long stoppedVMs = vms.stream()
.filter(vm -> "stopped".equals(vm.getStatus()))
.count();
System.out.println("=== VM Statistics ===");
System.out.println("Total VMs: " + vms.size());
System.out.println("Running: " + runningVMs);
System.out.println("Stopped: " + stoppedVMs);
} catch (ProxmoxAPIError | InterruptedException e) {
e.printStackTrace();
}
}
}
Check Cluster Health
public boolean isClusterHealthy(Proxmox proxmox) {
try {
List<PveClusterStatus> status = proxmox.getCluster()
.getStatus()
.execute();
long onlineNodes = status.stream()
.filter(member -> Boolean.TRUE.equals(member.getOnline()))
.count();
System.out.println("Online nodes: " + onlineNodes + "/" + status.size());
return onlineNodes == status.size();
} catch (Exception e) {
System.err.println("Failed to check cluster health: " + e.getMessage());
return false;
}
}
Load Balancing
Find Node with Lowest Load
public String findLeastLoadedNode(Proxmox proxmox)
throws ProxmoxAPIError, InterruptedException {
List<PveClusterResources> nodes = proxmox.getCluster()
.getResources("node")
.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(PveClusterResources::getNode)
.orElse(null);
}
VM Distribution Across Nodes
public Map<String, Integer> getVMDistribution(Proxmox proxmox)
throws ProxmoxAPIError, InterruptedException {
List<PveClusterResources> vms = proxmox.getCluster()
.getResources("vm")
.execute();
Map<String, Integer> distribution = new HashMap<>();
for (PveClusterResources vm : vms) {
String node = vm.getNode();
if (node != null) {
distribution.put(node, distribution.getOrDefault(node, 0) + 1);
}
}
System.out.println("=== VM Distribution ===");
distribution.forEach((node, count) ->
System.out.println(node + ": " + count + " VMs"));
return distribution;
}
Next Steps
- Node Management - Node-specific operations
- VM Management - Virtual machine management
- Container Management - LXC containers
- Storage Management - Storage operations