Storage Management - FreshPerf/PVE4J GitHub Wiki

Storage Management

This guide covers storage management operations in PVE4J.

Table of Contents

Listing Storage

List Storage on a Specific Node

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

try {
    List<PveStorageIndex> storage = proxmox.getNodes()
            .get("pve-node-01")
            .getStorage()
            .getIndex()
            .execute();
    
    for (PveStorageIndex pool : storage) {
        System.out.println("Storage: " + pool.getStorage());
        System.out.println("Type: " + pool.getType());
        System.out.println("Content: " + pool.getContent());
        System.out.println("Active: " + pool.getActive());
        System.out.println("---");
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

List All Storage in Cluster

import fr.freshperf.pve4j.entities.cluster.resources.PveClusterResources;
import java.util.List;

try {
    List<PveClusterResources> storage = proxmox.getCluster()
            .getResources("storage")
            .execute();
    
    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) {
            long usedGB = pool.getDisk() / (1024 * 1024 * 1024);
            long totalGB = pool.getMaxdisk() / (1024 * 1024 * 1024);
            double usage = (double) pool.getDisk() / pool.getMaxdisk() * 100;
            
            System.out.printf("Usage: %d GB / %d GB (%.2f%%)%n", usedGB, totalGB, usage);
        }
        
        System.out.println("---");
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Storage Information

Get Storage Status

import fr.freshperf.pve4j.entities.nodes.node.storage.PveStorageStatus;

try {
    PveStorageStatus status = proxmox.getNodes()
            .get("pve-node-01")
            .getStorage()
            .get("local-lvm")
            .getStatus()
            .execute();
    
    System.out.println("Storage: " + status.getStorage());
    System.out.println("Type: " + status.getType());
    System.out.println("Total: " + status.getTotal() + " bytes");
    System.out.println("Used: " + status.getUsed() + " bytes");
    System.out.println("Available: " + status.getAvail() + " bytes");
    System.out.println("Active: " + status.getActive());
    System.out.println("Content: " + status.getContent());
    
    if (status.getTotal() != null && status.getUsed() != null) {
        double usage = (double) status.getUsed() / status.getTotal() * 100;
        System.out.printf("Usage: %.2f%%%n", usage);
    }
    
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Storage Content

Get Storage Content

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

try {
    List<PveStorageContent> content = proxmox.getNodes()
            .get("pve-node-01")
            .getStorage()
            .get("local-lvm")
            .getContent()
            .execute();
    
    System.out.println("Storage Content:");
    
    for (PveStorageContent item : content) {
        System.out.println("Volume ID: " + item.getVolid());
        System.out.println("Content Type: " + item.getContent());
        System.out.println("Format: " + item.getFormat());
        System.out.println("Size: " + item.getSize() + " bytes");
        
        if (item.getVmid() != null) {
            System.out.println("VMID: " + item.getVmid());
        }
        
        System.out.println("---");
    }
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Storage Statistics

Get RRD Statistics

import fr.freshperf.pve4j.entities.nodes.node.storage.PveStorageRrd;

try {
    PveStorageRrd rrd = proxmox.getNodes()
            .get("pve-node-01")
            .getStorage()
            .get("local-lvm")
            .getRrd()
            .execute();
    
    System.out.println("Storage RRD Statistics retrieved");
    // RRD data contains time-series statistics for graphing
    
} catch (ProxmoxAPIError | InterruptedException e) {
    e.printStackTrace();
}

Storage Operations

Check Storage Availability

public boolean isStorageAvailable(Proxmox proxmox, String node, String storage) {
    try {
        PveStorageStatus status = proxmox.getNodes()
                .get(node)
                .getStorage()
                .get(storage)
                .getStatus()
                .execute();
        
        return Boolean.TRUE.equals(status.getActive());
        
    } catch (Exception e) {
        System.err.println("Failed to check storage availability: " + e.getMessage());
        return false;
    }
}

Find Storage by Type

public List<PveStorageIndex> findStorageByType(Proxmox proxmox, String node, String type) 
        throws ProxmoxAPIError, InterruptedException {
    
    List<PveStorageIndex> allStorage = proxmox.getNodes()
            .get(node)
            .getStorage()
            .getIndex()
            .execute();
    
    return allStorage.stream()
            .filter(storage -> type.equals(storage.getType()))
            .collect(Collectors.toList());
}

// Usage
List<PveStorageIndex> lvmStorage = findStorageByType(proxmox, "pve-node-01", "lvm");
List<PveStorageIndex> nfsStorage = findStorageByType(proxmox, "pve-node-01", "nfs");

Find Storage with Sufficient Space

public String findStorageWithSpace(Proxmox proxmox, String node, long requiredBytes) 
        throws ProxmoxAPIError, InterruptedException {
    
    List<PveStorageIndex> storage = proxmox.getNodes()
            .get(node)
            .getStorage()
            .getIndex()
            .execute();
    
    for (PveStorageIndex pool : storage) {
        if (!Boolean.TRUE.equals(pool.getActive())) {
            continue;
        }
        
        try {
            PveStorageStatus status = proxmox.getNodes()
                    .get(node)
                    .getStorage()
                    .get(pool.getStorage())
                    .getStatus()
                    .execute();
            
            if (status.getAvail() != null && status.getAvail() >= requiredBytes) {
                return pool.getStorage();
            }
            
        } catch (Exception e) {
            // Skip this storage on error
            continue;
        }
    }
    
    return null;
}

Storage Monitoring

Monitor Storage Usage

public class StorageMonitor {
    
    public void monitorStorage(Proxmox proxmox, String node, String storage) {
        try {
            PveStorageStatus status = proxmox.getNodes()
                    .get(node)
                    .getStorage()
                    .get(storage)
                    .getStatus()
                    .execute();
            
            if (status.getTotal() != null && status.getUsed() != null) {
                double usagePercent = (double) status.getUsed() / status.getTotal() * 100;
                
                System.out.printf("Storage %s: %.2f%% used%n", storage, usagePercent);
                
                if (usagePercent > 90) {
                    System.err.println("CRITICAL: Storage usage above 90%!");
                } else if (usagePercent > 80) {
                    System.err.println("WARNING: Storage usage above 80%!");
                }
            }
            
        } catch (ProxmoxAPIError | InterruptedException e) {
            System.err.println("Failed to monitor storage: " + e.getMessage());
        }
    }
}

List VM Disks on Storage

public void listVMDisks(Proxmox proxmox, String node, String storage) {
    try {
        List<PveStorageContent> content = proxmox.getNodes()
                .get(node)
                .getStorage()
                .get(storage)
                .getContent()
                .execute();
        
        System.out.println("VM Disks on " + storage + ":");
        
        content.stream()
                .filter(item -> "images".equals(item.getContent()))
                .forEach(disk -> {
                    long sizeGB = disk.getSize() / (1024 * 1024 * 1024);
                    System.out.printf("  VMID %d: %s (%d GB)%n", 
                            disk.getVmid(), disk.getVolid(), sizeGB);
                });
        
    } catch (ProxmoxAPIError | InterruptedException e) {
        e.printStackTrace();
    }
}

Generate Storage Report

public class StorageReporter {
    
    public void generateStorageReport(Proxmox proxmox, String node) {
        try {
            List<PveStorageIndex> storage = proxmox.getNodes()
                    .get(node)
                    .getStorage()
                    .getIndex()
                    .execute();
            
            System.out.println("=== Storage Report for " + node + " ===\n");
            
            for (PveStorageIndex pool : storage) {
                try {
                    PveStorageStatus status = proxmox.getNodes()
                            .get(node)
                            .getStorage()
                            .get(pool.getStorage())
                            .getStatus()
                            .execute();
                    
                    System.out.println("Storage: " + pool.getStorage());
                    System.out.println("Type: " + pool.getType());
                    System.out.println("Active: " + pool.getActive());
                    
                    if (status.getTotal() != null) {
                        long totalGB = status.getTotal() / (1024 * 1024 * 1024);
                        long usedGB = status.getUsed() / (1024 * 1024 * 1024);
                        long availGB = status.getAvail() / (1024 * 1024 * 1024);
                        double usage = (double) status.getUsed() / status.getTotal() * 100;
                        
                        System.out.println("Total: " + totalGB + " GB");
                        System.out.println("Used: " + usedGB + " GB");
                        System.out.println("Available: " + availGB + " GB");
                        System.out.printf("Usage: %.2f%%%n", usage);
                    }
                    
                    System.out.println("---\n");
                    
                } catch (Exception e) {
                    System.err.println("Failed to get status for " + pool.getStorage());
                }
            }
            
        } catch (ProxmoxAPIError | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Common Storage Types

Local Storage

  • Type dir - Local directory storage. Common for ISO images, container templates, backups.
  • Type lvm / lvmthin - Local LVM storage. Common for VM disks, high-performance workloads.

Network Storage

  • Type nfs - NFS storage. Shared storage across cluster nodes.
  • Type cifs - CIFS/SMB storage. Windows file shares.
  • Type glusterfs - GlusterFS. Distributed storage.
  • Type rbd - Ceph RBD. Distributed block storage.

Next Steps