diff --git a/builder/vmware/common/driver.go b/builder/vmware/common/driver.go index d8180b520..35a358cc4 100644 --- a/builder/vmware/common/driver.go +++ b/builder/vmware/common/driver.go @@ -45,6 +45,9 @@ type Driver interface { // Get the path to the VMware ISO for the given flavor. ToolsIsoPath(string) string + // Attach the VMware tools ISO + ToolsInstall() error + // Get the path to the DHCP leases file for the given device. DhcpLeasesPath(string) string diff --git a/builder/vmware/common/driver_fusion5.go b/builder/vmware/common/driver_fusion5.go index 40b62ad5c..ee6cdd6c1 100644 --- a/builder/vmware/common/driver_fusion5.go +++ b/builder/vmware/common/driver_fusion5.go @@ -148,6 +148,10 @@ func (d *Fusion5Driver) ToolsIsoPath(k string) string { return filepath.Join(d.AppPath, "Contents", "Library", "isoimages", k+".iso") } +func (d *Fusion5Driver) ToolsInstall() error { + return nil +} + func (d *Fusion5Driver) DhcpLeasesPath(device string) string { return "/var/db/vmware/vmnet-dhcpd-" + device + ".leases" } diff --git a/builder/vmware/common/driver_mock.go b/builder/vmware/common/driver_mock.go index 2f5486bac..6aa0d02c0 100644 --- a/builder/vmware/common/driver_mock.go +++ b/builder/vmware/common/driver_mock.go @@ -51,6 +51,9 @@ type DriverMock struct { ToolsIsoPathFlavor string ToolsIsoPathResult string + ToolsInstallCalled bool + ToolsInstallErr error + DhcpLeasesPathCalled bool DhcpLeasesPathDevice string DhcpLeasesPathResult string @@ -120,6 +123,11 @@ func (d *DriverMock) ToolsIsoPath(flavor string) string { return d.ToolsIsoPathResult } +func (d *DriverMock) ToolsInstall() error { + d.ToolsInstallCalled = true + return d.ToolsInstallErr +} + func (d *DriverMock) DhcpLeasesPath(device string) string { d.DhcpLeasesPathCalled = true d.DhcpLeasesPathDevice = device diff --git a/builder/vmware/common/driver_player5.go b/builder/vmware/common/driver_player5.go index 1bec4ea25..96c92e1e3 100644 --- a/builder/vmware/common/driver_player5.go +++ b/builder/vmware/common/driver_player5.go @@ -187,6 +187,10 @@ func (d *Player5LinuxDriver) ToolsIsoPath(flavor string) string { return "/usr/lib/vmware/isoimages/" + flavor + ".iso" } +func (d *Player5LinuxDriver) ToolsInstall() error { + return nil +} + func (d *Player5LinuxDriver) DhcpLeasesPath(device string) string { return "/etc/vmware/" + device + "/dhcpd/dhcpd.leases" } diff --git a/builder/vmware/common/driver_workstation9.go b/builder/vmware/common/driver_workstation9.go index 76af4419b..f4dff9d30 100644 --- a/builder/vmware/common/driver_workstation9.go +++ b/builder/vmware/common/driver_workstation9.go @@ -149,6 +149,10 @@ func (d *Workstation9Driver) ToolsIsoPath(flavor string) string { return workstationToolsIsoPath(flavor) } +func (d *Workstation9Driver) ToolsInstall() error { + return nil +} + func (d *Workstation9Driver) DhcpLeasesPath(device string) string { return workstationDhcpLeasesPath(device) } diff --git a/builder/vmware/iso/driver_esx5.go b/builder/vmware/iso/driver_esx5.go index 5587a2a4a..df6863c74 100644 --- a/builder/vmware/iso/driver_esx5.go +++ b/builder/vmware/iso/driver_esx5.go @@ -31,6 +31,7 @@ type ESX5Driver struct { comm packer.Communicator outputDir string + vmId string } func (d *ESX5Driver) Clone(dst, src string) error { @@ -46,9 +47,8 @@ func (d *ESX5Driver) CreateDisk(diskPathLocal string, size string, typeId string return d.sh("vmkfstools", "-c", size, "-d", typeId, "-a", "lsilogic", diskPath) } -func (d *ESX5Driver) IsRunning(vmxPathLocal string) (bool, error) { - vmxPath := filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)) - state, err := d.run(nil, "vim-cmd", "vmsvc/power.getstate", vmxPath) +func (d *ESX5Driver) IsRunning(string) (bool, error) { + state, err := d.run(nil, "vim-cmd", "vmsvc/power.getstate", d.vmId) if err != nil { return false, err } @@ -56,13 +56,11 @@ func (d *ESX5Driver) IsRunning(vmxPathLocal string) (bool, error) { } func (d *ESX5Driver) Start(vmxPathLocal string, headless bool) error { - vmxPath := filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)) - return d.sh("vim-cmd", "vmsvc/power.on", vmxPath) + return d.sh("vim-cmd", "vmsvc/power.on", d.vmId) } func (d *ESX5Driver) Stop(vmxPathLocal string) error { - vmxPath := filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)) - return d.sh("vim-cmd", "vmsvc/power.off", vmxPath) + return d.sh("vim-cmd", "vmsvc/power.off", d.vmId) } func (d *ESX5Driver) Register(vmxPathLocal string) error { @@ -70,7 +68,12 @@ func (d *ESX5Driver) Register(vmxPathLocal string) error { if err := d.upload(vmxPath, vmxPathLocal); err != nil { return err } - return d.sh("vim-cmd", "solo/registervm", vmxPath) + r, err := d.run(nil, "vim-cmd", "solo/registervm", vmxPath) + if err != nil { + return err + } + d.vmId = strings.TrimRight(r, "\n") + return nil } func (d *ESX5Driver) SuppressMessages(vmxPath string) error { @@ -78,8 +81,7 @@ func (d *ESX5Driver) SuppressMessages(vmxPath string) error { } func (d *ESX5Driver) Unregister(vmxPathLocal string) error { - vmxPath := filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)) - return d.sh("vim-cmd", "vmsvc/unregister", vmxPath) + return d.sh("vim-cmd", "vmsvc/unregister", d.vmId) } func (d *ESX5Driver) UploadISO(localPath string) (string, error) { @@ -105,6 +107,10 @@ func (d *ESX5Driver) ToolsIsoPath(string) string { return "" } +func (d *ESX5Driver) ToolsInstall() error { + return d.sh("vim-cmd", "vmsvc/tools.install", d.vmId) +} + func (d *ESX5Driver) DhcpLeasesPath(string) string { return "" } @@ -168,35 +174,18 @@ func (d *ESX5Driver) SSHAddress(state multistep.StateBag) (string, error) { return address.(string), nil } - r, err := d.esxcli("network", "vm", "list") - if err != nil { - return "", err - } - - record, err := r.find("Name", config.VMName) + r, err := d.run(nil, "vim-cmd", "vmsvc/get.guest", d.vmId, " | grep -m 1 ipAddress | awk -F'\"' '{print $2}'") if err != nil { return "", err } - wid := record["WorldID"] - if wid == "" { - return "", errors.New("VM WorldID not found") - } - r, err = d.esxcli("network", "vm", "port", "list", "-w", wid) - if err != nil { - return "", err - } - - record, err = r.read() - if err != nil { - return "", err - } + ipAddress := strings.TrimRight(r, "\n") - if record["IPAddress"] == "0.0.0.0" { + if ipAddress == "" { return "", errors.New("VM network port found, but no IP address") } - address := fmt.Sprintf("%s:%d", record["IPAddress"], config.SSHPort) + address := fmt.Sprintf("%s:%d", ipAddress, config.SSHPort) state.Put("vm_address", address) return address, nil } diff --git a/builder/vmware/iso/step_prepare_tools.go b/builder/vmware/iso/step_prepare_tools.go index 69ff81690..d9ad4acce 100644 --- a/builder/vmware/iso/step_prepare_tools.go +++ b/builder/vmware/iso/step_prepare_tools.go @@ -13,6 +13,10 @@ func (*stepPrepareTools) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) driver := state.Get("driver").(vmwcommon.Driver) + if config.RemoteType == "esx5" { + return multistep.ActionContinue + } + if config.ToolsUploadFlavor == "" { return multistep.ActionContinue } diff --git a/builder/vmware/iso/step_upload_tools.go b/builder/vmware/iso/step_upload_tools.go index 359430bb9..9784a1cc6 100644 --- a/builder/vmware/iso/step_upload_tools.go +++ b/builder/vmware/iso/step_upload_tools.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/mitchellh/multistep" "github.com/mitchellh/packer/packer" + vmwcommon "github.com/mitchellh/packer/builder/vmware/common" "os" ) @@ -15,6 +16,15 @@ type stepUploadTools struct{} func (*stepUploadTools) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) + driver := state.Get("driver").(vmwcommon.Driver) + + if config.RemoteType == "esx5" { + if err := driver.ToolsInstall(); err != nil { + state.Put("error", fmt.Errorf("Couldn't mount VMware tools ISO.")) + } + return multistep.ActionContinue + } + if config.ToolsUploadFlavor == "" { return multistep.ActionContinue }