From 1f523f179d5a184ebbb070490e97a56143b8dc8a Mon Sep 17 00:00:00 2001 From: Mathis Joffre Date: Tue, 16 Aug 2022 14:34:22 +0200 Subject: [PATCH 1/4] Add test for WithSnapshotOpt Closes #435 Signed-off-by: Mathis Joffre --- machine_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/machine_test.go b/machine_test.go index fa2b33d2..bb68a433 100644 --- a/machine_test.go +++ b/machine_test.go @@ -1952,20 +1952,22 @@ func TestLoadSnapshot(t *testing.T) { }, } + cfg.Snapshot.ResumeVM = false + m, err := NewMachine(ctx, cfg, func(m *Machine) { // Rewriting m.cmd partially wouldn't work since Cmd has // some unexported members args := m.cmd.Args[1:] m.cmd = exec.Command(getFirecrackerBinaryPath(), args...) - }, WithLogger(logrus.NewEntry(machineLogger)), WithSnapshot(memPath, snapPath)) + }, WithLogger(logrus.NewEntry(machineLogger)), WithSnapshot(memPath, snapPath, func(config *SnapshotConfig) { + config.ResumeVM = true + })) require.NoError(t, err) + require.Equal(t, m.Cfg.Snapshot.ResumeVM, true) err = m.Start(ctx) require.NoError(t, err) - err = m.ResumeVM(ctx) - require.NoError(t, err) - err = m.StopVMM() require.NoError(t, err) }, From a00debdf2542acdc537db00a988fb24dc0f6902e Mon Sep 17 00:00:00 2001 From: Mathis Joffre Date: Tue, 30 Aug 2022 09:41:01 +0200 Subject: [PATCH 2/4] Pin version of ltag for go <= v1.15 compatibility Signed-off-by: Mathis Joffre --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 0973a4b7..0ffb45b6 100644 --- a/Makefile +++ b/Makefile @@ -122,8 +122,8 @@ $(FC_TEST_BIN_PATH)/tc-redirect-tap: go get github.com/awslabs/tc-redirect-tap/cmd/tc-redirect-tap $(FC_TEST_DATA_PATH)/ltag: - GO111MODULE=off GOBIN=$(abspath $(FC_TEST_DATA_PATH)) \ - go get github.com/kunalkushwaha/ltag + GO111MODULE=on GOBIN=$(abspath $(FC_TEST_BIN_PATH)) \ + go get github.com/kunalkushwaha/ltag@v0.2.3 $(FIRECRACKER_DIR): - git clone https://github.com/firecracker-microvm/firecracker.git $(FIRECRACKER_DIR) @@ -144,6 +144,6 @@ firecracker-clean: lint: deps gofmt -s -l . - $(FC_TEST_DATA_PATH)/ltag -check -v -t .headers + $(FC_TEST_DATA_PATH)/bin/ltag -check -v -t .headers .PHONY: all generate clean distclean build test unit-tests all-tests check-kvm From 226c8ef27332f4db4f193ceef63681336e3a304b Mon Sep 17 00:00:00 2001 From: Mathis Joffre <51022808+Joffref@users.noreply.github.com> Date: Wed, 31 Aug 2022 16:56:33 +0200 Subject: [PATCH 3/4] Add mmds version 2 support (#441) Closes #437 Signed-off-by: Mathis Joffre --- handlers.go | 2 +- handlers_test.go | 1 + machine.go | 20 ++++++++++- machine_test.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 2 deletions(-) diff --git a/handlers.go b/handlers.go index 874084c4..d9d022d8 100644 --- a/handlers.go +++ b/handlers.go @@ -277,7 +277,7 @@ func NewSetMetadataHandler(metadata interface{}) Handler { var ConfigMmdsHandler = Handler{ Name: ConfigMmdsHandlerName, Fn: func(ctx context.Context, m *Machine) error { - return m.setMmdsConfig(ctx, m.Cfg.MmdsAddress, m.Cfg.NetworkInterfaces) + return m.setMmdsConfig(ctx, m.Cfg.MmdsAddress, m.Cfg.NetworkInterfaces, m.Cfg.MmdsVersion) }, } diff --git a/handlers_test.go b/handlers_test.go index 0801d677..c0a634a6 100644 --- a/handlers_test.go +++ b/handlers_test.go @@ -532,6 +532,7 @@ func TestHandlers(t *testing.T) { mmdsConfig := &models.MmdsConfig{ IPV4Address: String(mmdsAddress.String()), NetworkInterfaces: []string{"1"}, + Version: String(string(MMDSv1)), } cases := []struct { diff --git a/machine.go b/machine.go index 83f11895..4179fa1f 100644 --- a/machine.go +++ b/machine.go @@ -65,6 +65,13 @@ type SeccompConfig struct { // be started again. var ErrAlreadyStarted = errors.New("firecracker: machine already started") +type MMDSVersion string + +const ( + MMDSv1 = MMDSVersion("V1") + MMDSv2 = MMDSVersion("V2") +) + // Config is a collection of user-configurable VMM settings type Config struct { // SocketPath defines the file path where the Firecracker control socket @@ -152,6 +159,10 @@ type Config struct { // If not provided, the default address (169.254.169.254) will be used. MmdsAddress net.IP + // MmdsVersion is the MMDS version to use. + // If not provided, the default version (1) will be used. + MmdsVersion MMDSVersion + // Configuration for snapshot loading Snapshot SnapshotConfig } @@ -907,8 +918,15 @@ func (m *Machine) sendCtrlAltDel(ctx context.Context) error { return err } -func (m *Machine) setMmdsConfig(ctx context.Context, address net.IP, ifaces NetworkInterfaces) error { +func (m *Machine) setMmdsConfig(ctx context.Context, address net.IP, ifaces NetworkInterfaces, version MMDSVersion) error { var mmdsCfg models.MmdsConfig + // MMDS config supports v1 and v2, v1 is going to be deprecated. + // Default to the version 1 if no version is specified + if version == MMDSv1 || version == MMDSv2 { + mmdsCfg.Version = String(string(version)) + } else { + mmdsCfg.Version = String(string(MMDSv1)) + } if address != nil { mmdsCfg.IPV4Address = String(address.String()) } diff --git a/machine_test.go b/machine_test.go index bb68a433..b8984ade 100644 --- a/machine_test.go +++ b/machine_test.go @@ -869,6 +869,100 @@ func TestWaitForSocket(t *testing.T) { } } +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()) + require.NoError(t, err) + defer os.RemoveAll(dir) + + socketPath := filepath.Join(dir, "TestMicroVMExecution.sock") + logFifo := filepath.Join(dir, "firecracker.log") + metricsFifo := filepath.Join(dir, "firecracker-metrics") + capturedLog := filepath.Join(dir, "writer.fifo") + fw, err := os.OpenFile(capturedLog, os.O_CREATE|os.O_RDWR, 0600) + require.NoError(t, err, "failed to open fifo writer file") + defer fw.Close() + + vmlinuxPath := getVmlinuxPath(t) + + networkIfaces := []NetworkInterface{{ + StaticConfiguration: &StaticNetworkConfiguration{ + MacAddress: "01-23-45-67-89-AB-CD-EF", + HostDevName: "tap0", + }, + }} + + cfg := Config{ + SocketPath: socketPath, + LogFifo: logFifo, + MetricsFifo: metricsFifo, + LogLevel: "Debug", + MachineCfg: models.MachineConfiguration{ + VcpuCount: Int64(nCpus), + CPUTemplate: cpuTemplate, + MemSizeMib: Int64(memSz), + Smt: Bool(false), + }, + DisableValidation: true, + NetworkInterfaces: networkIfaces, + FifoLogWriter: fw, + MmdsVersion: MMDSv2, + } + + ctx := context.Background() + cmd := VMCommandBuilder{}. + WithSocketPath(socketPath). + WithBin(getFirecrackerBinaryPath()). + Build(ctx) + + m, err := NewMachine(ctx, cfg, WithProcessRunner(cmd), WithLogger(fctesting.NewLogEntry(t))) + if err != nil { + t.Fatalf("failed to create new machine: %v", err) + } + + m.Handlers.Validation = m.Handlers.Validation.Clear() + + vmmCtx, vmmCancel := context.WithTimeout(ctx, 30*time.Second) + defer vmmCancel() + exitchannel := make(chan error) + go func() { + err := m.startVMM(vmmCtx) + if err != nil { + exitchannel <- err + close(exitchannel) + return + } + defer m.StopVMM() + + exitchannel <- m.Wait(vmmCtx) + close(exitchannel) + }() + + deadlineCtx, deadlineCancel := context.WithTimeout(vmmCtx, 250*time.Millisecond) + defer deadlineCancel() + if err := waitForAliveVMM(deadlineCtx, m.client); err != nil { + t.Fatal(err) + } + + t.Run("TestCreateMachine", func(t *testing.T) { testCreateMachine(ctx, t, m) }) + t.Run("TestCreateBootSource", func(t *testing.T) { testCreateBootSource(ctx, t, m, vmlinuxPath) }) + t.Run("TestCreateNetworkInterface", func(t *testing.T) { testCreateNetworkInterfaceByID(ctx, t, m) }) + t.Run("TestAttachRootDrive", func(t *testing.T) { testAttachRootDrive(ctx, t, m) }) + t.Run("SetMetadata", func(t *testing.T) { testSetMetadata(ctx, t, m) }) + t.Run("UpdateMetadata", func(t *testing.T) { testUpdateMetadata(ctx, t, m) }) + t.Run("GetMetadata", func(t *testing.T) { testGetMetadata(ctx, t, m) }) // Should be after testSetMetadata and testUpdateMetadata + + // unconditionally stop the VM here. TestShutdown may have triggered a shutdown, but if it + // didn't for some reason, we still need to terminate it: + err = m.StopVMM() + assert.NoError(t, err, "failed to stop VM") +} + func testSetMetadata(ctx context.Context, t *testing.T, m *Machine) { metadata := map[string]string{"key": "value"} err := m.SetMetadata(ctx, metadata) From 288258ce96e549960d7a3d565878facbafa4ee1a Mon Sep 17 00:00:00 2001 From: Yasin Turan Date: Tue, 30 Aug 2022 19:50:04 +0000 Subject: [PATCH 4/4] Release v1.0.0 Signed-off-by: Yasin Turan --- CHANGELOG.md | 11 +++++++++++ version.go | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6941c917..0e0fa8e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +# 1.0.0 +* Added support for MMDS version 2. (#441) +* Added support for set drive IO engine type. (#411) +* Added support for get Firecracker version. (#410) +* Added a DriveOpt func for configuring CacheType. (#401) +* Added GetExportVMConfig to read the /vm/config endpoint. (#400) +* Added ability to allow passing cgroup-version to jailer. (#399) +* Added support for the MMDS configuration. (#290) +* Added PauseVM, ResumeVM, CreateSnapshot and LoadSnapshot capabilities. (#278) (#414) +* Fixed InitrdPath usage. (#295) + # 0.22.0 * Since firecracker-microvm/firecracker#2125, `cargo build` doesn't build jailer by default. (#263) * Fix Benchmark Goroutine (#259) diff --git a/version.go b/version.go index 3f504c64..a3206217 100644 --- a/version.go +++ b/version.go @@ -14,4 +14,4 @@ package firecracker // Version represents the current version of the SDK. -const Version = "0.22.0" +const Version = "1.0.0"