Skip to content

Commit

Permalink
Added hyperkit options for enterprise VPN support
Browse files Browse the repository at this point in the history
The purpose of these changes is to enhance Hyperkit support from the
minikube command line for better integration with enterprise networks
behind a VPN.

uuid: Provide VM UUID to restore MAC address (only supported with
      Hyperkit driver).
vpnkitSock: Location of the VPNKit socket used for networking. If empty,
            disables Hyperkit VPNKitSock, if 'auto' uses Docker for Mac
            VPNKit connection, otherwise uses the specified VSock."
vsockPorts: List of guest VSock ports that should be exposed as sockets
            on the host (Only supported on with hyperkit now).

Note:
tests pass but file:
`vendor/github.com/google/certificate-transparency/go/x509/root_darwin.go`
has to be edited to correct an issue - not committed since this is in
the vendor directory.
  • Loading branch information
seborama committed May 29, 2018
1 parent c6239b4 commit 821747a
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 16 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ REPOPATH ?= $(ORG)/docker-machine-driver-hyperkit
vendor:
dep ensure -v

.PHONY: test
test: vendor
go test -cover -race -parallel 2 ./...

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

Expand Down
68 changes: 52 additions & 16 deletions pkg/hyperkit/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,21 @@ import (
"os/user"
"path"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"

"regexp"

"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/log"
"github.com/docker/machine/libmachine/mcnutils"
"github.com/docker/machine/libmachine/state"
nfsexports "github.com/johanneswuerbach/nfsexports"
pkgdrivers "github.com/machine-drivers/docker-machine-driver-hyperkit/pkg/drivers"
hyperkit "github.com/moby/hyperkit/go"
"github.com/pkg/errors"
pkgdrivers "github.com/machine-drivers/docker-machine-driver-hyperkit/pkg/drivers"
"regexp"
"github.com/docker/machine/libmachine/mcnutils"
)

const (
Expand Down Expand Up @@ -66,10 +68,12 @@ type Driver struct {
NFSShares []string
NFSSharesRoot string
UUID string
BootKernel string
BootInitrd string
Initrd string
Vmlinuz string
BootKernel string
BootInitrd string
Initrd string
Vmlinuz string
VpnKitSock string
VSockPorts []string
}

func NewDriver(hostName, storePath string) *Driver {
Expand Down Expand Up @@ -103,7 +107,7 @@ func (d *Driver) Create() error {

isoPath := d.ResolveStorePath(isoFilename)
if err := d.extractKernel(isoPath); err != nil {
return err
return errors.Wrap(err, "extracting kernel")
}

return d.Start()
Expand Down Expand Up @@ -175,25 +179,32 @@ func (d *Driver) Restart() error {

// Start a host
func (d *Driver) Start() error {
h, err := hyperkit.New("", "", filepath.Join(d.StorePath, "machines", d.MachineName))
h, err := hyperkit.New("", d.VpnKitSock, filepath.Join(d.StorePath, "machines", d.MachineName))
if err != nil {
return err
return errors.Wrap(err, "new-ing Hyperkit")
}

// TODO: handle the rest of our settings.
h.Kernel = d.ResolveStorePath(d.Vmlinuz)
h.Initrd =d.ResolveStorePath(d.Initrd)
h.Initrd = d.ResolveStorePath(d.Initrd)
h.VMNet = true
h.ISOImages = []string{d.ResolveStorePath(isoFilename)}
h.Console = hyperkit.ConsoleFile
h.CPUs = d.CPU
h.Memory = d.Memory
h.UUID = d.UUID

if vsockPorts, err := d.extractVSockPorts(); err != nil {
return err
} else if len(vsockPorts) >= 1 {
h.VSock = true
h.VSockPorts = vsockPorts
}

log.Infof("Using UUID %s", h.UUID)
mac, err := GetMACAddressFromUUID(h.UUID)
if err != nil {
return err
return errors.Wrap(err, "getting MAC address from UUID")
}

// Need to strip 0's
Expand All @@ -208,7 +219,7 @@ func (d *Driver) Start() error {
}
log.Infof("Starting with cmdline: %s", d.Cmdline)
if err := h.Start(d.Cmdline); err != nil {
return err
return errors.Wrapf(err, "starting with cmd line: %s", d.Cmdline)
}

getIP := func() error {
Expand Down Expand Up @@ -275,11 +286,11 @@ func (d *Driver) extractKernel(isoPath string) error {
return nil
})
}
if d.BootKernel == "" || d.BootInitrd == "" {

if d.BootKernel == "" || d.BootInitrd == "" {
err := fmt.Errorf("==== Can't extract Kernel and Ramdisk file ====")
return err
}
}

dest := d.ResolveStorePath(d.Vmlinuz)
log.Debugf("Extracting %s into %s", d.BootKernel, dest)
Expand All @@ -296,6 +307,31 @@ func (d *Driver) extractKernel(isoPath string) error {
return nil
}

// InvalidPortNumberError implements the Error interface.
// It is used when a VSockPorts port number cannot be recognised as an integer.
type InvalidPortNumberError string

// Error returns an Error for InvalidPortNumberError
func (port InvalidPortNumberError) Error() string {
return fmt.Sprintf("vsock port '%s' is not an integer", string(port))
}

func (d *Driver) extractVSockPorts() ([]int, error) {
vsockPorts := make([]int, 0, len(d.VSockPorts))

for _, port := range d.VSockPorts {
p, err := strconv.Atoi(port)
if err != nil {
var err InvalidPortNumberError
err = InvalidPortNumberError(port)
return nil, err
}
vsockPorts = append(vsockPorts, p)
}

return vsockPorts, nil
}

func (d *Driver) setupNFSShare() error {
user, err := user.Current()
if err != nil {
Expand Down
86 changes: 86 additions & 0 deletions pkg/hyperkit/driver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// +build darwin

/*
Copyright 2018 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package hyperkit

import (
"testing"
)

func Test_portExtraction(t *testing.T) {
tests := []struct {
name string
ports []string
want []int
wantErr error
}{
{
"valid_empty",
[]string{},
[]int{},
nil,
},
{
"valid_list",
[]string{"10", "20", "30"},
[]int{10, 20, 30},
nil,
},
{
"invalid",
[]string{"8080", "not_an_integer"},
nil,
InvalidPortNumberError("not_an_integer"),
},
}

for _, tt := range tests {
d := NewDriver("", "")
d.VSockPorts = tt.ports
got, gotErr := d.extractVSockPorts()
if !testEq(got, tt.want) {
t.Errorf("extractVSockPorts() got: %v, want: %v", got, tt.want)
}
if gotErr != tt.wantErr {
t.Errorf("extractVSockPorts() gotErr: %s, wantErr: %s", gotErr.Error(), tt.wantErr.Error())
}
}
}

func testEq(a, b []int) bool {

if a == nil && b == nil {
return true
}

if a == nil || b == nil {
return false
}

if len(a) != len(b) {
return false
}

for i := range a {
if a[i] != b[i] {
return false
}
}

return true
}

0 comments on commit 821747a

Please sign in to comment.