aboutsummaryrefslogtreecommitdiff
path: root/cmd/c2vm/main.go
diff options
context:
space:
mode:
authorFranck Cuny <franck@fcuny.net>2021-05-15 13:51:19 -0700
committerFranck Cuny <franck@fcuny.net>2021-05-15 13:51:19 -0700
commit97e7a59291bf16c1dfa8e48b267116b4c66bc4c0 (patch)
tree1de0d475a6573b261b88888c7b0ef39f5f8e15ac /cmd/c2vm/main.go
parenthack: firecracker binary and CNI configuration (diff)
downloadcontainerd-to-vm-97e7a59291bf16c1dfa8e48b267116b4c66bc4c0.tar.gz
boot the VM
The binary needs a few more arguments: the path to the firecracker binary, the path to a linux kernel. Using the image that was generated, we can now boot the VM with firecracker. This will rely on a CNI configuration to create the network, and will use the provided kernel to boot.
Diffstat (limited to 'cmd/c2vm/main.go')
-rw-r--r--cmd/c2vm/main.go83
1 files changed, 80 insertions, 3 deletions
diff --git a/cmd/c2vm/main.go b/cmd/c2vm/main.go
index 3251f96..37a7704 100644
--- a/cmd/c2vm/main.go
+++ b/cmd/c2vm/main.go
@@ -19,6 +19,8 @@ import (
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/platforms"
"github.com/docker/docker/pkg/archive"
+ "github.com/firecracker-microvm/firecracker-go-sdk"
+ "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
"github.com/google/renameio"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
@@ -29,7 +31,8 @@ const (
)
var (
- platform = platforms.Only(ocispec.Platform{
+ firecrackerSock = filepath.Join(os.Getenv("XDG_RUNTIME_DIR"), "firecracker.sock")
+ platform = platforms.Only(ocispec.Platform{
OS: "linux",
Architecture: "amd64",
})
@@ -37,8 +40,10 @@ var (
func main() {
var (
- containerName = flag.String("container", "", "Name of the container")
- outFile = flag.String("out", "container.img", "firecracker output to create")
+ containerName = flag.String("container", "", "Name of the container")
+ outFile = flag.String("out", "container.img", "firecracker output to create")
+ linuxKernel = flag.String("linux-kernel", "", "path to the linux kernel to use")
+ firecrackerBinary = flag.String("firecracker-binary", "", "path to the firecracker binary")
)
flag.Parse()
@@ -47,6 +52,14 @@ func main() {
log.Fatal("a container is required")
}
+ if *linuxKernel == "" {
+ log.Fatalf("a linux kernel is required")
+ }
+
+ if *firecrackerBinary == "" {
+ log.Fatalf("the path to the firecracker binary is required")
+ }
+
client, err := containerd.New(containerdSock)
if err != nil {
log.Fatalf("failed to create a client for containerd: %v", err)
@@ -100,6 +113,8 @@ func main() {
if err := resizeImage(*outFile); err != nil {
log.Fatalf("failed to resize the image %s: %s\n", *outFile, err)
}
+
+ bootVM(ctx, *outFile, *linuxKernel, *firecrackerBinary)
}
func extract(ctx context.Context, client *containerd.Client, image containerd.Image, mntDir string) error {
@@ -224,3 +239,65 @@ func writeToFile(filepath string, content string) error {
}
return nil
}
+
+func bootVM(ctx context.Context, rawImage, linuxKernel, firecrackerBinary string) {
+ vmmCtx, vmmCancel := context.WithCancel(ctx)
+ defer vmmCancel()
+
+ devices := make([]models.Drive, 1)
+ devices[0] = models.Drive{
+ DriveID: firecracker.String("1"),
+ PathOnHost: &rawImage,
+ IsRootDevice: firecracker.Bool(true),
+ IsReadOnly: firecracker.Bool(false),
+ }
+ fcCfg := firecracker.Config{
+ LogLevel: "debug",
+ SocketPath: firecrackerSock,
+ KernelImagePath: linuxKernel,
+ KernelArgs: "console=ttyS0 reboot=k panic=1 pci=off init=/init.sh random.trust_cpu=on",
+ Drives: devices,
+ MachineCfg: models.MachineConfiguration{
+ VcpuCount: firecracker.Int64(1),
+ CPUTemplate: models.CPUTemplate("C3"),
+ HtEnabled: firecracker.Bool(true),
+ MemSizeMib: firecracker.Int64(512),
+ },
+ NetworkInterfaces: []firecracker.NetworkInterface{
+ {
+ CNIConfiguration: &firecracker.CNIConfiguration{
+ NetworkName: "c2vm",
+ IfName: "eth0",
+ },
+ },
+ },
+ }
+
+ machineOpts := []firecracker.Opt{}
+
+ command := firecracker.VMCommandBuilder{}.
+ WithBin(firecrackerBinary).
+ WithSocketPath(fcCfg.SocketPath).
+ WithStdin(os.Stdin).
+ WithStdout(os.Stdout).
+ WithStderr(os.Stderr).
+ Build(ctx)
+ machineOpts = append(machineOpts, firecracker.WithProcessRunner(command))
+ m, err := firecracker.NewMachine(vmmCtx, fcCfg, machineOpts...)
+ if err != nil {
+ fmt.Printf("failed to start the vm: %+v\n", err)
+ os.Exit(1)
+ }
+
+ if err := m.Start(vmmCtx); err != nil {
+ fmt.Printf("failed to start the vm: %+v\n", err)
+ os.Exit(1)
+ }
+ defer m.StopVMM()
+
+ if err := m.Wait(vmmCtx); err != nil {
+ fmt.Printf("failed to start the vm: %+v\n", err)
+ os.Exit(1)
+ }
+ log.Print("Machine was started")
+}