Skip to content

Moving minikube hyperkit changes upstream #13

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -2,10 +2,13 @@

/*
Copyright 2016 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.
@@ -16,10 +19,19 @@ limitations under the License.
package main

import (
"fmt"
"os"

"github.com/docker/machine/libmachine/drivers/plugin"
"github.com/machine-drivers/docker-machine-driver-hyperkit/pkg/hyperkit"
)

func main() {
if len(os.Args) > 1 && os.Args[1] == "version" {
fmt.Println("version:", hyperkit.GetVersion())
fmt.Println("commit:", hyperkit.GetGitCommitID())
return
}

plugin.RegisterDriver(hyperkit.NewDriver("", ""))
}
67 changes: 40 additions & 27 deletions pkg/drivers/drivers.go
Original file line number Diff line number Diff line change
@@ -17,57 +17,62 @@ limitations under the License.
package drivers

import (
"io"
"io/ioutil"
"os"
"path/filepath"
"syscall"

"github.com/cloudflare/cfssl/log"
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/mcnflag"
"github.com/docker/machine/libmachine/mcnutils"
"github.com/docker/machine/libmachine/ssh"
"github.com/golang/glog"
"github.com/pkg/errors"
)

// GetDiskPath returns the path of the machine disk image
func GetDiskPath(d *drivers.BaseDriver) string {
return filepath.Join(d.ResolveStorePath("."), d.GetMachineName()+".rawdisk")
}

// CommonDriver is the common driver base class
type CommonDriver struct{}

//Not implemented yet
// GetCreateFlags is not implemented yet
func (d *CommonDriver) GetCreateFlags() []mcnflag.Flag {
return nil
}

//Not implemented yet
// SetConfigFromFlags is not implemented yet
func (d *CommonDriver) SetConfigFromFlags(flags drivers.DriverOptions) error {
return nil
}

func createRawDiskImage(sshKeyPath, diskPath string, diskSizeMb int) error {
tarBuf, err := mcnutils.MakeDiskImage(sshKeyPath)
if err != nil {
return err
return errors.Wrap(err, "make disk image")
}

file, err := os.OpenFile(diskPath, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
if err != nil {
return err
return errors.Wrap(err, "open")
}
defer file.Close()
file.Seek(0, os.SEEK_SET)
if _, err := file.Seek(0, io.SeekStart); err != nil {
return errors.Wrap(err, "seek")
}

if _, err := file.Write(tarBuf.Bytes()); err != nil {
return err
return errors.Wrap(err, "write tar")
}
if err := file.Close(); err != nil {
return errors.Wrapf(err, "closing file %s", diskPath)
}

if err := os.Truncate(diskPath, int64(diskSizeMb*1000000)); err != nil {
return err
return errors.Wrap(err, "truncate")
}
return nil
}
@@ -79,46 +84,54 @@ func publicSSHKeyPath(d *drivers.BaseDriver) string {
// Restart a host. This may just call Stop(); Start() if the provider does not
// have any special restart behaviour.
func Restart(d drivers.Driver) error {
for _, f := range []func() error{d.Stop, d.Start} {
if err := f(); err != nil {
return err
}
if err := d.Stop(); err != nil {
return err
}
return nil

return d.Start()
}

// MakeDiskImage makes a boot2docker VM disk image.
func MakeDiskImage(d *drivers.BaseDriver, boot2dockerURL string, diskSize int) error {
//TODO(r2d4): rewrite this, not using b2dutils
b2dutils := mcnutils.NewB2dUtils(d.StorePath)
if err := b2dutils.CopyIsoToMachineDir(boot2dockerURL, d.MachineName); err != nil {
return errors.Wrap(err, "Error copying ISO to machine dir")
glog.Infof("Making disk image using store path: %s", d.StorePath)
b2 := mcnutils.NewB2dUtils(d.StorePath)
if err := b2.CopyIsoToMachineDir(boot2dockerURL, d.MachineName); err != nil {
return errors.Wrap(err, "copy iso to machine dir")
}

log.Info("Creating ssh key...")
if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil {
return err
keyPath := d.GetSSHKeyPath()
glog.Infof("Creating ssh key: %s...", keyPath)
if err := ssh.GenerateSSHKey(keyPath); err != nil {
return errors.Wrap(err, "generate ssh key")
}

log.Info("Creating raw disk image...")
diskPath := GetDiskPath(d)
glog.Infof("Creating raw disk image: %s...", diskPath)
if _, err := os.Stat(diskPath); os.IsNotExist(err) {
if err := createRawDiskImage(publicSSHKeyPath(d), diskPath, diskSize); err != nil {
return err
return errors.Wrapf(err, "createRawDiskImage(%s)", diskPath)
}
if err := fixPermissions(d.ResolveStorePath(".")); err != nil {
return err
machPath := d.ResolveStorePath(".")
if err := fixPermissions(machPath); err != nil {
return errors.Wrapf(err, "fixing permissions on %s", machPath)
}
}
return nil
}

func fixPermissions(path string) error {
os.Chown(path, syscall.Getuid(), syscall.Getegid())
files, _ := ioutil.ReadDir(path)
glog.Infof("Fixing permissions on %s ...", path)
if err := os.Chown(path, syscall.Getuid(), syscall.Getegid()); err != nil {
return errors.Wrap(err, "chown dir")
}
files, err := ioutil.ReadDir(path)
if err != nil {
return errors.Wrap(err, "read dir")
}
for _, f := range files {
fp := filepath.Join(path, f.Name())
if err := os.Chown(fp, syscall.Getuid(), syscall.Getegid()); err != nil {
return err
return errors.Wrap(err, "chown file")
}
}
return nil
50 changes: 50 additions & 0 deletions pkg/drivers/drivers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright 2016 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 drivers

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"k8s.io/minikube/pkg/minikube/tests"
)

func Test_createDiskImage(t *testing.T) {
tmpdir := tests.MakeTempDir()
defer os.RemoveAll(tmpdir)

sshPath := filepath.Join(tmpdir, "ssh")
if err := ioutil.WriteFile(sshPath, []byte("mysshkey"), 0644); err != nil {
t.Fatalf("writefile: %v", err)
}
diskPath := filepath.Join(tmpdir, "disk")

sizeInMb := 100
sizeInBytes := int64(sizeInMb) * 1000000
if err := createRawDiskImage(sshPath, diskPath, sizeInMb); err != nil {
t.Errorf("createDiskImage() error = %v", err)
}
fi, err := os.Lstat(diskPath)
if err != nil {
t.Errorf("Lstat() error = %v", err)
}
if fi.Size() != sizeInBytes {
t.Errorf("Disk size is %v, want %v", fi.Size(), sizeInBytes)
}
}
366 changes: 212 additions & 154 deletions pkg/hyperkit/driver.go

Large diffs are not rendered by default.

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
}
65 changes: 65 additions & 0 deletions pkg/hyperkit/iso.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
Copyright 2016 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 (
"fmt"
"io"
"os"
"strings"

"github.com/hooklift/iso9660"
)

// ExtractFile extracts a file from an ISO
func ExtractFile(isoPath, srcPath, destPath string) error {
iso, err := os.Open(isoPath)
if err != nil {
return err
}
defer iso.Close()

r, err := iso9660.NewReader(iso)
if err != nil {
return err
}

f, err := findFile(r, srcPath)
if err != nil {
return err
}

dst, err := os.Create(destPath)
if err != nil {
return err
}
defer dst.Close()

_, err = io.Copy(dst, f.Sys().(io.Reader))
return err
}

func findFile(r *iso9660.Reader, path string) (os.FileInfo, error) {
// Look through the ISO for a file with a matching path.
for f, err := r.Next(); err != io.EOF; f, err = r.Next() {
// For some reason file paths in the ISO sometimes contain a '.' character at the end, so strip that off.
if strings.TrimSuffix(f.Name(), ".") == path {
return f, nil
}
}
return nil, fmt.Errorf("unable to find file %s", path)
}
48 changes: 31 additions & 17 deletions pkg/hyperkit/network.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// +build darwin

/*
Copyright 2016 The Kubernetes Authors All rights reserved.
@@ -25,14 +27,24 @@ import (
"os/exec"
"regexp"
"strings"

"github.com/docker/machine/libmachine/log"
)

const (
DHCPLeasesFile = "/var/db/dhcpd_leases"
CONFIG_PLIST = "/Library/Preferences/SystemConfiguration/com.apple.vmnet"
NET_ADDR_KEY = "Shared_Net_Address"
// LeasesPath is the path to dhcpd leases
LeasesPath = "/var/db/dhcpd_leases"
// VMNetDomain is the domain for vmnet
VMNetDomain = "/Library/Preferences/SystemConfiguration/com.apple.vmnet"
// SharedNetAddrKey is the key for the network address
SharedNetAddrKey = "Shared_Net_Address"
)

var (
leadingZeroRegexp = regexp.MustCompile(`0([A-Fa-f0-9](:|$))`)
)

// DHCPEntry holds a parsed DNS entry
type DHCPEntry struct {
Name string
IPAddress string
@@ -41,11 +53,13 @@ type DHCPEntry struct {
Lease string
}

// GetIPAddressByMACAddress gets the IP address of a MAC address
func GetIPAddressByMACAddress(mac string) (string, error) {
return getIpAddressFromFile(mac, DHCPLeasesFile)
return getIPAddressFromFile(mac, LeasesPath)
}

func getIpAddressFromFile(mac, path string) (string, error) {
func getIPAddressFromFile(mac, path string) (string, error) {
log.Debugf("Searching for %s in %s ...", mac, path)
file, err := os.Open(path)
if err != nil {
return "", err
@@ -56,12 +70,15 @@ func getIpAddressFromFile(mac, path string) (string, error) {
if err != nil {
return "", err
}
log.Debugf("Found %d entries in %s!", len(dhcpEntries), path)
for _, dhcpEntry := range dhcpEntries {
log.Debugf("dhcp entry: %+v", dhcpEntry)
if dhcpEntry.HWAddress == mac {
log.Debugf("Found match: %s", mac)
return dhcpEntry.IPAddress, nil
}
}
return "", fmt.Errorf("Could not find an IP address for %s", mac)
return "", fmt.Errorf("could not find an IP address for %s", mac)
}

func parseDHCPdLeasesFile(file io.Reader) ([]DHCPEntry, error) {
@@ -99,33 +116,30 @@ func parseDHCPdLeasesFile(file io.Reader) ([]DHCPEntry, error) {
case "lease":
dhcpEntry.Lease = val
default:
return dhcpEntries, fmt.Errorf("Unable to parse line: %s", line)
return dhcpEntries, fmt.Errorf("unable to parse line: %s", line)
}
}
return dhcpEntries, scanner.Err()
}

// trimMacAddress trimming "0" of the ten's digit
func trimMacAddress(rawUUID string) string {
re := regexp.MustCompile(`0([A-Fa-f0-9](:|$))`)
mac := re.ReplaceAllString(rawUUID, "$1")

return mac
return leadingZeroRegexp.ReplaceAllString(rawUUID, "$1")
}

// GetNetAddr gets the network address for vmnet
func GetNetAddr() (net.IP, error) {
_, err := os.Stat(CONFIG_PLIST + ".plist")
if err != nil {
return nil, fmt.Errorf("Does not exist %s", CONFIG_PLIST+".plist")
plistPath := VMNetDomain + ".plist"
if _, err := os.Stat(plistPath); err != nil {
return nil, fmt.Errorf("stat: %v", err)
}

out, err := exec.Command("defaults", "read", CONFIG_PLIST, NET_ADDR_KEY).Output()
out, err := exec.Command("defaults", "read", VMNetDomain, SharedNetAddrKey).Output()
if err != nil {
return nil, err
}
ip := net.ParseIP(strings.TrimSpace(string(out)))
if ip == nil {
return nil, fmt.Errorf("Could not get the network address for vmnet")
return nil, fmt.Errorf("could not get the network address for vmnet")
}
return ip, nil
}
105 changes: 105 additions & 0 deletions pkg/hyperkit/network_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// +build darwin

/*
Copyright 2016 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 (
"io/ioutil"
"os"
"path/filepath"
"testing"
)

var validLeases = []byte(`{
name=foo
ip_address=1.2.3.4
hw_address=1,a1:b2:c3:d4:e5:f6
identifier=1,a2:b3:c4:d5:e6:f7
lease=0x597e1267
}
{
name=bar
ip_address=192.168.64.3
hw_address=1,a4:b5:c6:d7:e8:f9
identifier=1,a0:b0:c0:d0:e0:f0
lease=0x597e1267
}
{
name=bar
ip_address=192.168.64.4
hw_address=1,a5:b6:c7:d8:e9:f1
identifier=1,a5:b6:c7:d8:e9:f1
lease=0x597e1268
}`)

func Test_getIpAddressFromFile(t *testing.T) {
tmpdir := ioutil.TempDir()
defer os.RemoveAll(tmpdir)

dhcpFile := filepath.Join(tmpdir, "dhcp")
if err := ioutil.WriteFile(dhcpFile, validLeases, 0644); err != nil {
t.Fatalf("writefile: %v", err)
}

invalidFile := filepath.Join(tmpdir, "invalid")
if err := ioutil.WriteFile(invalidFile, []byte("foo"), 0644); err != nil {
t.Fatalf("writefile: %v", err)
}

type args struct {
mac string
path string
}
tests := []struct {
name string
args args
want string
wantErr bool
}{
{
"valid",
args{"a1:b2:c3:d4:e5:f6", dhcpFile},
"1.2.3.4",
false,
},
{
"duplicate",
args{"a4:b5:c6:d7:e8:f9", dhcpFile},
"192.168.64.3",
false,
},
{
"invalid",
args{"a1:b2:c3:d4:e5:f6", invalidFile},
"",
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := getIPAddressFromFile(tt.args.mac, tt.args.path)
if (err != nil) != tt.wantErr {
t.Errorf("getIPAddressFromFile() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("getIPAddressFromFile() = %v, want %v", got, tt.want)
}
})
}
}
106 changes: 0 additions & 106 deletions pkg/hyperkit/util.go

This file was deleted.

35 changes: 35 additions & 0 deletions pkg/hyperkit/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Copyright 2016 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

// The current version of the docker-machine-driver-hyperkit

// version is a private field and should be set when compiling with --ldflags="-X k8s.io/minikube/pkg/drivers/hyperkit.version=vX.Y.Z"
var version = "v0.0.0-unset"

// gitCommitID is a private field and should be set when compiling with --ldflags="-X k8s.io/minikube/pkg/drivers/hyperkit.gitCommitID=<commit-id>"
var gitCommitID = ""

// GetVersion returns the current docker-machine-driver-hyperkit version
func GetVersion() string {
return version
}

// GetGitCommitID returns the git commit id from which it is being built
func GetGitCommitID() string {
return gitCommitID
}
4 changes: 2 additions & 2 deletions pkg/hyperkit/vmnet.go
Original file line number Diff line number Diff line change
@@ -22,6 +22,6 @@ import (
vmnet "github.com/zchee/go-vmnet"
)

func GetMACAddressFromUUID(UUID string) (string, error) {
return vmnet.GetMACAddressFromUUID(UUID)
func GetMACAddressFromUUID(id string) (string, error) {
return vmnet.GetMACAddressFromUUID(id)
}