Skip to content

Commit

Permalink
fix: exclude VM templates and include containers when calculating a h…
Browse files Browse the repository at this point in the history
…ost's reserveable memory (#40)

Previously, it was only checked for VMs, without taking their Template status into consideration. (A Template VM can't be started, without explicitly removing the flag.). Existing LXCs on a host weren't taken into consideration either.

Now, we'll no longer include VM Template in our calculations. But in exchange we include LXCs now.

Fixes #36.
  • Loading branch information
pborn-ionos authored Dec 18, 2023
1 parent a1666e4 commit db7ace8
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
17 changes: 17 additions & 0 deletions pkg/proxmox/goproxmox/api_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,30 @@ 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 {
reservableMemory -= vm.MaxMem
}
}

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
}

Expand Down
40 changes: 39 additions & 1 deletion pkg/proxmox/goproxmox/api_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit db7ace8

Please sign in to comment.