From f1f128c6ddc46543d338c82bfe22de42b131e592 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Fri, 27 Jul 2018 19:28:34 +0200 Subject: [PATCH 1/2] Allow `linuxkit run vbox` to use multiple drives VirtualBox hardware (like physical hardware) has only a limited number of IDE device on an IDE Controller. Unfortunately when using an additional drive, it was given the port value of 2, which doesn't exists in VirtualBox IDE controllers (as only 0 and 1 are permitted). This change makes use of the SATA Controller which can host much more drives, to hook the additional drives. Signed-off-by: Brice Figureau --- src/cmd/linuxkit/run_vbox.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cmd/linuxkit/run_vbox.go b/src/cmd/linuxkit/run_vbox.go index 7bc7d5fea..70d2fdeac 100644 --- a/src/cmd/linuxkit/run_vbox.go +++ b/src/cmd/linuxkit/run_vbox.go @@ -171,6 +171,13 @@ func runVbox(args []string) { } } + if len(disks) > 0 { + _, out, err = manage(vboxmanage, "storagectl", name, "--name", "SATA", "--add", "sata") + if err != nil { + log.Fatalf("storagectl error: %v\n%s", err, out) + } + } + for i, d := range disks { id := strconv.Itoa(i) if d.Size != 0 && d.Format == "" { @@ -188,7 +195,7 @@ func runVbox(args []string) { log.Fatalf("Cannot create disk: %v", err) } } - _, out, err = manage(vboxmanage, "storageattach", name, "--storagectl", "IDE Controller", "--port", "2", "--device", id, "--type", "hdd", "--medium", d.Path) + _, out, err = manage(vboxmanage, "storageattach", name, "--storagectl", "SATA", "--port", "0", "--device", id, "--type", "hdd", "--medium", d.Path) if err != nil { log.Fatalf("storageattach error: %v\n%s", err, out) } From 02e5f705897a2fc9f8e4a941fb5f6bb30a30c060 Mon Sep 17 00:00:00 2001 From: Brice Figureau Date: Fri, 27 Jul 2018 19:30:25 +0200 Subject: [PATCH 2/2] Allow to specify more than one networking adapter for vbox Note: this patch introduces an incompatibility in the `linuxkit run vbox` arguments. It wasn't impossible to specify more than one network adapter to the `linuxkit run vbox` command. This patch allows to specify more than one `-networking` argument to specify different network adapters. For instance: ~~~sh linuxkit run vbox -networking type=nat -networking type=hostonly,adapter=vboxnet0 ~~~ will setup the VM with 2 NICs. It is also possible to get rid of the `type` argument. Signed-off-by: Brice Figureau --- docs/platform-vbox.md | 17 ++++++-- src/cmd/linuxkit/run_vbox.go | 81 ++++++++++++++++++++++++++++-------- 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/docs/platform-vbox.md b/docs/platform-vbox.md index 4b1fb86ca..f5f6ce12f 100644 --- a/docs/platform-vbox.md +++ b/docs/platform-vbox.md @@ -20,11 +20,20 @@ stdio, providing interactive access to the VM. ## Disks The Virtualbox backend support configuring a persistent disk using the -standard `linuxkit` `-disk` syntax. Multiple disks are +standard `linuxkit` `-disk` syntax. Multiple disks are supported and can be created in `raw` format; other formats that VirtualBox -supports can be attached +supports can be attached. Note that additional drives are attached to the +SATA Controller, unlike the VM disk which is on the IDE Controller. ## Networking -You can select the networking mode, which defaults to the standard `nat`, but -some networking modes may require additional configuration. +You can select the networking mode, which defaults to the standard `nat`, by using the +`-networking` command-line option. Some networking modes (`hostonly`, `bridge`) will require +the additional `adapter` parameter to the `-networking` option: + +~~~ +-networking hostonly,adapter=vboxnet0 +~~~ + +You can specify more than one `-networking` option to setup multiple adapters. It is +recommended to setup the first adapter as `nat`. diff --git a/src/cmd/linuxkit/run_vbox.go b/src/cmd/linuxkit/run_vbox.go index 70d2fdeac..5e04cbe47 100644 --- a/src/cmd/linuxkit/run_vbox.go +++ b/src/cmd/linuxkit/run_vbox.go @@ -17,6 +17,43 @@ import ( log "github.com/sirupsen/logrus" ) +// VBNetwork is the config for a Virtual Box network +type VBNetwork struct { + Type string + Adapter string +} + +// VBNetworks is the type for a list of VBNetwork +type VBNetworks []VBNetwork + +func (l *VBNetworks) String() string { + return fmt.Sprint(*l) +} + +// Set is used by flag to configure value from CLI +func (l *VBNetworks) Set(value string) error { + d := VBNetwork{} + s := strings.Split(value, ",") + for _, p := range s { + c := strings.SplitN(p, "=", 2) + switch len(c) { + case 1: + d.Type = c[0] + case 2: + switch c[0] { + case "type": + d.Type = c[1] + case "adapter", "bridgeadapter", "hostadapter": + d.Adapter = c[1] + default: + return fmt.Errorf("Unknown network config: %s", c[0]) + } + } + } + *l = append(*l, d) + return nil +} + func runVbox(args []string) { invoked := filepath.Base(os.Args[0]) flags := flag.NewFlagSet("vbox", flag.ExitOnError) @@ -51,8 +88,8 @@ func runVbox(args []string) { uefiBoot := flags.Bool("uefi", false, "Use UEFI boot") // networking - networking := flags.String("networking", "nat", "Networking mode. null|nat|bridged|intnet|hostonly|generic|natnetwork[]") - bridgeadapter := flags.String("bridgeadapter", "", "Bridge adapter interface to use if networking mode is bridged") + var networks VBNetworks + flags.Var(&networks, "networking", "Network config, may be repeated. [type=](null|nat|bridged|intnet|hostonly|generic|natnetwork[])[,[bridge|host]adapter=]") if err := flags.Parse(args); err != nil { log.Fatal("Unable to parse args") @@ -201,25 +238,33 @@ func runVbox(args []string) { } } - _, out, err = manage(vboxmanage, "modifyvm", name, "--nictype1", "virtio") - if err != nil { - log.Fatalf("modifyvm --nictype error: %v\n%s", err, out) - } - - _, out, err = manage(vboxmanage, "modifyvm", name, "--nic1", *networking) - if err != nil { - log.Fatalf("modifyvm --nic error: %v\n%s", err, out) - } - if *networking == "bridged" { - _, out, err = manage(vboxmanage, "modifyvm", name, "--bridgeadapter1", *bridgeadapter) + for i, d := range networks { + nic := i + 1 + _, out, err = manage(vboxmanage, "modifyvm", name, fmt.Sprintf("--nictype%d", nic), "virtio") if err != nil { - log.Fatalf("modifyvm --bridgeadapter error: %v\n%s", err, out) + log.Fatalf("modifyvm --nictype error: %v\n%s", err, out) } - } - _, out, err = manage(vboxmanage, "modifyvm", name, "--cableconnected1", "on") - if err != nil { - log.Fatalf("modifyvm --cableconnected error: %v\n%s", err, out) + _, out, err = manage(vboxmanage, "modifyvm", name, fmt.Sprintf("--nic%d", nic), d.Type) + if err != nil { + log.Fatalf("modifyvm --nic error: %v\n%s", err, out) + } + if d.Type == "hostonly" { + _, out, err = manage(vboxmanage, "modifyvm", name, fmt.Sprintf("--hostonlyadapter%d", nic), d.Adapter) + if err != nil { + log.Fatalf("modifyvm --hostonlyadapter error: %v\n%s", err, out) + } + } else if d.Type == "bridged" { + _, out, err = manage(vboxmanage, "modifyvm", name, fmt.Sprintf("--bridgeadapter%d", nic), d.Adapter) + if err != nil { + log.Fatalf("modifyvm --bridgeadapter error: %v\n%s", err, out) + } + } + + _, out, err = manage(vboxmanage, "modifyvm", name, fmt.Sprintf("--cableconnected%d", nic), "on") + if err != nil { + log.Fatalf("modifyvm --cableconnected error: %v\n%s", err, out) + } } // create socket