From 233e4075dbe62e9953d25607f6831db0c626926c Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Tue, 30 Sep 2014 23:14:06 -0700 Subject: [PATCH 1/3] Add Fusion driver and vmx template --- cmds.go | 1 + vmware/machine.go | 234 ++++++++++++++++++++++++++++++++++++++++++++++ vmware/vmrun.go | 30 ++++++ vmware/vmx.go | 43 +++++++++ 4 files changed, 308 insertions(+) create mode 100644 vmware/machine.go create mode 100644 vmware/vmrun.go create mode 100644 vmware/vmx.go diff --git a/cmds.go b/cmds.go index c13312b..5fc0812 100644 --- a/cmds.go +++ b/cmds.go @@ -12,6 +12,7 @@ import ( _ "github.com/boot2docker/boot2docker-cli/dummy" _ "github.com/boot2docker/boot2docker-cli/virtualbox" + _ "github.com/boot2docker/boot2docker-cli/vmware" "github.com/boot2docker/boot2docker-cli/driver" ) diff --git a/vmware/machine.go b/vmware/machine.go new file mode 100644 index 0000000..adff36c --- /dev/null +++ b/vmware/machine.go @@ -0,0 +1,234 @@ +package vmware + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "text/template" + + "github.com/boot2docker/boot2docker-cli/driver" + "github.com/ogier/pflag" +) + +var ( + verbose bool // Verbose mode (Local copy of B2D.Verbose). + cfg DriverCfg +) + +type DriverCfg struct { + VMRUN string // Path to VBoxManage utility. + VMDK string // base VMDK to use as persistent disk. +} + +func init() { + if err := driver.Register("fusion", InitFunc); err != nil { + fmt.Fprintf(os.Stderr, "Failed to initialize driver. Error : %s", err.Error()) + os.Exit(1) + } + if err := driver.RegisterConfig("fusion", ConfigFlags); err != nil { + fmt.Fprintf(os.Stderr, "Failed to initialize driver config. Error : %s", err.Error()) + os.Exit(1) + } +} + +// Initialize the Machine. +func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { + verbose = mc.Verbose + + m, err := GetMachine(getVMX(mc)) + if err != nil && mc.Init == true { + return CreateMachine(mc) + } + return m, err +} + +// Add cmdline params for this driver +func ConfigFlags(mc *driver.MachineConfig, flags *pflag.FlagSet) error { + cfg.VMRUN = "/Applications/VMware Fusion.app/Contents/Library/vmrun" + flags.StringVar(&cfg.VMRUN, "vmrun", cfg.VMRUN, "path to vmrun management utility.") + + return nil +} + +// Machine information. +type Machine struct { + Name string + State driver.MachineState + CPUs uint + Memory uint // main memory (in MB) + VRAM uint // video memory (in MB) + VMX string + OSType string + BootOrder []string // max 4 slots, each in {none|floppy|dvd|disk|net} + DockerPort uint + SSHPort uint +} + +// Refresh reloads the machine information. +func (m *Machine) Refresh() error { + mm, err := GetMachine(m.Name) + mm.State = driver.Running + if err != nil { + return err + } + *m = *mm + return nil +} + +// Start starts the machine. +func (m *Machine) Start() error { + m.State = driver.Running + vmrun("start", m.VMX, "nogui") + return nil +} + +// Suspend suspends the machine and saves its state to disk. +func (m *Machine) Save() error { + m.State = driver.Saved + fmt.Printf("Save %s: %s\n", m.Name, m.State) + return nil +} + +// Pause pauses the execution of the machine. +func (m *Machine) Pause() error { + m.State = driver.Paused + fmt.Printf("Pause %s: %s\n", m.Name, m.State) + return nil +} + +// Stop gracefully stops the machine. +func (m *Machine) Stop() error { + m.State = driver.Poweroff + vmrun("stop", m.VMX, "nogui") + return nil +} + +// Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. +func (m *Machine) Poweroff() error { + m.State = driver.Poweroff + fmt.Printf("Poweroff %s: %s\n", m.Name, m.State) + return nil +} + +// Restart gracefully restarts the machine. +func (m *Machine) Restart() error { + m.State = driver.Running + fmt.Printf("Restart %s: %s\n", m.Name, m.State) + return nil +} + +// Reset forcefully restarts the machine. State is lost and might corrupt the disk image. +func (m *Machine) Reset() error { + m.State = driver.Running + fmt.Printf("Reset %s: %s\n", m.Name, m.State) + return nil +} + +// Get vm name +func (m *Machine) GetName() string { + return m.Name +} + +// Get current state +func (m *Machine) GetState() driver.MachineState { + return m.State +} + +// Get serial file +func (m *Machine) GetSerialFile() string { + return "" +} + +// Get Docker port +func (m *Machine) GetDockerPort() uint { + return m.DockerPort +} + +// Get SSH port +func (m *Machine) GetSSHPort() uint { + return m.SSHPort +} + +// Delete deletes the machine and associated disk images. +func (m *Machine) Delete() error { + fmt.Printf("Delete %s: %s\n", m.Name, m.State) + return nil +} + +// Modify changes the settings of the machine. +func (m *Machine) Modify() error { + fmt.Printf("Modify %s: %s\n", m.Name, m.State) + return m.Refresh() +} + +// AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name. +func (m *Machine) AddNATPF(n int, name string, rule driver.PFRule) error { + fmt.Println("Add NAT PF") + return nil +} + +// DelNATPF deletes the NAT port forwarding rule with the given name from the n-th NIC. +func (m *Machine) DelNATPF(n int, name string) error { + fmt.Println("Del NAT PF") + return nil +} + +// SetNIC set the n-th NIC. +func (m *Machine) SetNIC(n int, nic driver.NIC) error { + fmt.Println("Set NIC") + return nil +} + +// AddStorageCtl adds a storage controller with the given name. +func (m *Machine) AddStorageCtl(name string, ctl driver.StorageController) error { + fmt.Println("Add storage ctl") + return nil +} + +// DelStorageCtl deletes the storage controller with the given name. +func (m *Machine) DelStorageCtl(name string) error { + fmt.Println("Del storage ctl") + return nil +} + +// AttachStorage attaches a storage medium to the named storage controller. +func (m *Machine) AttachStorage(ctlName string, medium driver.StorageMedium) error { + fmt.Println("Attach storage") + return nil +} + +// GetMachine finds a machine. +func GetMachine(vmx string) (*Machine, error) { + if _, err := os.Stat(vmx); os.IsNotExist(err) { + return nil, ErrMachineNotExist + } + m := &Machine{VMX: vmx} + return m, nil +} + +// CreateMachine creates a new virtual machine. +func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { + if err := os.MkdirAll(getBaseFolder(mc), 0755); err != nil { + return nil, err + } + + if _, err := os.Stat(getVMX(mc)); err == nil { + return nil, ErrMachineExist + } + + vmxt := template.Must(template.New("vmx").Parse(vmx)) + vmxfile, err := os.Create(getVMX(mc)) + if err != nil { + return nil, err + } + vmxt.Execute(vmxfile, mc) + return nil, nil +} + +func getBaseFolder(mc *driver.MachineConfig) string { + return filepath.Join(mc.Dir, mc.VM) +} +func getVMX(mc *driver.MachineConfig) string { + return filepath.Join(getBaseFolder(mc), strings.Join([]string{mc.VM, "vmx"}, ".")) +} diff --git a/vmware/vmrun.go b/vmware/vmrun.go new file mode 100644 index 0000000..5742cc8 --- /dev/null +++ b/vmware/vmrun.go @@ -0,0 +1,30 @@ +package vmware + +import ( + "errors" + "log" + "os" + "os/exec" + "strings" +) + +var ( + ErrMachineExist = errors.New("machine already exists") + ErrMachineNotExist = errors.New("machine does not exist") + ErrVMRUNNotFound = errors.New("VMRUN not found") +) + +func vmrun(args ...string) error { + cmd := exec.Command(cfg.VMRUN, args...) + if verbose { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Printf("executing: %v %v", cfg.VMRUN, strings.Join(args, " ")) + } + if stdout := cmd.Run(); stdout != nil { + if ee, ok := stdout.(*exec.Error); ok && ee == exec.ErrNotFound { + return ErrVMRUNNotFound + } + } + return nil +} diff --git a/vmware/vmx.go b/vmware/vmx.go new file mode 100644 index 0000000..37ffcb1 --- /dev/null +++ b/vmware/vmx.go @@ -0,0 +1,43 @@ +package vmware + +const vmx = ` +.encoding = "UTF-8" +bios.bootOrder = "CDROM" +config.version = "8" +displayName = "{{.VM}}" +ethernet0.addressType = "static" +ethernet0.connectionType = "nat" +ethernet0.address = "00:0c:29:2c:fe:e5" +ethernet0.linkStatePropagation.enable = "FALSE" +ethernet0.pciSlotNumber = "33" +ethernet0.present = "TRUE" +ethernet0.virtualDev = "e1000" +ethernet0.wakeOnPcktRcv = "FALSE" +ethernet1.addressType = "static" +ethernet1.connectionType = "hostonly" +ethernet1.address = "00:0c:29:2c:fe:ef" +ethernet1.pciSlotNumber = "34" +ethernet1.present = "TRUE" +ethernet1.virtualDev = "e1000" +ethernet1.wakeOnPcktRcv = "FALSE" +floppy0.present = "FALSE" +guestOS = "other26xlinux-64" +hpet0.present = "TRUE" +ide1:0.deviceType = "cdrom-image" +ide1:0.fileName = "{{.ISO}}" +ide1:0.present = "TRUE" +mem.hotadd = "TRUE" +memsize = "1024" +powerType.powerOff = "soft" +powerType.powerOn = "soft" +powerType.reset = "soft" +powerType.suspend = "soft" +sata0.present = "TRUE" +sata0:0.fileName = "{{.VMDK}}" +sata0:0.present = "TRUE" +scsi0.pciSlotNumber = "16" +scsi0.present = "FALSE" +scsi0.virtualDev = "lsilogic" +scsi0:0.present = "FALSE" +virtualHW.version = "10" +` From 1dfab34b9835add0b445183dc4ef9fd1751c2c55 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Thu, 2 Oct 2014 15:43:56 -0700 Subject: [PATCH 2/3] Add vmdk diskman; first successful Fusion boot --- vmware/machine.go | 30 +++++++++++++++++++++++------- vmware/vmrun.go | 13 +++++++++++++ vmware/vmx.go | 26 +++++++------------------- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/vmware/machine.go b/vmware/machine.go index adff36c..3095fb7 100644 --- a/vmware/machine.go +++ b/vmware/machine.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "path/filepath" - "strings" "text/template" "github.com/boot2docker/boot2docker-cli/driver" @@ -12,13 +11,13 @@ import ( ) var ( - verbose bool // Verbose mode (Local copy of B2D.Verbose). + verbose bool // Verbose mode. cfg DriverCfg ) type DriverCfg struct { - VMRUN string // Path to VBoxManage utility. - VMDK string // base VMDK to use as persistent disk. + VMRUN string // Path to vmrun utility. + VDISKMAN string // Path to vdiskmanager utility. } func init() { @@ -46,7 +45,10 @@ func InitFunc(mc *driver.MachineConfig) (driver.Machine, error) { // Add cmdline params for this driver func ConfigFlags(mc *driver.MachineConfig, flags *pflag.FlagSet) error { cfg.VMRUN = "/Applications/VMware Fusion.app/Contents/Library/vmrun" - flags.StringVar(&cfg.VMRUN, "vmrun", cfg.VMRUN, "path to vmrun management utility.") + flags.StringVar(&cfg.VMRUN, "vmrun", cfg.VMRUN, "path to vmrun utility.") + + cfg.VDISKMAN = "/Applications/VMware Fusion.app/Contents/Library/vmware-vdiskmanager" + flags.StringVar(&cfg.VDISKMAN, "vmdiskman", cfg.VDISKMAN, "path to vdiskmanager utility.") return nil } @@ -67,7 +69,7 @@ type Machine struct { // Refresh reloads the machine information. func (m *Machine) Refresh() error { - mm, err := GetMachine(m.Name) + mm, err := GetMachine(m.VMX) mm.State = driver.Running if err != nil { return err @@ -217,12 +219,26 @@ func CreateMachine(mc *driver.MachineConfig) (*Machine, error) { return nil, ErrMachineExist } + // Generate vmx config file from template vmxt := template.Must(template.New("vmx").Parse(vmx)) vmxfile, err := os.Create(getVMX(mc)) if err != nil { return nil, err } vmxt.Execute(vmxfile, mc) + + // Generate vmdk file + diskImg := filepath.Join(getBaseFolder(mc), fmt.Sprintf("%s.vmdk", mc.VM)) + if _, err := os.Stat(diskImg); err != nil { + if !os.IsNotExist(err) { + return nil, err + } + + if err := vdiskmanager(diskImg, mc.DiskSize); err != nil { + return nil, err + } + } + return nil, nil } @@ -230,5 +246,5 @@ func getBaseFolder(mc *driver.MachineConfig) string { return filepath.Join(mc.Dir, mc.VM) } func getVMX(mc *driver.MachineConfig) string { - return filepath.Join(getBaseFolder(mc), strings.Join([]string{mc.VM, "vmx"}, ".")) + return filepath.Join(getBaseFolder(mc), fmt.Sprintf("%s.vmx", mc.VM)) } diff --git a/vmware/vmrun.go b/vmware/vmrun.go index 5742cc8..dc0fe27 100644 --- a/vmware/vmrun.go +++ b/vmware/vmrun.go @@ -2,6 +2,7 @@ package vmware import ( "errors" + "fmt" "log" "os" "os/exec" @@ -28,3 +29,15 @@ func vmrun(args ...string) error { } return nil } + +// Make a vmdk disk image with the given size (in MB). +func vdiskmanager(dest string, size uint) error { + cmd := exec.Command(cfg.VDISKMAN, "-c", "-t", "0", "-s", fmt.Sprintf("%dMB", size), "-a", "lsilogic", dest) + + if stdout := cmd.Run(); stdout != nil { + if ee, ok := stdout.(*exec.Error); ok && ee == exec.ErrNotFound { + return ErrVMRUNNotFound + } + } + return nil +} diff --git a/vmware/vmx.go b/vmware/vmx.go index 37ffcb1..7b64523 100644 --- a/vmware/vmx.go +++ b/vmware/vmx.go @@ -2,24 +2,14 @@ package vmware const vmx = ` .encoding = "UTF-8" -bios.bootOrder = "CDROM" config.version = "8" displayName = "{{.VM}}" -ethernet0.addressType = "static" +ethernet0.addressType = "generated" ethernet0.connectionType = "nat" -ethernet0.address = "00:0c:29:2c:fe:e5" -ethernet0.linkStatePropagation.enable = "FALSE" -ethernet0.pciSlotNumber = "33" +ethernet0.linkStatePropagation.enable = "TRUE" ethernet0.present = "TRUE" ethernet0.virtualDev = "e1000" ethernet0.wakeOnPcktRcv = "FALSE" -ethernet1.addressType = "static" -ethernet1.connectionType = "hostonly" -ethernet1.address = "00:0c:29:2c:fe:ef" -ethernet1.pciSlotNumber = "34" -ethernet1.present = "TRUE" -ethernet1.virtualDev = "e1000" -ethernet1.wakeOnPcktRcv = "FALSE" floppy0.present = "FALSE" guestOS = "other26xlinux-64" hpet0.present = "TRUE" @@ -27,17 +17,15 @@ ide1:0.deviceType = "cdrom-image" ide1:0.fileName = "{{.ISO}}" ide1:0.present = "TRUE" mem.hotadd = "TRUE" -memsize = "1024" +memsize = "{{.Memory}}" powerType.powerOff = "soft" powerType.powerOn = "soft" powerType.reset = "soft" powerType.suspend = "soft" -sata0.present = "TRUE" -sata0:0.fileName = "{{.VMDK}}" -sata0:0.present = "TRUE" -scsi0.pciSlotNumber = "16" -scsi0.present = "FALSE" +scsi0.present = "TRUE" scsi0.virtualDev = "lsilogic" -scsi0:0.present = "FALSE" +scsi0:0.fileName = "{{.VM}}.vmdk" +scsi0:0.present = "TRUE" +virtualHW.productCompatibility = "hosted" virtualHW.version = "10" ` From 7fb5cbd78db12b164a5f47c4e1838b11d8c23f22 Mon Sep 17 00:00:00 2001 From: Zee Yang Date: Wed, 8 Oct 2014 16:51:32 -0700 Subject: [PATCH 3/3] Add vm control commands and get hostname --- cmds.go | 2 +- driver/driver.go | 1 + dummy/machine.go | 8 +++- {vmware => fusion}/machine.go | 86 +++++++++++++++++++++++------------ {vmware => fusion}/vmrun.go | 23 ++++++---- {vmware => fusion}/vmx.go | 2 +- util.go | 3 +- virtualbox/machine.go | 5 ++ 8 files changed, 87 insertions(+), 43 deletions(-) rename {vmware => fusion}/machine.go (78%) rename {vmware => fusion}/vmrun.go (68%) rename {vmware => fusion}/vmx.go (98%) diff --git a/cmds.go b/cmds.go index 5fc0812..510b9d5 100644 --- a/cmds.go +++ b/cmds.go @@ -11,8 +11,8 @@ import ( "time" _ "github.com/boot2docker/boot2docker-cli/dummy" + _ "github.com/boot2docker/boot2docker-cli/fusion" _ "github.com/boot2docker/boot2docker-cli/virtualbox" - _ "github.com/boot2docker/boot2docker-cli/vmware" "github.com/boot2docker/boot2docker-cli/driver" ) diff --git a/driver/driver.go b/driver/driver.go index 9b5524a..b27d140 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -42,6 +42,7 @@ type Machine interface { AttachStorage(ctlName string, medium StorageMedium) error GetState() MachineState GetName() string + GetHostname() string GetSerialFile() string GetDockerPort() uint GetSSHPort() uint diff --git a/dummy/machine.go b/dummy/machine.go index cfc3f1d..ce34b35 100644 --- a/dummy/machine.go +++ b/dummy/machine.go @@ -47,8 +47,9 @@ func ConfigFlags(B2D *driver.MachineConfig, flags *flag.FlagSet) error { // Machine information. type Machine struct { - Name string UUID string + Name string + Hostname string State driver.MachineState CPUs uint Memory uint // main memory (in MB) @@ -122,6 +123,11 @@ func (m *Machine) GetName() string { return m.Name } +// Get machine hostname +func (m *Machine) GetHostname() string { + return m.Hostname +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State diff --git a/vmware/machine.go b/fusion/machine.go similarity index 78% rename from vmware/machine.go rename to fusion/machine.go index 3095fb7..69e3257 100644 --- a/vmware/machine.go +++ b/fusion/machine.go @@ -1,9 +1,12 @@ -package vmware +package fusion import ( + "bufio" "fmt" "os" "path/filepath" + "strconv" + "strings" "text/template" "github.com/boot2docker/boot2docker-cli/driver" @@ -55,22 +58,17 @@ func ConfigFlags(mc *driver.MachineConfig, flags *pflag.FlagSet) error { // Machine information. type Machine struct { - Name string - State driver.MachineState - CPUs uint - Memory uint // main memory (in MB) - VRAM uint // video memory (in MB) - VMX string - OSType string - BootOrder []string // max 4 slots, each in {none|floppy|dvd|disk|net} - DockerPort uint - SSHPort uint + Name string + State driver.MachineState + CPUs uint64 + Memory uint64 // main memory (in MB) + VMX string + OSType string } // Refresh reloads the machine information. func (m *Machine) Refresh() error { mm, err := GetMachine(m.VMX) - mm.State = driver.Running if err != nil { return err } @@ -80,50 +78,43 @@ func (m *Machine) Refresh() error { // Start starts the machine. func (m *Machine) Start() error { - m.State = driver.Running vmrun("start", m.VMX, "nogui") return nil } // Suspend suspends the machine and saves its state to disk. func (m *Machine) Save() error { - m.State = driver.Saved - fmt.Printf("Save %s: %s\n", m.Name, m.State) + vmrun("suspend", m.VMX, "nogui") return nil } // Pause pauses the execution of the machine. func (m *Machine) Pause() error { - m.State = driver.Paused - fmt.Printf("Pause %s: %s\n", m.Name, m.State) + vmrun("pause", m.VMX, "nogui") return nil } // Stop gracefully stops the machine. func (m *Machine) Stop() error { - m.State = driver.Poweroff vmrun("stop", m.VMX, "nogui") return nil } // Poweroff forcefully stops the machine. State is lost and might corrupt the disk image. func (m *Machine) Poweroff() error { - m.State = driver.Poweroff - fmt.Printf("Poweroff %s: %s\n", m.Name, m.State) + vmrun("stop", m.VMX, "nogui") return nil } // Restart gracefully restarts the machine. func (m *Machine) Restart() error { - m.State = driver.Running - fmt.Printf("Restart %s: %s\n", m.Name, m.State) + vmrun("reset", m.VMX, "nogui") return nil } // Reset forcefully restarts the machine. State is lost and might corrupt the disk image. func (m *Machine) Reset() error { - m.State = driver.Running - fmt.Printf("Reset %s: %s\n", m.Name, m.State) + vmrun("reset", m.VMX, "nogui") return nil } @@ -132,6 +123,12 @@ func (m *Machine) GetName() string { return m.Name } +// Get vm hostname +func (m *Machine) GetHostname() string { + stdout, _, _ := vmrun("getGuestIPAddress", m.VMX) + return strings.TrimSpace(stdout) +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State @@ -144,23 +141,23 @@ func (m *Machine) GetSerialFile() string { // Get Docker port func (m *Machine) GetDockerPort() uint { - return m.DockerPort + return 2375 } // Get SSH port func (m *Machine) GetSSHPort() uint { - return m.SSHPort + return 22 } // Delete deletes the machine and associated disk images. func (m *Machine) Delete() error { - fmt.Printf("Delete %s: %s\n", m.Name, m.State) + vmrun("deleteVM", m.VMX, "nogui") return nil } // Modify changes the settings of the machine. func (m *Machine) Modify() error { - fmt.Printf("Modify %s: %s\n", m.Name, m.State) + fmt.Printf("Hot modify not supported") return m.Refresh() } @@ -205,7 +202,38 @@ func GetMachine(vmx string) (*Machine, error) { if _, err := os.Stat(vmx); os.IsNotExist(err) { return nil, ErrMachineNotExist } - m := &Machine{VMX: vmx} + + m := &Machine{VMX: vmx, State: driver.Poweroff} + + // VMRUN only tells use if the vm is running or not + if stdout, _, _ := vmrun("list"); strings.Contains(stdout, m.VMX) { + m.State = driver.Running + } + + // Parse the vmx file + vmxfile, err := os.Open(vmx) + if err != nil { + return m, err + } + defer vmxfile.Close() + + vmxscan := bufio.NewScanner(vmxfile) + for vmxscan.Scan() { + if vmxtokens := strings.Split(vmxscan.Text(), " = "); len(vmxtokens) > 1 { + vmxkey := strings.TrimSpace(vmxtokens[0]) + vmxvalue, _ := strconv.Unquote(vmxtokens[1]) + switch vmxkey { + case "displayName": + m.Name = vmxvalue + case "guestOS": + m.OSType = vmxvalue + case "memsize": + m.Memory, _ = strconv.ParseUint(vmxvalue, 10, 0) + case "numvcpus": + m.CPUs, _ = strconv.ParseUint(vmxvalue, 10, 0) + } + } + } return m, nil } diff --git a/vmware/vmrun.go b/fusion/vmrun.go similarity index 68% rename from vmware/vmrun.go rename to fusion/vmrun.go index dc0fe27..ba36419 100644 --- a/vmware/vmrun.go +++ b/fusion/vmrun.go @@ -1,10 +1,10 @@ -package vmware +package fusion import ( + "bytes" "errors" "fmt" "log" - "os" "os/exec" "strings" ) @@ -15,19 +15,24 @@ var ( ErrVMRUNNotFound = errors.New("VMRUN not found") ) -func vmrun(args ...string) error { +func vmrun(args ...string) (string, string, error) { cmd := exec.Command(cfg.VMRUN, args...) if verbose { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr log.Printf("executing: %v %v", cfg.VMRUN, strings.Join(args, " ")) } - if stdout := cmd.Run(); stdout != nil { - if ee, ok := stdout.(*exec.Error); ok && ee == exec.ErrNotFound { - return ErrVMRUNNotFound + + var stdout bytes.Buffer + var stderr bytes.Buffer + cmd.Stdout, cmd.Stderr = &stdout, &stderr + + err := cmd.Run() + if err != nil { + if ee, ok := err.(*exec.Error); ok && ee == exec.ErrNotFound { + err = ErrVMRUNNotFound } } - return nil + + return stdout.String(), stderr.String(), err } // Make a vmdk disk image with the given size (in MB). diff --git a/vmware/vmx.go b/fusion/vmx.go similarity index 98% rename from vmware/vmx.go rename to fusion/vmx.go index 7b64523..2b467ba 100644 --- a/vmware/vmx.go +++ b/fusion/vmx.go @@ -1,4 +1,4 @@ -package vmware +package fusion const vmx = ` .encoding = "UTF-8" diff --git a/util.go b/util.go index fa072aa..7809835 100644 --- a/util.go +++ b/util.go @@ -168,7 +168,6 @@ func reader(r io.Reader) { } func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { - DefaultSSHArgs := []string{ "-o", "IdentitiesOnly=yes", "-o", "StrictHostKeyChecking=no", @@ -176,7 +175,7 @@ func getSSHCommand(m driver.Machine, args ...string) *exec.Cmd { "-o", "LogLevel=quiet", // suppress "Warning: Permanently added '[localhost]:2022' (ECDSA) to the list of known hosts." "-p", fmt.Sprintf("%d", m.GetSSHPort()), "-i", B2D.SSHKey, - "docker@localhost", + fmt.Sprintf("docker@%s", m.GetHostname()), } sshArgs := append(DefaultSSHArgs, args...) diff --git a/virtualbox/machine.go b/virtualbox/machine.go index 2009d01..6523073 100644 --- a/virtualbox/machine.go +++ b/virtualbox/machine.go @@ -305,6 +305,11 @@ func (m *Machine) GetName() string { return m.Name } +// Get machine hostname +func (m *Machine) GetHostname() string { + return "localhost" +} + // Get current state func (m *Machine) GetState() driver.MachineState { return m.State