Merge pull request #1575 from Weichen81/arm-multi-arch
Fix pull-multi-arch images for Arm
This commit is contained in:
commit
1d896a82c2
85
platforms/cpuinfo.go
Normal file
85
platforms/cpuinfo.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package platforms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Present the ARM instruction set architecture, eg: v7, v8
|
||||||
|
var cpuVariant string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if isArmArch(runtime.GOARCH) {
|
||||||
|
cpuVariant = getCPUVariant()
|
||||||
|
} else {
|
||||||
|
cpuVariant = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Linux, the kernel has already detected the ABI, ISA and Features.
|
||||||
|
// So we don't need to access the ARM registers to detect platform information
|
||||||
|
// by ourselves. We can just parse these information from /proc/cpuinfo
|
||||||
|
func getCPUInfo(pattern string) (info string, err error) {
|
||||||
|
if !isLinuxOS(runtime.GOOS) {
|
||||||
|
return "", errors.Wrapf(errdefs.ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS)
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuinfo, err := os.Open("/proc/cpuinfo")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer cpuinfo.Close()
|
||||||
|
|
||||||
|
// Start to Parse the Cpuinfo line by line. For SMP SoC, we parse
|
||||||
|
// the first core is enough.
|
||||||
|
scanner := bufio.NewScanner(cpuinfo)
|
||||||
|
for scanner.Scan() {
|
||||||
|
newline := scanner.Text()
|
||||||
|
list := strings.Split(newline, ":")
|
||||||
|
|
||||||
|
if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) {
|
||||||
|
return strings.TrimSpace(list[1]), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the scanner encountered errors
|
||||||
|
err = scanner.Err()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.Wrapf(errdefs.ErrNotFound, "getCPUInfo for pattern: %s", pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCPUVariant() string {
|
||||||
|
variant, err := getCPUInfo("Cpu architecture")
|
||||||
|
if err != nil {
|
||||||
|
log.L.WithError(err).Error("failure getting variant")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
switch variant {
|
||||||
|
case "8":
|
||||||
|
variant = "v8"
|
||||||
|
case "7", "7M", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)":
|
||||||
|
variant = "v7"
|
||||||
|
case "6", "6TEJ":
|
||||||
|
variant = "v6"
|
||||||
|
case "5", "5T", "5TE", "5TEJ":
|
||||||
|
variant = "v5"
|
||||||
|
case "4", "4T":
|
||||||
|
variant = "v4"
|
||||||
|
case "3":
|
||||||
|
variant = "v3"
|
||||||
|
default:
|
||||||
|
variant = "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
return variant
|
||||||
|
}
|
24
platforms/cpuinfo_test.go
Normal file
24
platforms/cpuinfo_test.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package platforms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"runtime"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCPUVariant(t *testing.T) {
|
||||||
|
if !isArmArch(runtime.GOARCH) || !isLinuxOS(runtime.GOOS) {
|
||||||
|
t.Skip("only relevant on linux/arm")
|
||||||
|
}
|
||||||
|
|
||||||
|
variants := []string{"v8", "v7", "v6", "v5", "v4", "v3"}
|
||||||
|
|
||||||
|
p := getCPUVariant()
|
||||||
|
for _, variant := range variants {
|
||||||
|
if p == variant {
|
||||||
|
t.Logf("got valid variant as expected: %#v = %#v\n", p, variant)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Fatalf("could not get valid variant as expected: %v\n", variants)
|
||||||
|
}
|
@ -5,6 +5,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// isLinuxOS returns true if the operating system is Linux.
|
||||||
|
//
|
||||||
|
// The OS value should be normalized before calling this function.
|
||||||
|
func isLinuxOS(os string) bool {
|
||||||
|
return os == "linux"
|
||||||
|
}
|
||||||
|
|
||||||
// These function are generated from from https://golang.org/src/go/build/syslist.go.
|
// These function are generated from from https://golang.org/src/go/build/syslist.go.
|
||||||
//
|
//
|
||||||
// We use switch statements because they are slightly faster than map lookups
|
// We use switch statements because they are slightly faster than map lookups
|
||||||
@ -21,6 +28,17 @@ func isKnownOS(os string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isArmArch returns true if the architecture is ARM.
|
||||||
|
//
|
||||||
|
// The arch value should be normalized before being passed to this function.
|
||||||
|
func isArmArch(arch string) bool {
|
||||||
|
switch arch {
|
||||||
|
case "arm", "arm64":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// isKnownArch returns true if we know about the architecture.
|
// isKnownArch returns true if we know about the architecture.
|
||||||
//
|
//
|
||||||
// The arch value should be normalized before being passed to this function.
|
// The arch value should be normalized before being passed to this function.
|
||||||
|
@ -16,6 +16,7 @@ func DefaultSpec() specs.Platform {
|
|||||||
return specs.Platform{
|
return specs.Platform{
|
||||||
OS: runtime.GOOS,
|
OS: runtime.GOOS,
|
||||||
Architecture: runtime.GOARCH,
|
Architecture: runtime.GOARCH,
|
||||||
// TODO(stevvooe): Need to resolve GOARM for arm hosts.
|
// The Variant field will be empty if arch != ARM.
|
||||||
|
Variant: cpuVariant,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ func TestDefault(t *testing.T) {
|
|||||||
expected := specs.Platform{
|
expected := specs.Platform{
|
||||||
OS: runtime.GOOS,
|
OS: runtime.GOOS,
|
||||||
Architecture: runtime.GOARCH,
|
Architecture: runtime.GOARCH,
|
||||||
|
Variant: cpuVariant,
|
||||||
}
|
}
|
||||||
p := DefaultSpec()
|
p := DefaultSpec()
|
||||||
if !reflect.DeepEqual(p, expected) {
|
if !reflect.DeepEqual(p, expected) {
|
||||||
|
Loading…
Reference in New Issue
Block a user