From 56620d00602234ec2f603ed86685b91e661f4d3e Mon Sep 17 00:00:00 2001 From: Stanislas Lange Date: Sat, 31 Jul 2021 19:30:37 +0000 Subject: [PATCH] feat: copy rootfs when creating new VM --- README.md | 4 ++++ go.mod | 1 + go.sum | 2 ++ job.go | 2 -- main.go | 1 + options.go | 13 ++++++------- vm.go | 4 ++++ vmm.go | 18 +++++++++++++++++- 8 files changed, 35 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c371ed8..3e390bc 100644 --- a/README.md +++ b/README.md @@ -161,3 +161,7 @@ Our C program has been successfully compiled and executed! "stdout": "Hello, World!" } ``` + +## Known issues + +Cleanup when shutting down VMs does not work properly. diff --git a/go.mod b/go.mod index 106632e..bf46358 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imroc/req v0.3.0 github.com/mailru/easyjson v0.7.7 // indirect + github.com/rs/xid v1.3.0 // indirect github.com/sirupsen/logrus v1.8.1 github.com/streadway/amqp v1.0.0 github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect diff --git a/go.sum b/go.sum index 21290d3..a6d5684 100644 --- a/go.sum +++ b/go.sum @@ -276,6 +276,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= diff --git a/job.go b/job.go index a21a2c3..89d5d6e 100644 --- a/job.go +++ b/job.go @@ -53,7 +53,6 @@ func (job benchJob) run(ctx context.Context, WarmVMs <-chan runningFirecracker) var httpRes *http.Response var agentRes agentExecRes - // FIXME httpRes, err = http.Post("http://"+vm.ip.String()+":8080/run", "application/json", bytes.NewBuffer(reqJSON)) if err != nil { log.WithError(err).Error("Failed to request execution to agent") @@ -76,5 +75,4 @@ func (job benchJob) run(ctx context.Context, WarmVMs <-chan runningFirecracker) if err != nil { q.setjobFailed(ctx, job, agentExecRes{Error: err.Error()}) } - } diff --git a/main.go b/main.go index 46f608d..ca7da8c 100644 --- a/main.go +++ b/main.go @@ -47,6 +47,7 @@ type agentExecRes struct { type runningFirecracker struct { vmmCtx context.Context vmmCancel context.CancelFunc + vmmID string machine *firecracker.Machine ip net.IP } diff --git a/options.go b/options.go index 3c41b4f..04a4ea2 100644 --- a/options.go +++ b/options.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "math/rand" "os" "path/filepath" "strconv" @@ -12,9 +11,8 @@ import ( models "github.com/firecracker-microvm/firecracker-go-sdk/client/models" ) -// Converts options to a usable firecracker config -func getFirecrackerConfig() (firecracker.Config, error) { - socket := getSocketPath() +func getFirecrackerConfig(vmmID string) (firecracker.Config, error) { + socket := getSocketPath(vmmID) return firecracker.Config{ SocketPath: socket, KernelImagePath: "../../linux/vmlinux", @@ -22,7 +20,7 @@ func getFirecrackerConfig() (firecracker.Config, error) { Drives: []models.Drive{{ DriveID: firecracker.String("1"), // TODO: copy base rootfs and use a temp roots per VM - PathOnHost: firecracker.String("../agent/rootfs.ext4"), + PathOnHost: firecracker.String("/tmp/rootfs-" + vmmID + ".ext4"), IsRootDevice: firecracker.Bool(true), IsReadOnly: firecracker.Bool(false), RateLimiter: firecracker.NewRateLimiter( @@ -54,11 +52,12 @@ func getFirecrackerConfig() (firecracker.Config, error) { }, nil } -func getSocketPath() string { +func getSocketPath(vmmID string) string { filename := strings.Join([]string{ ".firecracker.sock", strconv.Itoa(os.Getpid()), - strconv.Itoa(rand.Intn(10000))}, + vmmID, + }, "-", ) dir := os.TempDir() diff --git a/vm.go b/vm.go index 95f41fe..a7d7e95 100644 --- a/vm.go +++ b/vm.go @@ -46,4 +46,8 @@ func (vm runningFirecracker) shutDown() { if err != nil { log.WithError(err).Error("Failed to delete firecracker socket") } + err = os.Remove("/tmp/rootfs-" + vm.vmmID + ".ext4") + if err != nil { + log.WithError(err).Error("Failed to delete firecracker rootfs") + } } diff --git a/vmm.go b/vmm.go index f8a287f..09ca612 100644 --- a/vmm.go +++ b/vmm.go @@ -3,16 +3,31 @@ package main import ( "context" "fmt" + "io/ioutil" "os" "os/exec" firecracker "github.com/firecracker-microvm/firecracker-go-sdk" + "github.com/rs/xid" log "github.com/sirupsen/logrus" ) +func copy(src string, dst string) error { + data, err := ioutil.ReadFile(src) + if err != nil { + return err + } + err = ioutil.WriteFile(dst, data, 0644) + return err +} + // Create a VMM with a given set of options and start the VM func createAndStartVM(ctx context.Context) (*runningFirecracker, error) { - fcCfg, err := getFirecrackerConfig() + vmmID := xid.New().String() + + copy("../agent/rootfs.ext4", "/tmp/rootfs-"+vmmID+".ext4") + + fcCfg, err := getFirecrackerConfig(vmmID) if err != nil { log.Errorf("Error: %s", err) return nil, err @@ -78,6 +93,7 @@ func createAndStartVM(ctx context.Context) (*runningFirecracker, error) { return &runningFirecracker{ vmmCtx: vmmCtx, vmmCancel: vmmCancel, + vmmID: vmmID, machine: m, ip: m.Cfg.NetworkInterfaces[0].StaticConfiguration.IPConfiguration.IPAddr.IP, }, nil