VM Management - FreshPerf/PVE4J GitHub Wiki

VM Management

This guide covers comprehensive QEMU virtual machine management using PVE4J.

Table of Contents

Listing VMs

List VMs on a Specific Node

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

try {
    List<PveQemuIndex> vms = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .getIndex()
            .execute();
    
    for (PveQemuIndex vm : vms) {
        System.out.printf("VMID: %d, Name: %s, Status: %s%n",
                vm.getVmid(), vm.getName(), vm.getStatus());
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

List All VMs in Cluster

try {
    List<PveClusterResources> vms = proxmox.getCluster()
            .getResources("vm")
            .execute();
    
    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();
}

VM Information

Get VM Status

try {
    PveQemuStatus status = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .getStatus()
            .execute();
    
    System.out.println("Status: " + status.getStatus());
    System.out.println("CPU Usage: " + status.getCpu());
    System.out.println("Memory: " + status.getMem() + " / " + status.getMaxmem());
    System.out.println("Disk Read: " + status.getDiskread());
    System.out.println("Disk Write: " + status.getDiskwrite());
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Get VM Configuration

try {
    PveQemuConfig config = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .getConfig()
            .execute();
    
    System.out.println("Name: " + config.getName());
    System.out.println("Memory: " + config.getMemory());
    System.out.println("Cores: " + config.getCores());
    System.out.println("Sockets: " + config.getSockets());
    System.out.println("Boot Order: " + config.getBoot());
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Get Pending Configuration Changes

try {
    List<PveQemuPendingChange> pending = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .getPending()
            .execute();
    
    for (PveQemuPendingChange change : pending) {
        System.out.println("Key: " + change.getKey() + " → " + change.getValue());
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Creating VMs

Create a VM with Options

import fr.freshperf.pve4j.entities.nodes.node.qemu.PveQemuCreateOptions;

try {
    PveQemuCreateOptions options = PveQemuCreateOptions.builder()
            .name("web-server")
            .memory(4096)
            .cores(4)
            .sockets(1)
            .ostype("l26")
            .scsihw("virtio-scsi-pci")
            .boot("order=scsi0;ide2;net0")
            .agent(true)
            .onboot(true)
            .build();
    
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .create(100, options)
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM created!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Create a Minimal VM

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .create(101)
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM 101 created with defaults!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Lifecycle Operations

Start a VM

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .start()
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM started successfully!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Stop a VM (Hard)

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .stop()
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM stopped!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Shutdown a VM (Graceful ACPI)

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .shutdown()
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM shutdown!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Reboot / Reset / Suspend / Resume

// Graceful reboot (ACPI)
vm.reboot().waitForCompletion(proxmox).execute();

// Hard reset
vm.reset().waitForCompletion(proxmox).execute();

// Suspend
vm.suspend().waitForCompletion(proxmox).execute();

// Resume
vm.resume().waitForCompletion(proxmox).execute();

Delete a VM

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .delete()
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM deleted!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

VM Configuration

Update Configuration (Asynchronous - POST)

try {
    PveQemuConfigUpdateOptions options = PveQemuConfigUpdateOptions.builder()
            .memory(4096)
            .cores(4)
            .description("Updated via PVE4J")
            .build();
    
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .updateConfig(options)
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM configuration updated!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Update Configuration (Synchronous - PUT)

try {
    PveQemuConfigUpdateOptions options = PveQemuConfigUpdateOptions.builder()
            .memory(2048)
            .build();
    
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .updateConfigSync(options)
            .execute();
    
    System.out.println("VM configuration updated synchronously!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Cloning VMs

Simple Clone

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(9000)
            .cloneVm(100)
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM cloned!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Clone with Options

import fr.freshperf.pve4j.entities.nodes.node.qemu.PveQemuCloneOptions;

try {
    PveQemuCloneOptions options = PveQemuCloneOptions.builder()
            .name("web-server-01")
            .description("Web server cloned from template")
            .full(true)  // Full clone instead of linked clone
            .storage("local-lvm")
            .build();
    
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(9000)
            .cloneVm(100, options)
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM cloned with options!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Disk Management

Resize a Disk

try {
    // Increase by 10GB
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .resize("scsi0", "+10G")
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("Disk resized!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Move a Disk

import fr.freshperf.pve4j.entities.nodes.node.qemu.PveQemuMoveDiskOptions;

try {
    PveQemuMoveDiskOptions options = PveQemuMoveDiskOptions.builder()
            .storage("fast-ssd")
            .delete(true)  // Delete original after move
            .build();
    
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .moveDisk("scsi0", options)
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("Disk moved!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Unlink Disks

try {
    proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .unlink("unused0")
            .execute();
    
    System.out.println("Disk unlinked!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Backup

Create a Backup

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .backup()
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("Backup completed!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Backup with Options

import fr.freshperf.pve4j.entities.nodes.node.qemu.PveQemuBackupOptions;

try {
    PveQemuBackupOptions options = PveQemuBackupOptions.builder()
            .storage("backup-storage")
            .mode("snapshot")
            .compress("zstd")
            .notesTemplate("{{guestname}} backup")
            .build();
    
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .backup(options)
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("Backup completed with options!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Migration

Migrate a VM to Another Node

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .migrate("pve-node-02")
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM migrated!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Online Migration with Storage

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .migrate("pve-node-02", true, "local-lvm")  // online, target storage
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("Online migration completed!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Templates

Convert a VM to Template

try {
    PveTask task = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(9000)
            .template()
            .waitForCompletion(proxmox)
            .execute();
    
    System.out.println("VM converted to template!");
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Guest Agent

The QEMU guest agent allows communication with the VM's operating system. The VM must have the qemu-guest-agent package installed and the agent enabled in the VM configuration.

System Information

var agent = proxmox.getNodes()
        .get("pve-node-01")
        .getQemu()
        .get(100)
        .getAgent();

try {
    // Hostname
    var hostname = agent.getHostName().execute();
    System.out.println("Hostname: " + hostname);
    
    // OS info
    var osInfo = agent.getOsInfo().execute();
    System.out.println("OS: " + osInfo);
    
    // Time and timezone
    var time = agent.getTime().execute();
    var timezone = agent.getTimezone().execute();
    
    // Users
    var users = agent.getUsers().execute();
    
    // vCPUs
    var vcpus = agent.getVcpus().execute();
    
    // Network interfaces
    var interfaces = agent.getNetworkInterfaces().execute();
    
    // Agent info
    var info = agent.getInfo().execute();
    
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Filesystem Operations

try {
    // Get filesystem info
    var fsInfo = agent.getFsInfo().execute();
    
    // Freeze filesystems (for consistent snapshots)
    var freezeResult = agent.fsFreeze().execute();
    
    // Check freeze status
    var freezeStatus = agent.getFsFreezeStatus().execute();
    
    // Thaw filesystems
    var thawResult = agent.fsThaw().execute();
    
    // Trim unused blocks
    var trimResult = agent.fstrim().execute();
    
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Guest Agent Commands

try {
    // Ping the agent
    agent.ping().execute();
    
    // Graceful shutdown via agent
    agent.shutdown().execute();
    
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Cloud-Init

Access the Cloud-Init configuration for a VM:

var cloudInit = proxmox.getNodes()
        .get("pve-node-01")
        .getQemu()
        .get(100)
        .getCloudInit();

VNC Access

Get VNC Proxy Information

try {
    PveQemuVmVncProxy vnc = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .getVnc()
            .getVncProxy()
            .execute();
    
    System.out.println("VNC Port: " + vnc.getPort());
    System.out.println("VNC Ticket: " + vnc.getTicket());
    System.out.println("VNC User: " + vnc.getUser());
    System.out.println("VNC Certificate: " + vnc.getCert());
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

RRD Statistics

Get VM Performance Data

try {
    // Available timeframes: "hour", "day", "week", "month", "year"
    List<PveQemuRrdDataPoint> rrdData = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .getRrdData("hour")
            .execute();
    
    for (PveQemuRrdDataPoint point : rrdData) {
        System.out.println("Data point: " + point);
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

With Options

import fr.freshperf.pve4j.entities.nodes.node.qemu.PveQemuRrdDataOptions;

try {
    PveQemuRrdDataOptions options = PveQemuRrdDataOptions.builder()
            .cf("AVERAGE")  // or "MAX"
            .build();
    
    List<PveQemuRrdDataPoint> rrdData = proxmox.getNodes()
            .get("pve-node-01")
            .getQemu()
            .get(100)
            .getRrdData("day", options)
            .execute();
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Snapshots

For detailed snapshot management, see the Snapshot Management guide.

Quick Example

// Create a snapshot
proxmox.getNodes()
        .get("pve-node-01")
        .getQemu()
        .get(100)
        .getSnapshots()
        .create("pre-upgrade", PveQemuSnapshotCreateOptions.builder()
                .description("Before system upgrade")
                .build())
        .waitForCompletion(proxmox)
        .execute();

// List snapshots
List<PveQemuSnapshot> snapshots = proxmox.getNodes()
        .get("pve-node-01")
        .getQemu()
        .get(100)
        .getSnapshots()
        .list()
        .execute();

// Rollback
proxmox.getNodes()
        .get("pve-node-01")
        .getQemu()
        .get(100)
        .getSnapshots()
        .get("pre-upgrade")
        .rollback()
        .waitForCompletion(proxmox)
        .execute();

Next Steps