mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-02-14 18:29:53 +00:00
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
```
This commit is contained in:
committed by
GitHub
parent
c1c4b612a4
commit
2efbc20b7c
@@ -15,14 +15,12 @@ import (
|
||||
// ref: https://gitlab.com/x86-psABIs/x86-64-ABI
|
||||
// ref: https://developers.redhat.com/blog/2021/01/05/building-red-hat-enterprise-linux-9-for-the-x86-64-v2-microarchitecture-level
|
||||
var microarchs = map[string][]string{
|
||||
"x86-64": {"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2"},
|
||||
"x86-64-v2": {"cx16", "lahf_lm", "popcnt", "ssse3", "sse4_1", "sse4_2", "ssse3"},
|
||||
"x86-64-v3": {"avx", "avx2", "bmi1", "bmi2", "f16c", "fma", "lzcnt", "movbe", "xsave"},
|
||||
"x86-64-v4": {"avx512f", "avx512bw", "avx512cd", "avx512dq", "avx512vl"},
|
||||
}
|
||||
|
||||
// x8664BaseFeatures are the features that are present in all x86-64 microarchitectures.
|
||||
var x8664BaseFeatures = []string{"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2"}
|
||||
|
||||
type AnalyzeHostCPU struct {
|
||||
hostAnalyzer *troubleshootv1beta2.CPUAnalyze
|
||||
}
|
||||
@@ -126,13 +124,36 @@ func (a *AnalyzeHostCPU) Analyze(
|
||||
}
|
||||
|
||||
func doCompareHostCPUMicroArchitecture(microarch string, flags []string) (res bool, err error) {
|
||||
specifics, ok := microarchs[microarch]
|
||||
if !ok && microarch != "x86-64" {
|
||||
specifics := make([]string, 0)
|
||||
switch microarch {
|
||||
case "x86-64-v4":
|
||||
specifics = append(specifics, microarchs["x86-64-v4"]...)
|
||||
fallthrough
|
||||
case "x86-64-v3":
|
||||
specifics = append(specifics, microarchs["x86-64-v3"]...)
|
||||
fallthrough
|
||||
case "x86-64-v2":
|
||||
specifics = append(specifics, microarchs["x86-64-v2"]...)
|
||||
fallthrough
|
||||
case "x86-64":
|
||||
specifics = append(specifics, microarchs["x86-64"]...)
|
||||
default:
|
||||
return false, errors.Errorf("troubleshoot does not yet support microarchitecture %q", microarch)
|
||||
}
|
||||
expectedFlags := x8664BaseFeatures
|
||||
if len(specifics) > 0 {
|
||||
expectedFlags = append(expectedFlags, specifics...)
|
||||
|
||||
for _, flag := range specifics {
|
||||
if slices.Contains(flags, flag) {
|
||||
continue
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func doCompareHostCPUFlags(expected string, flags []string) (res bool, err error) {
|
||||
expectedFlags := strings.Split(expected, ",")
|
||||
if len(expectedFlags) == 0 {
|
||||
return false, errors.New("expected flags cannot be empty")
|
||||
}
|
||||
for _, flag := range expectedFlags {
|
||||
if slices.Contains(flags, flag) {
|
||||
@@ -173,6 +194,11 @@ func compareHostCPUConditionalToActual(conditional string, logicalCount int, phy
|
||||
return doCompareHostCPUMicroArchitecture(desired, flags)
|
||||
}
|
||||
|
||||
// hasFlags allows users to query for specific flags on the CPU.
|
||||
if strings.ToLower(comparator) == "hasflags" {
|
||||
return doCompareHostCPUFlags(desired, flags)
|
||||
}
|
||||
|
||||
if !compareLogical && !comparePhysical && !compareUnspecified {
|
||||
return false, errors.New("unable to parse conditional")
|
||||
}
|
||||
|
||||
@@ -152,6 +152,18 @@ func Test_compareHostCPUConditionalToActual(t *testing.T) {
|
||||
flags: []string{"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2", "cx16", "lahf_lm", "popcnt", "ssse3", "sse4_1", "sse4_2", "ssse3"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "has a non existent flag",
|
||||
when: "hasFlags cmov,doesNotExist",
|
||||
flags: []string{"cmov", "cx8", "fpu", "fxsr", "mmx", "syscall", "sse", "sse2", "cx16", "lahf_lm", "popcnt", "ssse3", "sse4_1", "sse4_2", "ssse3"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "has flags",
|
||||
when: "hasFlags a,b,c",
|
||||
flags: []string{"a", "b", "c", "d", "e"},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user