From 2e059c624f1a6240a7e0798c8a154e4798e87164 Mon Sep 17 00:00:00 2001 From: Michael Schurter Date: Mon, 26 Sep 2022 13:03:03 -0700 Subject: [PATCH] fingerprint: add node attr for reserverable cores (#14694) * fingerprint: add node attr for reserverable cores Add an attribute for the number of reservable CPU cores as they may differ from the existing `cpu.numcores` due to client configuration or OS support. Hopefully clarifies some confusion in #14676 * add changelog * num_reservable_cores -> reservablecores --- .changelog/14694.txt | 3 +++ client/fingerprint/cpu.go | 4 +++- client/fingerprint/cpu_test.go | 12 +++++++++++- website/content/docs/runtime/interpolation.mdx | 8 +++++++- 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .changelog/14694.txt diff --git a/.changelog/14694.txt b/.changelog/14694.txt new file mode 100644 index 000000000..06881ebbf --- /dev/null +++ b/.changelog/14694.txt @@ -0,0 +1,3 @@ +```release-note:improvement +fingerprint: Add node attribute for number of reservable cores: `cpu.num_reservable_cores` +``` diff --git a/client/fingerprint/cpu.go b/client/fingerprint/cpu.go index e0fc8b2c5..3bc886805 100644 --- a/client/fingerprint/cpu.go +++ b/client/fingerprint/cpu.go @@ -2,6 +2,7 @@ package fingerprint import ( "fmt" + "strconv" "github.com/hashicorp/nomad/lib/cpuset" @@ -62,7 +63,7 @@ func (f *CPUFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintR var numCores int if numCores = stats.CPUNumCores(); numCores > 0 { - resp.AddAttribute("cpu.numcores", fmt.Sprintf("%d", numCores)) + resp.AddAttribute("cpu.numcores", strconv.Itoa(numCores)) f.logger.Debug("detected core count", "cores", numCores) } @@ -80,6 +81,7 @@ func (f *CPUFingerprint) Fingerprint(req *FingerprintRequest, resp *FingerprintR f.logger.Debug("detected reservable cores", "cpuset", reservableCores) } } + resp.AddAttribute("cpu.reservablecores", strconv.Itoa(len(reservableCores))) tt := int(stats.TotalTicksAvailable()) if cfg.CpuCompute > 0 { diff --git a/client/fingerprint/cpu_test.go b/client/fingerprint/cpu_test.go index 5d2e23e16..bc3785955 100644 --- a/client/fingerprint/cpu_test.go +++ b/client/fingerprint/cpu_test.go @@ -67,7 +67,9 @@ func TestCPUFingerprint_OverrideCompute(t *testing.T) { node := &structs.Node{ Attributes: make(map[string]string), } - cfg := &config.Config{} + cfg := &config.Config{ + ReservableCores: []uint16{0, 1, 2}, + } var originalCPU int { @@ -82,6 +84,10 @@ func TestCPUFingerprint_OverrideCompute(t *testing.T) { t.Fatalf("expected response to be applicable") } + if attr := response.Attributes["cpu.reservablecores"]; attr != "3" { + t.Fatalf("expected cpu.reservablecores == 3 but found %s", attr) + } + if response.Resources.CPU == 0 { t.Fatalf("expected fingerprint of cpu of but found 0") } @@ -111,5 +117,9 @@ func TestCPUFingerprint_OverrideCompute(t *testing.T) { if response.Attributes["cpu.totalcompute"] != strconv.Itoa(cfg.CpuCompute) { t.Fatalf("expected override cpu.totalcompute of %d but found %s", cfg.CpuCompute, response.Attributes["cpu.totalcompute"]) } + + if attr := response.Attributes["cpu.reservablecores"]; attr != "3" { + t.Fatalf("expected cpu.reservablecores == 3 but found %s", attr) + } } } diff --git a/website/content/docs/runtime/interpolation.mdx b/website/content/docs/runtime/interpolation.mdx index b9f852258..ec3c93133 100644 --- a/website/content/docs/runtime/interpolation.mdx +++ b/website/content/docs/runtime/interpolation.mdx @@ -169,7 +169,13 @@ Below is a table documenting common node properties: {'${attr.cpu.numcores}'} - Number of CPU cores on the client + Number of CPU cores on the client. May differ from how many cores are available for reservation due to OS or configuration. See cpu.reservablecores. + + + + {'${attr.cpu.reservablecores}'} + + Number of CPU cores on the client avaible for scheduling. Number of cores used by the scheduler when placing work with resources.cores set.