From 7df90da9c8305eda0db373c66a47378b9ea609c8 Mon Sep 17 00:00:00 2001 From: Mahmood Ali Date: Fri, 26 Mar 2021 16:07:12 -0400 Subject: [PATCH] oversubscription: adds CLI and API support This commit updates the API to pass the MemoryMaxMB field, and the CLI to show the max set for the task. Also, start parsing the MemoryMaxMB in hcl2, as it's set by tags. A sample CLI output; note the additional `Max: ` for "task": ``` $ nomad alloc status 96fbeb0b ID = 96fbeb0b-a0b3-aa95-62bf-b8a39492fd5c [...] Task "cgroup-fetcher" is "running" Task Resources CPU Memory Disk Addresses 0/500 MHz 32 MiB/20 MiB 300 MiB Task Events: [...] Task "task" is "running" Task Resources CPU Memory Disk Addresses 0/500 MHz 176 KiB/20 MiB 300 MiB Max: 30 MiB Task Events: [...] ``` --- api/allocations.go | 3 +- api/resources.go | 13 ++--- command/agent/job_endpoint.go | 4 ++ command/agent/job_endpoint_test.go | 47 +++++++++++++++++++ command/alloc_status.go | 13 ++++- .../hashicorp/nomad/api/allocations.go | 3 +- .../hashicorp/nomad/api/resources.go | 13 ++--- 7 files changed, 81 insertions(+), 15 deletions(-) diff --git a/api/allocations.go b/api/allocations.go index be4058977..0c1a01b1a 100644 --- a/api/allocations.go +++ b/api/allocations.go @@ -511,7 +511,8 @@ type AllocatedCpuResources struct { } type AllocatedMemoryResources struct { - MemoryMB int64 + MemoryMB int64 + MemoryMaxMB int64 } type AllocatedDeviceResource struct { diff --git a/api/resources.go b/api/resources.go index ae420b22f..d9bd49476 100644 --- a/api/resources.go +++ b/api/resources.go @@ -7,12 +7,13 @@ import ( // Resources encapsulates the required resources of // a given task or task group. type Resources struct { - CPU *int `hcl:"cpu,optional"` - Cores *int `hcl:"cores,optional"` - MemoryMB *int `mapstructure:"memory" hcl:"memory,optional"` - DiskMB *int `mapstructure:"disk" hcl:"disk,optional"` - Networks []*NetworkResource `hcl:"network,block"` - Devices []*RequestedDevice `hcl:"device,block"` + CPU *int `hcl:"cpu,optional"` + Cores *int `hcl:"cores,optional"` + MemoryMB *int `mapstructure:"memory" hcl:"memory,optional"` + MemoryMaxMB *int `mapstructure:"memory_max" hcl:"memory_max,optional"` + DiskMB *int `mapstructure:"disk" hcl:"disk,optional"` + Networks []*NetworkResource `hcl:"network,block"` + Devices []*RequestedDevice `hcl:"device,block"` // COMPAT(0.10) // XXX Deprecated. Please do not use. The field will be removed in Nomad diff --git a/command/agent/job_endpoint.go b/command/agent/job_endpoint.go index 79e44bba9..3b358c447 100644 --- a/command/agent/job_endpoint.go +++ b/command/agent/job_endpoint.go @@ -1193,6 +1193,10 @@ func ApiResourcesToStructs(in *api.Resources) *structs.Resources { out.Cores = *in.Cores } + if in.MemoryMaxMB != nil { + out.MemoryMaxMB = *in.MemoryMaxMB + } + // COMPAT(0.10): Only being used to issue warnings if in.IOPS != nil { out.IOPS = *in.IOPS diff --git a/command/agent/job_endpoint_test.go b/command/agent/job_endpoint_test.go index 9a4870e81..099eb2a60 100644 --- a/command/agent/job_endpoint_test.go +++ b/command/agent/job_endpoint_test.go @@ -2930,6 +2930,53 @@ func TestConversion_apiLogConfigToStructs(t *testing.T) { })) } +func TestConversion_apiResourcesToStructs(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + input *api.Resources + expected *structs.Resources + }{ + { + "nil", + nil, + nil, + }, + { + "plain", + &api.Resources{ + CPU: helper.IntToPtr(100), + MemoryMB: helper.IntToPtr(200), + }, + &structs.Resources{ + CPU: 100, + MemoryMB: 200, + }, + }, + { + "with memory max", + &api.Resources{ + CPU: helper.IntToPtr(100), + MemoryMB: helper.IntToPtr(200), + MemoryMaxMB: helper.IntToPtr(300), + }, + &structs.Resources{ + CPU: 100, + MemoryMB: 200, + MemoryMaxMB: 300, + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + found := ApiResourcesToStructs(c.input) + require.Equal(t, c.expected, found) + }) + } +} + func TestConversion_apiConnectSidecarTaskToStructs(t *testing.T) { t.Parallel() require.Nil(t, apiConnectSidecarTaskToStructs(nil)) diff --git a/command/alloc_status.go b/command/alloc_status.go index aabcaaf43..4e21d18ad 100644 --- a/command/alloc_status.go +++ b/command/alloc_status.go @@ -563,13 +563,21 @@ func (c *AllocStatusCommand) outputTaskResources(alloc *api.Allocation, task str var resourcesOutput []string resourcesOutput = append(resourcesOutput, "CPU|Memory|Disk|Addresses") firstAddr := "" + secondAddr := "" if len(addr) > 0 { firstAddr = addr[0] } + if len(addr) > 1 { + secondAddr = addr[1] + } // Display the rolled up stats. If possible prefer the live statistics cpuUsage := strconv.Itoa(*resource.CPU) memUsage := humanize.IBytes(uint64(*resource.MemoryMB * bytesPerMegabyte)) + memMax := "" + if max := resource.MemoryMaxMB; max != nil && *max != 0 && *max != *resource.MemoryMB { + memMax = "Max: " + humanize.IBytes(uint64(*resource.MemoryMaxMB*bytesPerMegabyte)) + } var deviceStats []*api.DeviceGroupStats if stats != nil { @@ -588,7 +596,10 @@ func (c *AllocStatusCommand) outputTaskResources(alloc *api.Allocation, task str memUsage, humanize.IBytes(uint64(*alloc.Resources.DiskMB*bytesPerMegabyte)), firstAddr)) - for i := 1; i < len(addr); i++ { + if memMax != "" || secondAddr != "" { + resourcesOutput = append(resourcesOutput, fmt.Sprintf("|%v||%v", memMax, secondAddr)) + } + for i := 2; i < len(addr); i++ { resourcesOutput = append(resourcesOutput, fmt.Sprintf("|||%v", addr[i])) } c.Ui.Output(formatListWithSpaces(resourcesOutput)) diff --git a/vendor/github.com/hashicorp/nomad/api/allocations.go b/vendor/github.com/hashicorp/nomad/api/allocations.go index be4058977..0c1a01b1a 100644 --- a/vendor/github.com/hashicorp/nomad/api/allocations.go +++ b/vendor/github.com/hashicorp/nomad/api/allocations.go @@ -511,7 +511,8 @@ type AllocatedCpuResources struct { } type AllocatedMemoryResources struct { - MemoryMB int64 + MemoryMB int64 + MemoryMaxMB int64 } type AllocatedDeviceResource struct { diff --git a/vendor/github.com/hashicorp/nomad/api/resources.go b/vendor/github.com/hashicorp/nomad/api/resources.go index ae420b22f..d9bd49476 100644 --- a/vendor/github.com/hashicorp/nomad/api/resources.go +++ b/vendor/github.com/hashicorp/nomad/api/resources.go @@ -7,12 +7,13 @@ import ( // Resources encapsulates the required resources of // a given task or task group. type Resources struct { - CPU *int `hcl:"cpu,optional"` - Cores *int `hcl:"cores,optional"` - MemoryMB *int `mapstructure:"memory" hcl:"memory,optional"` - DiskMB *int `mapstructure:"disk" hcl:"disk,optional"` - Networks []*NetworkResource `hcl:"network,block"` - Devices []*RequestedDevice `hcl:"device,block"` + CPU *int `hcl:"cpu,optional"` + Cores *int `hcl:"cores,optional"` + MemoryMB *int `mapstructure:"memory" hcl:"memory,optional"` + MemoryMaxMB *int `mapstructure:"memory_max" hcl:"memory_max,optional"` + DiskMB *int `mapstructure:"disk" hcl:"disk,optional"` + Networks []*NetworkResource `hcl:"network,block"` + Devices []*RequestedDevice `hcl:"device,block"` // COMPAT(0.10) // XXX Deprecated. Please do not use. The field will be removed in Nomad