diff --git a/builder/vmware/driver_esx5.go b/builder/vmware/driver_esx5.go index dcfde929b..44394913f 100644 --- a/builder/vmware/driver_esx5.go +++ b/builder/vmware/driver_esx5.go @@ -19,6 +19,8 @@ import ( "time" ) +// ESX5 driver talks to an ESXi5 hypervisor remotely over SSH to build +// virtual machines. This driver can only manage one machine at a time. type ESX5Driver struct { Host string Port uint @@ -26,7 +28,8 @@ type ESX5Driver struct { Password string Datastore string - comm packer.Communicator + comm packer.Communicator + outputDir string } func (d *ESX5Driver) CompactDisk(diskPathLocal string) error { @@ -56,7 +59,7 @@ func (d *ESX5Driver) Stop(vmxPathLocal string) error { } func (d *ESX5Driver) Register(vmxPathLocal string) error { - vmxPath := d.datastorePath(vmxPathLocal) + vmxPath := filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)) if err := d.upload(vmxPath, vmxPathLocal); err != nil { return err } @@ -64,7 +67,8 @@ func (d *ESX5Driver) Register(vmxPathLocal string) error { } func (d *ESX5Driver) Unregister(vmxPathLocal string) error { - return d.sh("vim-cmd", "vmsvc/unregister", d.datastorePath(vmxPathLocal)) + vmxPath := filepath.Join(d.outputDir, filepath.Base(vmxPathLocal)) + return d.sh("vim-cmd", "vmsvc/unregister", vmxPath) } func (d *ESX5Driver) UploadISO(localPath string) (string, error) { @@ -74,7 +78,7 @@ func (d *ESX5Driver) UploadISO(localPath string) (string, error) { return "", err } - if err := d.MkdirAll(filepath.Dir(targetFile)); err != nil { + if err := d.mkdir(filepath.Dir(targetFile)); err != nil { return "", err } @@ -199,17 +203,21 @@ func (d *ESX5Driver) SSHAddress(state multistep.StateBag) (string, error) { return address, nil } -func (d *ESX5Driver) DirExists(path string) (bool, error) { - err := d.sh("test", "-e", d.datastorePath(path)) +func (d *ESX5Driver) DirExists() (bool, error) { + err := d.sh("test", "-e", d.outputDir) return err == nil, nil } -func (d *ESX5Driver) MkdirAll(path string) error { - return d.sh("mkdir", "-p", d.datastorePath(path)) +func (d *ESX5Driver) MkdirAll() error { + return d.mkdir(d.outputDir) } -func (d *ESX5Driver) RemoveAll(path string) error { - return d.sh("rm", "-rf", d.datastorePath(path)) +func (d *ESX5Driver) RemoveAll() error { + return d.sh("rm", "-rf", d.outputDir) +} + +func (d *ESX5Driver) SetOutputDir(path string) { + d.outputDir = d.datastorePath(path) } func (d *ESX5Driver) datastorePath(path string) string { @@ -279,6 +287,10 @@ func (d *ESX5Driver) checkGuestIPHackEnabled() error { return nil } +func (d *ESX5Driver) mkdir(path string) error { + return d.sh("mkdir", "-p", path) +} + func (d *ESX5Driver) upload(dst, src string) error { f, err := os.Open(src) if err != nil { diff --git a/builder/vmware/output_dir.go b/builder/vmware/output_dir.go index 37dcaf6e8..14880499c 100644 --- a/builder/vmware/output_dir.go +++ b/builder/vmware/output_dir.go @@ -9,24 +9,31 @@ import ( // so that the output directory can be properly made on remote (ESXi) based // VMware products as well as local. type OutputDir interface { - DirExists(string) (bool, error) - MkdirAll(string) error - RemoveAll(string) error + DirExists() (bool, error) + MkdirAll() error + RemoveAll() error + SetOutputDir(string) } // localOutputDir is an OutputDir implementation where the directory // is on the local machine. -type localOutputDir struct{} +type localOutputDir struct { + dir string +} -func (localOutputDir) DirExists(path string) (bool, error) { - _, err := os.Stat(path) +func (d *localOutputDir) DirExists() (bool, error) { + _, err := os.Stat(d.dir) return err == nil, err } -func (localOutputDir) MkdirAll(path string) error { - return os.MkdirAll(path, 0755) +func (d *localOutputDir) MkdirAll() error { + return os.MkdirAll(d.dir, 0755) } -func (localOutputDir) RemoveAll(path string) error { - return os.RemoveAll(path) +func (d *localOutputDir) RemoveAll() error { + return os.RemoveAll(d.dir) +} + +func (d *localOutputDir) SetOutputDir(path string) { + d.dir = path } diff --git a/builder/vmware/step_prepare_output_dir.go b/builder/vmware/step_prepare_output_dir.go index 70fb7d197..dc5d9ecb8 100644 --- a/builder/vmware/step_prepare_output_dir.go +++ b/builder/vmware/step_prepare_output_dir.go @@ -7,14 +7,18 @@ import ( "time" ) -type stepPrepareOutputDir struct{} +type stepPrepareOutputDir struct { + dir OutputDir +} func (s *stepPrepareOutputDir) Run(state multistep.StateBag) multistep.StepAction { config := state.Get("config").(*config) ui := state.Get("ui").(packer.Ui) dir := s.outputDir(state) - exists, err := dir.DirExists(config.OutputDir) + dir.SetOutputDir(config.OutputDir) + + exists, err := dir.DirExists() if err != nil { state.Put("error", err) return multistep.ActionHalt @@ -22,14 +26,16 @@ func (s *stepPrepareOutputDir) Run(state multistep.StateBag) multistep.StepActio if exists && config.PackerForce { ui.Say("Deleting previous output directory...") - dir.RemoveAll(config.OutputDir) + dir.RemoveAll() } - if err := dir.MkdirAll(config.OutputDir); err != nil { + if err := dir.MkdirAll(); err != nil { state.Put("error", err) return multistep.ActionHalt } + s.dir = dir + return multistep.ActionContinue } @@ -38,19 +44,19 @@ func (s *stepPrepareOutputDir) Cleanup(state multistep.StateBag) { _, halted := state.GetOk(multistep.StateHalted) if cancelled || halted { - config := state.Get("config").(*config) ui := state.Get("ui").(packer.Ui) - dir := s.outputDir(state) - ui.Say("Deleting output directory...") - for i := 0; i < 5; i++ { - err := dir.RemoveAll(config.OutputDir) - if err == nil { - break - } + if s.dir != nil { + ui.Say("Deleting output directory...") + for i := 0; i < 5; i++ { + err := s.dir.RemoveAll() + if err == nil { + break + } - log.Printf("Error removing output dir: %s", err) - time.Sleep(2 * time.Second) + log.Printf("Error removing output dir: %s", err) + time.Sleep(2 * time.Second) + } } } }