From c2bd4b8dbadd7b2f87a81c811cfe17c257dfb184 Mon Sep 17 00:00:00 2001 From: Zhang Wei Date: Wed, 14 Jun 2017 17:23:12 +0800 Subject: [PATCH] Add cbfs support Export and Support starting VM with bios+cbfs from runv command, also use CBFS as first choice when kernel also exists. Signed-off-by: Zhang Wei --- containerd/containerd.go | 14 +++++-- create.go | 65 +++++++-------------------------- main.go | 16 +++++++- utils.go | 79 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 56 deletions(-) create mode 100644 utils.go diff --git a/containerd/containerd.go b/containerd/containerd.go index 4ce76363..5d115721 100644 --- a/containerd/containerd.go +++ b/containerd/containerd.go @@ -80,6 +80,8 @@ var ContainerdCommand = cli.Command{ driver := context.GlobalString("driver") kernel := context.GlobalString("kernel") initrd := context.GlobalString("initrd") + bios := context.GlobalString("bios") + cbfs := context.GlobalString("cbfs") vsock := context.GlobalBool("vsock") template := context.GlobalString("template") stateDir := context.String("state-dir") @@ -105,14 +107,16 @@ var ContainerdCommand = cli.Command{ if (driver != "" && driver != tconfig.Driver) || (kernel != "" && kernel != tconfig.Config.Kernel) || - (initrd != "" && initrd != tconfig.Config.Initrd) { - glog.Warningf("template config is not match the driver, kernel or initrd argument, disable template") + (initrd != "" && initrd != tconfig.Config.Initrd) || + (bios != "" && bios != tconfig.Config.Bios) || + (cbfs != "" && cbfs != tconfig.Config.Cbfs) { + glog.Warningf("template config is not match the driver, kernel, initrd, bios or cbfs argument, disable template") template = "" } else if driver == "" { driver = tconfig.Driver } - } else if kernel == "" || initrd == "" { - glog.Error("argument kernel and initrd must be set") + } else if (bios == "" || cbfs == "") && (kernel == "" || initrd == "") { + glog.Error("argument kernel+initrd or bios+cbfs must be set") os.Exit(1) } @@ -130,6 +134,8 @@ var ContainerdCommand = cli.Command{ bootConfig := hypervisor.BootConfig{ Kernel: kernel, Initrd: initrd, + Bios: bios, + Cbfs: cbfs, EnableVsock: vsock, } f = singlefactory.Dummy(bootConfig) diff --git a/create.go b/create.go index 9c52f685..873203a5 100644 --- a/create.go +++ b/create.go @@ -18,23 +18,6 @@ import ( netcontext "golang.org/x/net/context" ) -func firstExistingFile(candidates []string) string { - for _, file := range candidates { - if _, err := os.Stat(file); err == nil { - return file - } - } - return "" -} - -func getDefaultBundlePath() string { - cwd, err := os.Getwd() - if err != nil { - return "" - } - return cwd -} - var createCommand = cli.Command{ Name: "create", Usage: "create a container", @@ -140,38 +123,6 @@ func runContainer(context *cli.Context, createOnly bool) { } } - kernel := context.GlobalString("kernel") - initrd := context.GlobalString("initrd") - // only set the default kernel/initrd when it is the first container(sharedContainer == "") - if kernel == "" && sharedContainer == "" { - kernel = firstExistingFile([]string{ - filepath.Join(bundle, spec.Root.Path, "boot/vmlinuz"), - filepath.Join(bundle, "boot/vmlinuz"), - filepath.Join(bundle, "vmlinuz"), - "/var/lib/hyper/kernel", - }) - } - if initrd == "" && sharedContainer == "" { - initrd = firstExistingFile([]string{ - filepath.Join(bundle, spec.Root.Path, "boot/initrd.img"), - filepath.Join(bundle, "boot/initrd.img"), - filepath.Join(bundle, "initrd.img"), - "/var/lib/hyper/hyper-initrd.img", - }) - } - - // convert the paths to abs - kernel, err = filepath.Abs(kernel) - if err != nil { - fmt.Fprintf(os.Stderr, "Cannot get abs path for kernel: %v\n", err) - os.Exit(-1) - } - initrd, err = filepath.Abs(initrd) - if err != nil { - fmt.Fprintf(os.Stderr, "Cannot get abs path for initrd: %v\n", err) - os.Exit(-1) - } - var namespace string var cmd *exec.Cmd if sharedContainer != "" { @@ -188,6 +139,12 @@ func runContainer(context *cli.Context, createOnly bool) { os.Exit(-1) } + kernel, initrd, bios, cbfs, err := getKernelFiles(context, spec.Root.Path) + if err != nil { + fmt.Fprintf(os.Stderr, "Can't find kernel/initrd/bios/cbfs files") + os.Exit(-1) + } + namespace, err = ioutil.TempDir("/run", "runv-namespace-") if err != nil { fmt.Fprintf(os.Stderr, "Failed to create runv namespace path: %v", err) @@ -195,11 +152,17 @@ func runContainer(context *cli.Context, createOnly bool) { } args := []string{ - "--kernel", kernel, - "--initrd", initrd, "--default_cpus", fmt.Sprintf("%d", context.GlobalInt("default_cpus")), "--default_memory", fmt.Sprintf("%d", context.GlobalInt("default_memory")), } + + // if user set bios+cbfs, then use bios+cbfs first + if context.GlobalString("bios") != "" && context.GlobalString("cbfs") != "" { + args = append(args, "--bios", bios, "--cbfs", cbfs) + } else { + args = append(args, "--kernel", kernel, "--initrd", initrd) + } + if context.GlobalBool("debug") { args = append(args, "--debug") } diff --git a/main.go b/main.go index 633137d9..ca254907 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,7 @@ import ( "time" "github.com/docker/docker/pkg/reexec" + "github.com/golang/glog" "github.com/golang/protobuf/ptypes" "github.com/hyperhq/runv/containerd" "github.com/hyperhq/runv/containerd/api/grpc/types" @@ -109,6 +110,14 @@ func main() { Name: "initrd", Usage: "runv-compatible initrd for the container", }, + cli.StringFlag{ + Name: "bios", + Usage: "bios for the container", + }, + cli.StringFlag{ + Name: "cbfs", + Usage: "cbfs for the container", + }, cli.StringFlag{ Name: "template", Usage: "path to the template vm state directory", @@ -132,6 +141,11 @@ func main() { } return nil } + app.After = func(context *cli.Context) error { + // make sure glog flush all the messages to file + glog.Flush() + return nil + } app.Commands = []cli.Command{ createCommand, @@ -147,7 +161,7 @@ func main() { containerd.ContainerdCommand, } if err := app.Run(os.Args); err != nil { - fmt.Printf("%s\n", err.Error()) + fmt.Fprintf(os.Stderr, "%v", err) } } diff --git a/utils.go b/utils.go new file mode 100644 index 00000000..24e65e4c --- /dev/null +++ b/utils.go @@ -0,0 +1,79 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/urfave/cli" +) + +const ( + defaultKernelInstallDir string = "/var/lib/hyper" +) + +func firstExistingFile(candidates []string) string { + for _, file := range candidates { + if _, err := os.Stat(file); err == nil { + return file + } + } + return "" +} + +func getDefaultBundlePath() string { + cwd, err := os.Getwd() + if err != nil { + return "" + } + return cwd +} + +// getKernelFiles chooses kernel/initrd/bios/cbfs files based on user specified ones +func getKernelFiles(context *cli.Context, rootPath string) (string, string, string, string, error) { + kernel := context.GlobalString("kernel") + initrd := context.GlobalString("initrd") + bios := context.GlobalString("bios") + cbfs := context.GlobalString("cbfs") + bundle := context.String("bundle") + + for k, v := range map[*string][]string{ + &kernel: { + filepath.Join(bundle, rootPath, "boot/vmlinuz"), + filepath.Join(bundle, "boot/vmlinuz"), + filepath.Join(bundle, "vmlinuz"), + filepath.Join(defaultKernelInstallDir, "kernel"), + }, + &initrd: { + filepath.Join(bundle, rootPath, "boot/initrd.img"), + filepath.Join(bundle, "boot/initrd.img"), + filepath.Join(bundle, "initrd.img"), + filepath.Join(defaultKernelInstallDir, "hyper-initrd.img"), + }, + &bios: { + filepath.Join(bundle, rootPath, "boot/bios.bin"), + filepath.Join(bundle, "boot/bios.bin"), + filepath.Join(bundle, "bios.bin"), + filepath.Join(defaultKernelInstallDir, "bios.bin"), + }, + &cbfs: { + filepath.Join(bundle, rootPath, "boot/cbfs.rom"), + filepath.Join(bundle, "boot/cbfs.rom"), + filepath.Join(bundle, "cbfs.rom"), + filepath.Join(defaultKernelInstallDir, "cbfs.rom"), + }, + } { + if *k == "" { + *k = firstExistingFile(v) + } + if *k != "" { + var err error + *k, err = filepath.Abs(*k) + if err != nil { + return "", "", "", "", fmt.Errorf("cannot get abs path for kernel files: %v", err) + } + } + } + + return kernel, initrd, bios, cbfs, nil +}