Skip to content

Commit 2efbc20

Browse files
feat: allow users to check cpu flags (#1631)
allow users to check if specific cpu flags are supported by the host. ```yaml apiVersion: troubleshoot.sh/v1beta2 kind: HostPreflight metadata: name: ec-cluster-preflight spec: collectors: - cpu: {} analyzers: - cpu: checkName: CPU outcomes: - pass: when: hasFlags cmov,cx8,fpu,fxsr,mmx message: CPU supports all required flags - fail: message: CPU not supported ```
1 parent c1c4b61 commit 2efbc20

File tree

2 files changed

+46
-8
lines changed

2 files changed

+46
-8
lines changed

pkg/analyze/host_cpu.go

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@ import (
1515
// ref: https://gitlab.com/x86-psABIs/x86-64-ABI
1616
// ref: https://developers.redhat.com/blog/2021/01/05/building-red-hat-enterprise-linux-9-for-the-x86-64-v2-microarchitecture-level
1717
var microarchs = map[string][]string{
18+
"x86-64": {"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2"},
1819
"x86-64-v2": {"cx16", "lahf_lm", "popcnt", "ssse3", "sse4_1", "sse4_2", "ssse3"},
1920
"x86-64-v3": {"avx", "avx2", "bmi1", "bmi2", "f16c", "fma", "lzcnt", "movbe", "xsave"},
2021
"x86-64-v4": {"avx512f", "avx512bw", "avx512cd", "avx512dq", "avx512vl"},
2122
}
2223

23-
// x8664BaseFeatures are the features that are present in all x86-64 microarchitectures.
24-
var x8664BaseFeatures = []string{"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2"}
25-
2624
type AnalyzeHostCPU struct {
2725
hostAnalyzer *troubleshootv1beta2.CPUAnalyze
2826
}
@@ -126,13 +124,36 @@ func (a *AnalyzeHostCPU) Analyze(
126124
}
127125

128126
func doCompareHostCPUMicroArchitecture(microarch string, flags []string) (res bool, err error) {
129-
specifics, ok := microarchs[microarch]
130-
if !ok && microarch != "x86-64" {
127+
specifics := make([]string, 0)
128+
switch microarch {
129+
case "x86-64-v4":
130+
specifics = append(specifics, microarchs["x86-64-v4"]...)
131+
fallthrough
132+
case "x86-64-v3":
133+
specifics = append(specifics, microarchs["x86-64-v3"]...)
134+
fallthrough
135+
case "x86-64-v2":
136+
specifics = append(specifics, microarchs["x86-64-v2"]...)
137+
fallthrough
138+
case "x86-64":
139+
specifics = append(specifics, microarchs["x86-64"]...)
140+
default:
131141
return false, errors.Errorf("troubleshoot does not yet support microarchitecture %q", microarch)
132142
}
133-
expectedFlags := x8664BaseFeatures
134-
if len(specifics) > 0 {
135-
expectedFlags = append(expectedFlags, specifics...)
143+
144+
for _, flag := range specifics {
145+
if slices.Contains(flags, flag) {
146+
continue
147+
}
148+
return false, nil
149+
}
150+
return true, nil
151+
}
152+
153+
func doCompareHostCPUFlags(expected string, flags []string) (res bool, err error) {
154+
expectedFlags := strings.Split(expected, ",")
155+
if len(expectedFlags) == 0 {
156+
return false, errors.New("expected flags cannot be empty")
136157
}
137158
for _, flag := range expectedFlags {
138159
if slices.Contains(flags, flag) {
@@ -173,6 +194,11 @@ func compareHostCPUConditionalToActual(conditional string, logicalCount int, phy
173194
return doCompareHostCPUMicroArchitecture(desired, flags)
174195
}
175196

197+
// hasFlags allows users to query for specific flags on the CPU.
198+
if strings.ToLower(comparator) == "hasflags" {
199+
return doCompareHostCPUFlags(desired, flags)
200+
}
201+
176202
if !compareLogical && !comparePhysical && !compareUnspecified {
177203
return false, errors.New("unable to parse conditional")
178204
}

pkg/analyze/host_cpu_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ func Test_compareHostCPUConditionalToActual(t *testing.T) {
152152
flags: []string{"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2", "cx16", "lahf_lm", "popcnt", "ssse3", "sse4_1", "sse4_2", "ssse3"},
153153
expected: true,
154154
},
155+
{
156+
name: "has a non existent flag",
157+
when: "hasFlags cmov,doesNotExist",
158+
flags: []string{"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2", "cx16", "lahf_lm", "popcnt", "ssse3", "sse4_1", "sse4_2", "ssse3"},
159+
expected: false,
160+
},
161+
{
162+
name: "has flags",
163+
when: "hasFlags a,b,c",
164+
flags: []string{"a", "b", "c", "d", "e"},
165+
expected: true,
166+
},
155167
}
156168
for _, test := range tests {
157169
t.Run(test.name, func(t *testing.T) {

0 commit comments

Comments
 (0)