From 7b5943160bb88e2bd87de1f0f9fe1049165ea9a0 Mon Sep 17 00:00:00 2001 From: Alexander Laamanen Date: Wed, 1 Feb 2017 13:32:02 +0200 Subject: [PATCH] Re-enable the CommHost() call. Use common's driver factory. --- builder/vmware/common/driver.go | 7 +- builder/vmware/common/driver_esx5.go | 133 +++++++++--------- .../vmware/common/step_type_boot_command.go | 1 + builder/vmware/iso/builder.go | 11 -- builder/vmware/iso/driver.go | 33 +---- builder/vmware/vmx/builder.go | 10 +- builder/vmware/vmx/config.go | 3 + 7 files changed, 79 insertions(+), 119 deletions(-) diff --git a/builder/vmware/common/driver.go b/builder/vmware/common/driver.go index e65e429b9..ed37ff207 100644 --- a/builder/vmware/common/driver.go +++ b/builder/vmware/common/driver.go @@ -15,6 +15,7 @@ import ( "strings" "time" + "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" ) @@ -81,11 +82,9 @@ type Driver interface { // NewDriver returns a new driver implementation for this operating // system, or an error if the driver couldn't be initialized. -func NewDriver(dconfig *DriverConfig, config *SSHConfig) (Driver, error) { +func NewDriver(dconfig *DriverConfig, config *SSHConfig, commConfig *communicator.Config, vmName string) (Driver, error) { drivers := []Driver{} - log.Printf("**** NewDriver()") if dconfig.RemoteType != "" { - log.Printf("**** Creating the remote driver.") drivers = []Driver{ &ESX5Driver{ Host: dconfig.RemoteHost, @@ -96,6 +95,8 @@ func NewDriver(dconfig *DriverConfig, config *SSHConfig) (Driver, error) { Datastore: dconfig.RemoteDatastore, CacheDatastore: dconfig.RemoteCacheDatastore, CacheDirectory: dconfig.RemoteCacheDirectory, + VMName: vmName, + CommConfig: *commConfig, }, } diff --git a/builder/vmware/common/driver_esx5.go b/builder/vmware/common/driver_esx5.go index 7519c586f..6c6b02c13 100644 --- a/builder/vmware/common/driver_esx5.go +++ b/builder/vmware/common/driver_esx5.go @@ -16,8 +16,8 @@ import ( "strings" "time" - vmwcommon "github.com/hashicorp/packer/builder/vmware/common" "github.com/hashicorp/packer/communicator/ssh" + "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/multistep" helperssh "github.com/hashicorp/packer/helper/ssh" "github.com/hashicorp/packer/packer" @@ -37,6 +37,8 @@ type ESX5Driver struct { Datastore string CacheDatastore string CacheDirectory string + VMName string + CommConfig communicator.Config comm packer.Communicator outputDir string @@ -56,9 +58,9 @@ func (d *ESX5Driver) Clone(dst, src string, linked bool) error { log.Printf("Source: %s\n", srcVmx) log.Printf("Dest: %s\n", dstVmx) - err := d.sh("mkdir", dstDir) + err := d.MkdirAll() if err != nil { - return fmt.Errorf("Failed to create the destination directory %s: %s", dstDir, err) + return fmt.Errorf("Failed to create the destination directory %s: %s", d.outputDir, err) } err = d.sh("cp", srcVmx, dstVmx) @@ -458,71 +460,66 @@ func (ESX5Driver) UpdateVMX(_, password string, port uint, data map[string]strin } func (d *ESX5Driver) CommHost(state multistep.StateBag) (string, error) { - // config := state.Get("config").(*Config) - // sshc := config.SSHConfig.Comm - // port := sshc.SSHPort - // if sshc.Type == "winrm" { - // port = sshc.WinRMPort - // } - // - // if address, ok := state.GetOk("vm_address"); ok { - // return address.(string), nil - // } - // - // if address := config.CommConfig.Host(); address != "" { - // state.Put("vm_address", address) - // return address, nil - // } - // - // r, err := d.esxcli("network", "vm", "list") - // if err != nil { - // return "", err - // } - // - // record, err := r.find("Name", config.VMName) - // 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 - // } - // - // // Loop through interfaces - // for { - // record, err = r.read() - // if err == io.EOF { - // break - // } - // if err != nil { - // return "", err - // } - // - // if record["IPAddress"] == "0.0.0.0" { - // continue - // } - // // When multiple NICs are connected to the same network, choose - // // one that has a route back. This Dial should ensure that. - // conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", record["IPAddress"], port), 2*time.Second) - // if err != nil { - // if e, ok := err.(*net.OpError); ok { - // if e.Timeout() { - // log.Printf("Timeout connecting to %s", record["IPAddress"]) - // continue - // } - // } - // } else { - // defer conn.Close() - // address := record["IPAddress"] - // state.Put("vm_address", address) - // return address, nil - // } - // } + port := d.CommConfig.Port() + + if address, ok := state.GetOk("vm_address"); ok { + return address.(string), nil + } + + if address := d.CommConfig.Host(); address != "" { + state.Put("vm_address", address) + return address, nil + } + + r, err := d.esxcli("network", "vm", "list") + if err != nil { + return "", err + } + + record, err := r.find("Name", d.VMName) + 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 + } + + // Loop through interfaces + for { + record, err = r.read() + if err == io.EOF { + break + } + if err != nil { + return "", err + } + + if record["IPAddress"] == "0.0.0.0" { + continue + } + // When multiple NICs are connected to the same network, choose + // one that has a route back. This Dial should ensure that. + conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", record["IPAddress"], port), 2*time.Second) + if err != nil { + if e, ok := err.(*net.OpError); ok { + if e.Timeout() { + log.Printf("Timeout connecting to %s", record["IPAddress"]) + continue + } + } + } else { + defer conn.Close() + address := record["IPAddress"] + state.Put("vm_address", address) + return address, nil + } + } return "", errors.New("No interface on the VM has an IP address ready") } diff --git a/builder/vmware/common/step_type_boot_command.go b/builder/vmware/common/step_type_boot_command.go index ac33fd24c..b241d57ba 100644 --- a/builder/vmware/common/step_type_boot_command.go +++ b/builder/vmware/common/step_type_boot_command.go @@ -70,6 +70,7 @@ func (s *StepTypeBootCommand) Run(ctx context.Context, state multistep.StateBag) // Connect to VNC ui.Say(fmt.Sprintf("Connecting to VM via VNC (%s:%d)", vncIp, vncPort)) + nc, err := net.Dial("tcp", fmt.Sprintf("%s:%d", vncIp, vncPort)) if err != nil { err := fmt.Errorf("Error connecting to VNC: %s", err) diff --git a/builder/vmware/iso/builder.go b/builder/vmware/iso/builder.go index 8f175560d..751799d42 100644 --- a/builder/vmware/iso/builder.go +++ b/builder/vmware/iso/builder.go @@ -76,17 +76,6 @@ type Config struct { VMXDiskTemplatePath string `mapstructure:"vmx_disk_template_path"` VMXTemplatePath string `mapstructure:"vmx_template_path"` - // remote vsphere - RemoteType string `mapstructure:"remote_type"` - RemoteDatastore string `mapstructure:"remote_datastore"` - RemoteCacheDatastore string `mapstructure:"remote_cache_datastore"` - RemoteCacheDirectory string `mapstructure:"remote_cache_directory"` - RemoteHost string `mapstructure:"remote_host"` - RemotePort uint `mapstructure:"remote_port"` - RemoteUser string `mapstructure:"remote_username"` - RemotePassword string `mapstructure:"remote_password"` - RemotePrivateKey string `mapstructure:"remote_private_key_file"` - CommConfig communicator.Config `mapstructure:",squash"` ctx interpolate.Context diff --git a/builder/vmware/iso/driver.go b/builder/vmware/iso/driver.go index 6580c3108..947ff4c16 100644 --- a/builder/vmware/iso/driver.go +++ b/builder/vmware/iso/driver.go @@ -9,36 +9,5 @@ import ( // NewDriver returns a new driver implementation for this operating // system, or an error if the driver couldn't be initialized. func NewDriver(config *Config) (vmwcommon.Driver, error) { - drivers := []vmwcommon.Driver{} - - if config.RemoteType == "" { - return vmwcommon.NewDriver(&config.DriverConfig, &config.SSHConfig) - } - - drivers = []vmwcommon.Driver{ - &vmwcommon.ESX5Driver{ - Host: config.RemoteHost, - Port: config.RemotePort, - Username: config.RemoteUser, - Password: config.RemotePassword, - PrivateKeyFile: config.RemotePrivateKey, - Datastore: config.RemoteDatastore, - CacheDatastore: config.RemoteCacheDatastore, - CacheDirectory: config.RemoteCacheDirectory, - }, - } - - errs := "" - for _, driver := range drivers { - err := driver.Verify() - if err == nil { - return driver, nil - } - errs += "* " + err.Error() + "\n" - } - - return nil, fmt.Errorf( - "Unable to initialize any driver for this platform. The errors\n"+ - "from each driver are shown below. Please fix at least one driver\n"+ - "to continue:\n%s", errs) + return vmwcommon.NewDriver(&config.DriverConfig, &config.SSHConfig, &config.CommConfig, config.VMName) } diff --git a/builder/vmware/vmx/builder.go b/builder/vmware/vmx/builder.go index 64d89d887..35ef9068b 100644 --- a/builder/vmware/vmx/builder.go +++ b/builder/vmware/vmx/builder.go @@ -34,7 +34,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { // Run executes a Packer build and returns a packer.Artifact representing // a VMware image. func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { - driver, err := vmwcommon.NewDriver(&b.config.DriverConfig, &b.config.SSHConfig) + driver, err := vmwcommon.NewDriver(&b.config.DriverConfig, &b.config.SSHConfig, &b.config.CommConfig, b.config.VMName) if err != nil { return nil, fmt.Errorf("Failed creating VMware driver: %s", err) } @@ -83,10 +83,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &vmwcommon.StepUploadVMX{ RemoteType: b.config.RemoteType, }, - &vmwcommon.StepRegister{ - Format: "foo", - KeepRegistered: false, - }, &vmwcommon.StepConfigureVNC{ Enabled: !b.config.DisableVNC, VNCBindAddress: b.config.VNCBindAddress, @@ -94,6 +90,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe VNCPortMax: b.config.VNCPortMax, VNCDisablePassword: b.config.VNCDisablePassword, }, + &vmwcommon.StepRegister{ + Format: "foo", + KeepRegistered: false, + }, &vmwcommon.StepRun{ DurationBeforeStop: 5 * time.Second, Headless: b.config.Headless, diff --git a/builder/vmware/vmx/config.go b/builder/vmware/vmx/config.go index bd25dc92a..b5babbb4c 100644 --- a/builder/vmware/vmx/config.go +++ b/builder/vmware/vmx/config.go @@ -8,6 +8,7 @@ import ( vmwcommon "github.com/hashicorp/packer/builder/vmware/common" "github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common/bootcommand" + "github.com/hashicorp/packer/helper/communicator" "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/template/interpolate" @@ -33,6 +34,8 @@ type Config struct { SourcePath string `mapstructure:"source_path"` VMName string `mapstructure:"vm_name"` + CommConfig communicator.Config `mapstructure:",squash"` + ctx interpolate.Context }