--- name: manage-proxmox-pool version: 1.0.0 description: Manage Proxmox VE resource pools — CRUD, membership, and extended CPU/storage quota enforcement (not native to Proxmox) tags: [proxmox, pools, quota, api, shell] --- # Manage Proxmox Pool Assumes `my_auth`, `my_base_url`, `my_curl` are set (see `auth-proxmox-api` skill). ## Pool Endpoints ``` GET /api2/json/pools # list all pools POST /api2/json/pools # create a pool GET /api2/json/pools/{poolid} # get pool details + members PUT /api2/json/pools/{poolid} # update pool (comment, add/remove members) DELETE /api2/json/pools/{poolid} # delete pool (does NOT delete member VMs/CTs) ``` ## List Pools (TSV) ```sh fn_pool_list() { ( ${my_curl} -H "${my_auth}" "${my_base_url}/pools" | jq -r '.data[] | [.poolid, .comment] | @tsv' ); } ``` ## Get Pool Members ```sh fn_pool_get() { ( my_pool="${1}" ${my_curl} -H "${my_auth}" "${my_base_url}/pools/${my_pool}" | jq -r '.data.members[] | [.vmid, .type, .name, .status, .maxcpu, .maxmem, .maxdisk] | @tsv' ); } ``` Response member fields: `vmid`, `type` (`qemu`|`lxc`), `name`, `status`, `maxcpu`, `maxmem` (bytes), `maxdisk` (bytes). ## Create Pool ```sh fn_pool_create() { ( my_pool="${1}" my_comment="${2:-}" ${my_curl} -H "${my_auth}" \ -X POST "${my_base_url}/pools" \ --data-urlencode "poolid=${my_pool}" \ --data-urlencode "comment=${my_comment}" ); } ``` ## Add Member to Pool ```sh fn_pool_add_member() { ( my_pool="${1}" my_vmid="${2}" ${my_curl} -H "${my_auth}" \ -X PUT "${my_base_url}/pools/${my_pool}" \ --data-urlencode "vms=${my_vmid}" ); } ``` ## Delete Pool ```sh fn_pool_delete() { ( my_pool="${1}" ${my_curl} -H "${my_auth}" \ -X DELETE "${my_base_url}/pools/${my_pool}" ); } ``` --- ## Extended Quota Enforcement Proxmox has no native CPU/storage caps per pool. This project enforces them as a **pre-flight check** before any resource is created or resized. ### Quota Config (ENV) ```sh PROXMOX_POOL_MAX_CORES=32 PROXMOX_POOL_MAX_STORAGE_GB=500 ``` ### Calculate Current Pool Usage ```sh fn_pool_usage() { ( my_pool="${1}" my_members_json="$( ${my_curl} -H "${my_auth}" "${my_base_url}/pools/${my_pool}" | jq '.data.members' )" my_used_cores="$( printf '%s' "${my_members_json}" | jq '[.[].maxcpu] | add // 0' )" # maxdisk is bytes; convert to GB my_used_storage_gb="$( printf '%s' "${my_members_json}" | jq '([.[].maxdisk] | add // 0) / 1073741824 | ceil' )" printf '%s\t%s\n' "${my_used_cores}" "${my_used_storage_gb}" ); } ``` ### Pre-flight Quota Check Run before creating or resizing any resource in a pool. Returns non-zero and prints an error if the operation would exceed quota. ```sh fn_pool_preflight() { ( my_pool="${1}" my_new_cores="${2}" my_new_storage_gb="${3}" my_max_cores="${PROXMOX_POOL_MAX_CORES:-}" my_max_storage="${PROXMOX_POOL_MAX_STORAGE_GB:-}" if test -z "${my_max_cores}" && test -z "${my_max_storage}"; then return 0 fi my_usage="$(fn_pool_usage "${my_pool}")" my_used_cores="$(printf '%s' "${my_usage}" | cut -f1)" my_used_storage="$(printf '%s' "${my_usage}" | cut -f2)" my_total_cores="$((my_used_cores + my_new_cores))" my_total_storage="$((my_used_storage + my_new_storage_gb))" if test -n "${my_max_cores}" && test "${my_total_cores}" -gt "${my_max_cores}"; then printf 'ERROR: pool %s would exceed CPU quota: %d + %d = %d > %d\n' \ "${my_pool}" "${my_used_cores}" "${my_new_cores}" \ "${my_total_cores}" "${my_max_cores}" >&2 return 1 fi if test -n "${my_max_storage}" && test "${my_total_storage}" -gt "${my_max_storage}"; then printf 'ERROR: pool %s would exceed storage quota: %dGB + %dGB = %dGB > %dGB\n' \ "${my_pool}" "${my_used_storage}" "${my_new_storage_gb}" \ "${my_total_storage}" "${my_max_storage}" >&2 return 1 fi return 0 ); } ``` ### Show Quota Report (TSV) ```sh fn_pool_quota_report() { ( my_pool="${1}" my_max_cores="${PROXMOX_POOL_MAX_CORES:-unlimited}" my_max_storage="${PROXMOX_POOL_MAX_STORAGE_GB:-unlimited}" my_usage="$(fn_pool_usage "${my_pool}")" my_used_cores="$(printf '%s' "${my_usage}" | cut -f1)" my_used_storage="$(printf '%s' "${my_usage}" | cut -f2)" printf 'pool\tresource\tused\tlimit\n' printf '%s\tcores\t%s\t%s\n' "${my_pool}" "${my_used_cores}" "${my_max_cores}" printf '%s\tstorage_gb\t%s\t%s\n' "${my_pool}" "${my_used_storage}" "${my_max_storage}" ); } ``` ## Notes - Pool membership is assigned at CT/VM creation time via the `pool` param. - Deleting a pool does not delete its member VMs/CTs. - `maxdisk` from pool members includes rootfs + all mountpoints combined. - The quota check is a pre-flight only — it does not prevent direct Proxmox API access.