diff --git a/benchmark_test.go b/benchmark_test.go index 3dbfa9e9..87ca1faf 100644 --- a/benchmark_test.go +++ b/benchmark_test.go @@ -51,7 +51,6 @@ func createMachine(ctx context.Context, name string, forwardSignals []os.Signal) LogLevel: "Info", MachineCfg: models.MachineConfiguration{ VcpuCount: Int64(1), - CPUTemplate: models.CPUTemplate(models.CPUTemplateT2), MemSizeMib: Int64(256), Smt: Bool(false), }, diff --git a/examples/cmd/snapshotting/example_demo.go b/examples/cmd/snapshotting/example_demo.go index d62f7c3e..e3524c92 100644 --- a/examples/cmd/snapshotting/example_demo.go +++ b/examples/cmd/snapshotting/example_demo.go @@ -77,7 +77,6 @@ func createNewConfig(socketPath string, opts ...configOpt) sdk.Config { kernelImagePath := filepath.Join(dir, "vmlinux") var vcpuCount int64 = 2 - cpuTemplate := models.CPUTemplate(models.CPUTemplateT2) var memSizeMib int64 = 256 smt := false @@ -91,7 +90,6 @@ func createNewConfig(socketPath string, opts ...configOpt) sdk.Config { KernelImagePath: kernelImagePath, MachineCfg: models.MachineConfiguration{ VcpuCount: &vcpuCount, - CPUTemplate: cpuTemplate, MemSizeMib: &memSizeMib, Smt: &smt, }, diff --git a/internal/cpu_template.go b/internal/cpu_template.go new file mode 100644 index 00000000..00543611 --- /dev/null +++ b/internal/cpu_template.go @@ -0,0 +1,71 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"). You may +// not use this file except in compliance with the License. A copy of the +// License is located at +// +// http://aws.amazon.com/apache2.0/ +// +// or in the "license" file accompanying this file. This file is distributed +// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +// express or implied. See the License for the specific language governing +// permissions and limitations under the License. + +package internal + +import ( + "bufio" + "io" + "os" + "regexp" + "runtime" + "sync" +) + +var ( + isIntel bool + isIntelOnce sync.Once +) + +// SupportCPUTemplate returns true if Firecracker supports CPU templates on +// the current architecture. +func SupportCPUTemplate() (bool, error) { + if runtime.GOARCH != "amd64" { + return false, nil + } + + var err error + isIntelOnce.Do(func() { + isIntel, err = checkIsIntel() + }) + return isIntel, err +} + +var vendorID = regexp.MustCompile(`^vendor_id\s*:\s*(.+)$`) + +func checkIsIntel() (bool, error) { + f, err := os.Open("/proc/cpuinfo") + if err != nil { + return false, err + } + defer f.Close() + + id, err := findFirstVendorID(f) + if err != nil { + return false, err + } + + return id == "GenuineIntel", nil +} + +func findFirstVendorID(r io.Reader) (string, error) { + s := bufio.NewScanner(r) + for s.Scan() { + line := s.Text() + matches := vendorID.FindStringSubmatch(line) + if len(matches) == 2 { + return matches[1], nil + } + } + return "", nil +} \ No newline at end of file diff --git a/internal/cpu_template_test.go b/internal/cpu_template_test.go new file mode 100644 index 00000000..0136c63c --- /dev/null +++ b/internal/cpu_template_test.go @@ -0,0 +1,41 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"). You may +// not use this file except in compliance with the License. A copy of the +// License is located at +// +// http://aws.amazon.com/apache2.0/ +// +// or in the "license" file accompanying this file. This file is distributed +// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +// express or implied. See the License for the specific language governing +// permissions and limitations under the License. + +package internal + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFindFirstVendorID(t *testing.T) { + cases := []struct { + input string + vendorID string + }{ + {"vendor_id : GenuineIntel", "GenuineIntel"}, + {"vendor_id : AuthenticAMD", "AuthenticAMD"}, + + // aarch64 doesn't have vendor IDs. + {"", ""}, + } + for _, c := range cases { + r := strings.NewReader(c.input) + id, err := findFirstVendorID(r) + require.NoError(t, err) + assert.Equal(t, c.vendorID, id) + } +} \ No newline at end of file diff --git a/machine_test.go b/machine_test.go index a0deaf11..0e2fa83b 100644 --- a/machine_test.go +++ b/machine_test.go @@ -19,7 +19,6 @@ import ( "errors" "flag" "fmt" - "github.com/vishvananda/netns" "io" "io/ioutil" "net" @@ -35,6 +34,8 @@ import ( "testing" "time" + "github.com/vishvananda/netns" + "github.com/containerd/fifo" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" @@ -44,6 +45,7 @@ import ( models "github.com/firecracker-microvm/firecracker-go-sdk/client/models" ops "github.com/firecracker-microvm/firecracker-go-sdk/client/operations" "github.com/firecracker-microvm/firecracker-go-sdk/fctesting" + "github.com/firecracker-microvm/firecracker-go-sdk/internal" ) const ( @@ -114,10 +116,9 @@ func TestNewMachine(t *testing.T) { Config{ DisableValidation: true, MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(1), - MemSizeMib: Int64(100), - CPUTemplate: models.CPUTemplate(models.CPUTemplateT2), - Smt: Bool(false), + VcpuCount: Int64(1), + MemSizeMib: Int64(100), + Smt: Bool(false), }, }, WithLogger(fctesting.NewLogEntry(t))) @@ -172,7 +173,6 @@ func TestJailerMicroVMExecution(t *testing.T) { } var nCpus int64 = 2 - cpuTemplate := models.CPUTemplate(models.CPUTemplateT2) var memSz int64 = 256 // short names and directory to prevent SUN_LEN error @@ -210,10 +210,9 @@ func TestJailerMicroVMExecution(t *testing.T) { LogLevel: "Debug", KernelImagePath: vmlinuxPath, MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(nCpus), - CPUTemplate: cpuTemplate, - MemSizeMib: Int64(memSz), - Smt: Bool(false), + VcpuCount: Int64(nCpus), + MemSizeMib: Int64(memSz), + Smt: Bool(false), }, Drives: []models.Drive{ { @@ -296,7 +295,6 @@ func TestMicroVMExecution(t *testing.T) { fctesting.RequiresKVM(t) var nCpus int64 = 2 - cpuTemplate := models.CPUTemplate(models.CPUTemplateT2) var memSz int64 = 256 dir, err := ioutil.TempDir("", t.Name()) @@ -326,10 +324,9 @@ func TestMicroVMExecution(t *testing.T) { MetricsFifo: metricsFifo, LogLevel: "Debug", MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(nCpus), - CPUTemplate: cpuTemplate, - MemSizeMib: Int64(memSz), - Smt: Bool(false), + VcpuCount: Int64(nCpus), + MemSizeMib: Int64(memSz), + Smt: Bool(false), }, DisableValidation: true, NetworkInterfaces: networkIfaces, @@ -498,10 +495,9 @@ func testLogAndMetrics(t *testing.T, logLevel string) string { DisableValidation: true, KernelImagePath: getVmlinuxPath(t), MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(1), - MemSizeMib: Int64(64), - CPUTemplate: models.CPUTemplate(models.CPUTemplateT2), - Smt: Bool(false), + VcpuCount: Int64(1), + MemSizeMib: Int64(64), + Smt: Bool(false), }, MetricsPath: filepath.Join(dir, "fc-metrics.out"), LogPath: filepath.Join(dir, "fc.log"), @@ -553,12 +549,14 @@ func TestStartVMMOnce(t *testing.T) { DisableValidation: true, KernelImagePath: getVmlinuxPath(t), MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(1), - MemSizeMib: Int64(64), - CPUTemplate: models.CPUTemplate(models.CPUTemplateT2), - Smt: Bool(false), + VcpuCount: Int64(1), + MemSizeMib: Int64(64), + Smt: Bool(false), }, } + if cpu_temp, err := internal.SupportCPUTemplate(); cpu_temp && err == nil { + cfg.MachineCfg.CPUTemplate = models.CPUTemplate(models.CPUTemplateT2) + } ctx := context.Background() cmd := VMCommandBuilder{}. WithSocketPath(cfg.SocketPath). @@ -844,10 +842,9 @@ func TestStopVMMCleanup(t *testing.T) { KernelImagePath: getVmlinuxPath(t), NetworkInterfaces: []NetworkInterface{networkInterface}, MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(1), - MemSizeMib: Int64(64), - CPUTemplate: models.CPUTemplate(models.CPUTemplateT2), - Smt: Bool(false), + VcpuCount: Int64(1), + MemSizeMib: Int64(64), + Smt: Bool(false), }, } ctx := context.Background() @@ -939,7 +936,6 @@ func TestMicroVMExecutionWithMmdsV2(t *testing.T) { fctesting.RequiresKVM(t) var nCpus int64 = 2 - cpuTemplate := models.CPUTemplate(models.CPUTemplateT2) var memSz int64 = 256 dir, err := ioutil.TempDir("", t.Name()) @@ -969,10 +965,9 @@ func TestMicroVMExecutionWithMmdsV2(t *testing.T) { MetricsFifo: metricsFifo, LogLevel: "Debug", MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(nCpus), - CPUTemplate: cpuTemplate, - MemSizeMib: Int64(memSz), - Smt: Bool(false), + VcpuCount: Int64(nCpus), + MemSizeMib: Int64(memSz), + Smt: Bool(false), }, DisableValidation: true, NetworkInterfaces: networkIfaces, @@ -1344,7 +1339,6 @@ func TestPID(t *testing.T) { defer os.RemoveAll(dir) var nCpus int64 = 2 - cpuTemplate := models.CPUTemplate(models.CPUTemplateT2) var memSz int64 = 256 socketPath := filepath.Join(dir, "TestPID.sock") defer os.Remove(socketPath) @@ -1361,10 +1355,9 @@ func TestPID(t *testing.T) { SocketPath: socketPath, KernelImagePath: vmlinuxPath, MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(nCpus), - CPUTemplate: cpuTemplate, - MemSizeMib: Int64(memSz), - Smt: Bool(false), + VcpuCount: Int64(nCpus), + MemSizeMib: Int64(memSz), + Smt: Bool(false), }, Drives: []models.Drive{ { @@ -1675,10 +1668,9 @@ func createValidConfig(t *testing.T, socketPath string, opts ...machineConfigOpt SocketPath: socketPath, KernelImagePath: getVmlinuxPath(t), MachineCfg: models.MachineConfiguration{ - VcpuCount: Int64(2), - CPUTemplate: models.CPUTemplate(models.CPUTemplateT2), - MemSizeMib: Int64(256), - Smt: Bool(false), + VcpuCount: Int64(2), + MemSizeMib: Int64(256), + Smt: Bool(false), }, Drives: []models.Drive{ {