diff --git a/pkg/proxmox/goproxmox/api_client.go b/pkg/proxmox/goproxmox/api_client.go index 8d2b535d..b4ad09b4 100644 --- a/pkg/proxmox/goproxmox/api_client.go +++ b/pkg/proxmox/goproxmox/api_client.go @@ -195,6 +195,10 @@ func (c *APIClient) GetReservableMemoryBytes(ctx context.Context, nodeName strin } for _, vm := range vms { + // Ignore VM Templates, as they can't be started. + if vm.Template { + continue + } if reservableMemory < vm.MaxMem { reservableMemory = 0 } else { @@ -202,6 +206,19 @@ func (c *APIClient) GetReservableMemoryBytes(ctx context.Context, nodeName strin } } + containers, err := node.Containers(ctx) + if err != nil { + return 0, fmt.Errorf("cannot list containers for node %s: %w", nodeName, err) + } + + for _, ct := range containers { + if reservableMemory < ct.MaxMem { + reservableMemory = 0 + } else { + reservableMemory -= ct.MaxMem + } + } + return reservableMemory, nil } diff --git a/pkg/proxmox/goproxmox/api_client_test.go b/pkg/proxmox/goproxmox/api_client_test.go index 233cea4d..1a6f8496 100644 --- a/pkg/proxmox/goproxmox/api_client_test.go +++ b/pkg/proxmox/goproxmox/api_client_test.go @@ -64,7 +64,45 @@ func TestProxmoxAPIClient_GetReservableMemoryBytes(t *testing.T) { newJSONResponder(200, proxmox.Node{Memory: proxmox.Memory{Total: 30}})) httpmock.RegisterResponder(http.MethodGet, `=~/nodes/test/qemu`, - newJSONResponder(200, proxmox.VirtualMachines{{MaxMem: test.maxMem}})) + // Somehow, setting proxmox.VirtualMachines{} ALWAYS has `Template: true` when defined this way. + // So it's better to just define a legitimate json response + newJSONResponder(200, []interface{}{ + map[string]interface{}{ + "name": "legit-worker", + "maxmem": test.maxMem, + "vmid": 1111, + "diskwrite": 0, + "mem": 0, + "uptime": 0, + "disk": 0, + "cpu": 0, + "cpus": 1, + "status": "stopped", + "netout": 0, + "maxdisk": 0, + "netin": 0, + "diskread": 0, + }, + map[string]interface{}{ + "name": "template", + "maxmem": 102400, + "vmid": 2222, + "diskwrite": 0, + "mem": 0, + "uptime": 0, + "disk": 0, + "cpu": 0, + "template": 1, + "cpus": 1, + "status": "stopped", + "netout": 0, + "maxdisk": 0, + "netin": 0, + "diskread": 0, + }})) + + httpmock.RegisterResponder(http.MethodGet, `=~/nodes/test/lxc`, + newJSONResponder(200, proxmox.Containers{})) reservable, err := client.GetReservableMemoryBytes(context.Background(), "test") require.NoError(t, err)