Add Zygostates hardware qualification runner
This commit is contained in:
commit
65541dc8eb
1 changed files with 2889 additions and 0 deletions
107
internal/zygostates/identity.go
Normal file
107
internal/zygostates/identity.go
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
package zygostates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type HardwareIdentity struct {
|
||||
Key string `json:"key"`
|
||||
BoardVendor string `json:"board_vendor,omitempty"`
|
||||
BoardName string `json:"board_name,omitempty"`
|
||||
BoardVersion string `json:"board_version,omitempty"`
|
||||
BoardSerial string `json:"board_serial,omitempty"`
|
||||
ProductName string `json:"product_name,omitempty"`
|
||||
ProductSerial string `json:"product_serial,omitempty"`
|
||||
ProductUUID string `json:"product_uuid,omitempty"`
|
||||
}
|
||||
|
||||
var uuidPattern = regexp.MustCompile(`(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
|
||||
|
||||
func readHardwareIdentity(root string) (HardwareIdentity, error) {
|
||||
read := func(name string) string {
|
||||
contents, err := os.ReadFile(filepath.Join(root, name))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return strings.TrimSpace(string(contents))
|
||||
}
|
||||
identity := HardwareIdentity{
|
||||
BoardVendor: read("board_vendor"),
|
||||
BoardName: read("board_name"),
|
||||
BoardVersion: read("board_version"),
|
||||
BoardSerial: read("board_serial"),
|
||||
ProductName: read("product_name"),
|
||||
ProductSerial: read("product_serial"),
|
||||
ProductUUID: strings.ToLower(read("product_uuid")),
|
||||
}
|
||||
if validUUID(identity.ProductUUID) {
|
||||
identity.Key = identity.ProductUUID
|
||||
return identity, nil
|
||||
}
|
||||
if validIdentifier(identity.BoardSerial) {
|
||||
identity.Key = sanitizeIdentifier(identity.BoardSerial)
|
||||
return identity, nil
|
||||
}
|
||||
return HardwareIdentity{}, fmt.Errorf("no valid SMBIOS product UUID or board serial")
|
||||
}
|
||||
|
||||
func validUUID(value string) bool {
|
||||
if !uuidPattern.MatchString(value) {
|
||||
return false
|
||||
}
|
||||
compact := strings.ReplaceAll(strings.ToLower(value), "-", "")
|
||||
return compact != strings.Repeat("0", 32) && compact != strings.Repeat("f", 32)
|
||||
}
|
||||
|
||||
func validIdentifier(value string) bool {
|
||||
normalized := strings.ToLower(strings.TrimSpace(value))
|
||||
if normalized == "" {
|
||||
return false
|
||||
}
|
||||
for _, placeholder := range []string{"default string", "none", "not specified", "system serial number", "to be filled by o.e.m.", "unknown"} {
|
||||
if normalized == placeholder {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return sanitizeIdentifier(value) != ""
|
||||
}
|
||||
|
||||
func sanitizeIdentifier(value string) string {
|
||||
var result strings.Builder
|
||||
for _, character := range strings.ToLower(strings.TrimSpace(value)) {
|
||||
switch {
|
||||
case character >= 'a' && character <= 'z', character >= '0' && character <= '9', character == '-', character == '_', character == '.':
|
||||
result.WriteRune(character)
|
||||
default:
|
||||
result.WriteByte('-')
|
||||
}
|
||||
}
|
||||
return strings.Trim(result.String(), "-.")
|
||||
}
|
||||
|
||||
type SystemMetadata struct {
|
||||
Identity HardwareIdentity `json:"identity"`
|
||||
Hostname string `json:"hostname"`
|
||||
Kernel string `json:"kernel"`
|
||||
Architecture string `json:"architecture"`
|
||||
LogicalCPUs int `json:"logical_cpus"`
|
||||
GoVersion string `json:"go_version"`
|
||||
}
|
||||
|
||||
func systemMetadata(identity HardwareIdentity) SystemMetadata {
|
||||
hostname, _ := os.Hostname()
|
||||
kernel, _ := os.ReadFile("/proc/sys/kernel/osrelease")
|
||||
return SystemMetadata{
|
||||
Identity: identity,
|
||||
Hostname: hostname,
|
||||
Kernel: strings.TrimSpace(string(kernel)),
|
||||
Architecture: runtime.GOARCH,
|
||||
LogicalCPUs: runtime.NumCPU(),
|
||||
GoVersion: runtime.Version(),
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue