diff --git a/builder/vsphere/common/step_remote_upload.go b/builder/vsphere/common/step_remote_upload.go index 522ae5a96..413d0c051 100644 --- a/builder/vsphere/common/step_remote_upload.go +++ b/builder/vsphere/common/step_remote_upload.go @@ -3,6 +3,7 @@ package common import ( "context" "fmt" + "log" "path/filepath" "github.com/hashicorp/packer/builder/vsphere/driver" @@ -14,6 +15,7 @@ type StepRemoteUpload struct { Datastore string Host string SetHostForDatastoreUploads bool + UploadedCustomCD bool } func (s *StepRemoteUpload) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { @@ -36,6 +38,7 @@ func (s *StepRemoteUpload) Run(_ context.Context, state multistep.StateBag) mult state.Put("error", err) return multistep.ActionHalt } + s.UploadedCustomCD = true state.Put("cd_path", fullRemotePath) } @@ -66,8 +69,11 @@ func (s *StepRemoteUpload) uploadFile(path string, d driver.Driver, ui packer.Ui ui.Say(fmt.Sprintf("Uploading %s to %s", filename, remotePath)) - if err := ds.MakeDirectory(remoteDirectory); err != nil { - return "", err + if exists := ds.DirExists(remotePath); exists == false { + log.Printf("Remote directory doesn't exist; creating...") + if err := ds.MakeDirectory(remoteDirectory); err != nil { + return "", err + } } if err := ds.UploadFile(path, remotePath, s.Host, s.SetHostForDatastoreUploads); err != nil { @@ -83,23 +89,29 @@ func (s *StepRemoteUpload) Cleanup(state multistep.StateBag) { return } + if !s.UploadedCustomCD { + return + } + + UploadedCDPath, ok := state.GetOk("cd_path") + if !ok { + return + } + ui := state.Get("ui").(packer.Ui) d := state.Get("driver").(*driver.VCenterDriver) + ui.Say("Deleting cd_files image from remote datastore ...") - if UploadedCDPath, ok := state.GetOk("cd_path"); ok { - ui.Say("Deleting cd_files image from remote datastore ...") - - ds, err := d.FindDatastore(s.Datastore, s.Host) - if err != nil { - state.Put("error", err) - return - } + ds, err := d.FindDatastore(s.Datastore, s.Host) + if err != nil { + log.Printf("Error finding datastore to delete custom CD; please delete manually: %s", err) + return + } - err = ds.Delete(UploadedCDPath.(string)) - if err != nil { - state.Put("error", err) - return - } + err = ds.Delete(UploadedCDPath.(string)) + if err != nil { + log.Printf("Error deleting custom CD from remote datastore; please delete manually: %s", err) + return } } diff --git a/builder/vsphere/common/step_remote_upload_test.go b/builder/vsphere/common/step_remote_upload_test.go index 85526017d..44188dbfe 100644 --- a/builder/vsphere/common/step_remote_upload_test.go +++ b/builder/vsphere/common/step_remote_upload_test.go @@ -11,7 +11,11 @@ import ( func TestStepRemoteUpload_Run(t *testing.T) { state := basicStateBag(nil) + dsMock := driver.DatastoreMock{ + DirExistsReturn: false, + } driverMock := driver.NewDriverMock() + driverMock.DatastoreMock = &dsMock state.Put("driver", driverMock) state.Put("iso_path", "[datastore] iso/path") diff --git a/builder/vsphere/driver/datastore.go b/builder/vsphere/driver/datastore.go index f8eaf6eaf..adc13447f 100644 --- a/builder/vsphere/driver/datastore.go +++ b/builder/vsphere/driver/datastore.go @@ -16,6 +16,7 @@ import ( type Datastore interface { Info(params ...string) (*mo.Datastore, error) FileExists(path string) bool + DirExists(path string) bool Name() string ResolvePath(path string) string UploadFile(src, dst, host string, setHost bool) error @@ -102,6 +103,14 @@ func (ds *DatastoreDriver) Info(params ...string) (*mo.Datastore, error) { return &info, nil } +func (ds *DatastoreDriver) DirExists(filepath string) bool { + _, err := ds.ds.Stat(ds.driver.ctx, filepath) + if _, ok := err.(object.DatastoreNoSuchDirectoryError); ok { + return false + } + return true +} + func (ds *DatastoreDriver) FileExists(path string) bool { _, err := ds.ds.Stat(ds.driver.ctx, path) return err == nil diff --git a/builder/vsphere/driver/datastore_mock.go b/builder/vsphere/driver/datastore_mock.go index 889dd254a..9330d9227 100644 --- a/builder/vsphere/driver/datastore_mock.go +++ b/builder/vsphere/driver/datastore_mock.go @@ -9,6 +9,9 @@ type DatastoreMock struct { FileExistsCalled bool FileExistsReturn bool + DirExistsCalled bool + DirExistsReturn bool + NameReturn string MakeDirectoryCalled bool @@ -37,6 +40,10 @@ func (ds *DatastoreMock) FileExists(path string) bool { return ds.FileExistsReturn } +func (ds *DatastoreMock) DirExists(path string) bool { + ds.DirExistsCalled = true + return ds.DirExistsReturn +} func (ds *DatastoreMock) Name() string { if ds.NameReturn == "" { return "datastore-mock"