diff --git a/src/cmd/linuxkit/run_hyperkit.go b/src/cmd/linuxkit/run_hyperkit.go index a76204165..48fb563bf 100644 --- a/src/cmd/linuxkit/run_hyperkit.go +++ b/src/cmd/linuxkit/run_hyperkit.go @@ -8,12 +8,19 @@ import ( "os" "os/exec" "path/filepath" + "strings" log "github.com/Sirupsen/logrus" "github.com/moby/hyperkit/go" "github.com/satori/go.uuid" ) +const ( + networkingNone string = "none" + networkingDockerForMac = "docker-for-mac" + networkingVPNKit = "vpnkit" +) + // Process the run arguments and execute run func runHyperKit(args []string) { flags := flag.NewFlagSet("hyperkit", flag.ExitOnError) @@ -34,9 +41,7 @@ func runHyperKit(args []string) { ipStr := flags.String("ip", "", "IP address for the VM") state := flags.String("state", "", "Path to directory to keep VM state in") vsockports := flags.String("vsock-ports", "", "List of vsock ports to forward from the guest on startup (comma separated). A unix domain socket for each port will be created in the state directory") - startVPNKit := flags.Bool("start-vpnkit", false, "Launch a new VPNKit instead of reusing the instance from Docker for Mac. The new instance will be on a separate internal network. This enables IP port forwarding from the host to the guest if the guest supports it.") - vpnKitDefaultSocket := filepath.Join(os.Getenv("HOME"), "Library/Containers/com.docker.docker/Data/s50") - vpnKitEthernetSocket := flags.String("vpnkit-socket", vpnKitDefaultSocket, "Path to VPNKit ethernet socket. The Docker for Mac socket is used by default. Overridden if -start-vpnkit is set.") + networking := flags.String("networking", networkingDockerForMac, "Networking mode. Valid options are 'docker-for-mac', 'vpnkit[,socket-path]' and 'none'. 'docker-for-mac' connects to the network used by Docker for Mac. 'vpnkit' connects to the VPNKit socket specified. If socket-path is omitted a new VPNKit instance will be started and 'vpnkit_eth.sock' will be created in the state directory. 'none' disables networking.`") if err := flags.Parse(args); err != nil { log.Fatal("Unable to parse args") @@ -105,29 +110,8 @@ func runHyperKit(args []string) { *disk = filepath.Join(*state, "disk.img") } - var vpnKitPortSocket string - var vpnKitProcess *os.Process - - // Launch new VPNKit if needed - if *startVPNKit { - *vpnKitEthernetSocket = filepath.Join(*state, "vpnkit_eth.sock") - vpnKitPortSocket = filepath.Join(*state, "vpnkit_port.sock") - vsockSocket := filepath.Join(*state, "connect") - vpnKitProcess, err = launchVPNKit(*vpnKitEthernetSocket, vsockSocket, vpnKitPortSocket) - if err != nil { - log.Fatalln("Unable to start vpnkit: ", err) - } - defer func() { - if vpnKitProcess != nil { - err := vpnKitProcess.Kill() - if err != nil { - log.Println(err) - } - } - }() - } - - h, err := hyperkit.New(*hyperkitPath, *vpnKitEthernetSocket, *state) + // Create new HyperKit instance (w/o networking for now) + h, err := hyperkit.New(*hyperkitPath, "", *state) if err != nil { log.Fatalln("Error creating hyperkit: ", err) } @@ -136,6 +120,45 @@ func runHyperKit(args []string) { log.Fatalln("Unable to parse vsock-ports: ", err) } + // Select network mode + var vpnKitProcess *os.Process + netMode := strings.SplitN(*networking, ",", 2) + + switch netMode[0] { + case networkingDockerForMac: + h.VPNKitSock = filepath.Join(os.Getenv("HOME"), "Library/Containers/com.docker.docker/Data/s50") + case networkingVPNKit: + if len(netMode) > 1 { + // Socket path specified, try to use existing VPNKit instance + h.VPNKitSock = netMode[1] + } else { + // Start new VPNKit instance + h.VPNKitSock = filepath.Join(*state, "vpnkit_eth.sock") + vpnKitPortSocket := filepath.Join(*state, "vpnkit_port.sock") + vsockSocket := filepath.Join(*state, "connect") + vpnKitProcess, err = launchVPNKit(h.VPNKitSock, vsockSocket, vpnKitPortSocket) + if err != nil { + log.Fatalln("Unable to start vpnkit: ", err) + } + defer func() { + if vpnKitProcess != nil { + err := vpnKitProcess.Kill() + if err != nil { + log.Println(err) + } + } + }() + // The guest will use this 9P mount to configure which ports to forward + h.Sockets9P = []hyperkit.Socket9P{{Path: vpnKitPortSocket, Tag: "port"}} + // VSOCK port 62373 is used to pass traffic from host->guest + h.VSockPorts = append(h.VSockPorts, 62373) + } + case networkingNone: + h.VPNKitSock = "" + default: + log.Fatalf("Invalid networking mode: %s", netMode[0]) + } + h.Kernel = prefix + "-kernel" h.Initrd = prefix + "-initrd.img" h.VPNKitKey = vpnKitKey @@ -147,14 +170,6 @@ func runHyperKit(args []string) { h.Memory = *mem h.DiskSize = diskSz - // Add 9p and vsock for port forwarding if VPNKit is launched automatically - if *startVPNKit { - // The guest will use this 9P mount to configure which ports to forward - h.Sockets9P = []hyperkit.Socket9P{{Path: vpnKitPortSocket, Tag: "port"}} - // VSOCK port 62373 is used to pass traffic from host->guest - h.VSockPorts = append(h.VSockPorts, 62373) - } - err = h.Run(string(cmdline)) if err != nil { log.Fatalf("Cannot run hyperkit: %v", err) diff --git a/vendor.conf b/vendor.conf index e19777fa9..6a9ed128e 100644 --- a/vendor.conf +++ b/vendor.conf @@ -5,7 +5,7 @@ github.com/docker/infrakit cb420e3e50ea60afe58538b1d3cab1cb14059433 github.com/golang/protobuf c9c7427a2a70d2eb3bafa0ab2dc163e45f143317 github.com/googleapis/gax-go 8c5154c0fe5bf18cf649634d4c6df50897a32751 github.com/mitchellh/go-ps 4fdf99ab29366514c69ccccddab5dc58b8d84062 -github.com/moby/hyperkit 95a60c3e75ac73a1cfd73bacdb5de94a737b6095 +github.com/moby/hyperkit 70205a6d5143340299a679af259f70dfcd7cf8a4 github.com/packethost/packngo 91d54000aa56874149d348a884ba083c41d38091 github.com/rneugeba/iso9660wrap 4606f848a055435cdef85305960b0e1bb788d506 github.com/satori/go.uuid b061729afc07e77a8aa4fad0a2fd840958f1942a diff --git a/vendor/github.com/moby/hyperkit/go/hyperkit.go b/vendor/github.com/moby/hyperkit/go/hyperkit.go index 3a3398ee4..1b67e0046 100644 --- a/vendor/github.com/moby/hyperkit/go/hyperkit.go +++ b/vendor/github.com/moby/hyperkit/go/hyperkit.go @@ -553,6 +553,9 @@ func checkVPNKitSock(vpnkitsock string) (string, error) { if vpnkitsock == "auto" { vpnkitsock = filepath.Join(getHome(), defaultVPNKitSock) } + if vpnkitsock == "" { + return "", nil + } vpnkitsock = filepath.Clean(vpnkitsock) _, err := os.Stat(vpnkitsock)