diff --git a/builder/vsphere/iso/builder.go b/builder/vsphere/iso/builder.go index 0665b2088..f9ace1139 100644 --- a/builder/vsphere/iso/builder.go +++ b/builder/vsphere/iso/builder.go @@ -40,27 +40,23 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &common.StepConnect{ Config: &b.config.ConnectConfig, }, - ) - - if b.config.ISOUrls != nil { - steps = append(steps, - &packerCommon.StepDownload{ - Checksum: b.config.ISOChecksum, - Description: "ISO", - Extension: b.config.TargetExtension, - ResultKey: "iso_path", - TargetPath: b.config.TargetPath, - Url: b.config.ISOUrls, - }, - &StepRemoteUpload{ - Datastore: b.config.Datastore, - Host: b.config.Host, - SetHostForDatastoreUploads: b.config.SetHostForDatastoreUploads, - }, - ) - } - - steps = append(steps, + &packerCommon.StepDownload{ + Checksum: b.config.ISOChecksum, + Description: "ISO", + Extension: b.config.TargetExtension, + ResultKey: "iso_path", + TargetPath: b.config.TargetPath, + Url: b.config.ISOUrls, + }, + &packerCommon.StepCreateCD{ + Files: b.config.CDConfig.CDFiles, + Label: b.config.CDConfig.CDLabel, + }, + &StepRemoteUpload{ + Datastore: b.config.Datastore, + Host: b.config.Host, + SetHostForDatastoreUploads: b.config.SetHostForDatastoreUploads, + }, &StepCreateVM{ Config: &b.config.CreateConfig, Location: &b.config.LocationConfig, diff --git a/builder/vsphere/iso/config.go b/builder/vsphere/iso/config.go index 890f10942..42b583e7f 100644 --- a/builder/vsphere/iso/config.go +++ b/builder/vsphere/iso/config.go @@ -15,6 +15,7 @@ import ( type Config struct { packerCommon.PackerConfig `mapstructure:",squash"` packerCommon.HTTPConfig `mapstructure:",squash"` + packerCommon.CDConfig `mapstructure:",squash"` common.ConnectConfig `mapstructure:",squash"` CreateConfig `mapstructure:",squash"` @@ -80,6 +81,7 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.CDRomConfig.Prepare()...) + errs = packer.MultiErrorAppend(errs, c.CDConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.BootConfig.Prepare(&c.ctx)...) errs = packer.MultiErrorAppend(errs, c.WaitIpConfig.Prepare()...) errs = packer.MultiErrorAppend(errs, c.Comm.Prepare(&c.ctx)...) diff --git a/builder/vsphere/iso/config.hcl2spec.go b/builder/vsphere/iso/config.hcl2spec.go index 3d298aec6..4216438f0 100644 --- a/builder/vsphere/iso/config.hcl2spec.go +++ b/builder/vsphere/iso/config.hcl2spec.go @@ -22,6 +22,8 @@ type FlatConfig struct { HTTPPortMax *int `mapstructure:"http_port_max" cty:"http_port_max" hcl:"http_port_max"` HTTPAddress *string `mapstructure:"http_bind_address" cty:"http_bind_address" hcl:"http_bind_address"` HTTPInterface *string `mapstructure:"http_interface" undocumented:"true" cty:"http_interface" hcl:"http_interface"` + CDFiles []string `mapstructure:"cd_files" cty:"cd_files" hcl:"cd_files"` + CDLabel *string `mapstructure:"cd_label" cty:"cd_label" hcl:"cd_label"` VCenterServer *string `mapstructure:"vcenter_server" cty:"vcenter_server" hcl:"vcenter_server"` Username *string `mapstructure:"username" cty:"username" hcl:"username"` Password *string `mapstructure:"password" cty:"password" hcl:"password"` @@ -158,6 +160,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "http_port_max": &hcldec.AttrSpec{Name: "http_port_max", Type: cty.Number, Required: false}, "http_bind_address": &hcldec.AttrSpec{Name: "http_bind_address", Type: cty.String, Required: false}, "http_interface": &hcldec.AttrSpec{Name: "http_interface", Type: cty.String, Required: false}, + "cd_files": &hcldec.AttrSpec{Name: "cd_files", Type: cty.List(cty.String), Required: false}, + "cd_label": &hcldec.AttrSpec{Name: "cd_label", Type: cty.String, Required: false}, "vcenter_server": &hcldec.AttrSpec{Name: "vcenter_server", Type: cty.String, Required: false}, "username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false}, "password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false}, diff --git a/builder/vsphere/iso/step_add_cdrom.go b/builder/vsphere/iso/step_add_cdrom.go index 6a6c22c1f..4dc77709b 100644 --- a/builder/vsphere/iso/step_add_cdrom.go +++ b/builder/vsphere/iso/step_add_cdrom.go @@ -62,6 +62,14 @@ func (s *StepAddCDRom) Run(_ context.Context, state multistep.StateBag) multiste } } + // Add our custom CD, if it exists + cd_path, ok := state.Get("cd_path").(string) + if ok { + if cd_path != "" { + s.Config.ISOPaths = append(s.Config.ISOPaths, cd_path) + } + } + if len(s.Config.ISOPaths) > 0 { for _, path := range s.Config.ISOPaths { if err := vm.AddCdrom(s.Config.CdromType, path); err != nil { diff --git a/builder/vsphere/iso/step_remote_upload.go b/builder/vsphere/iso/step_remote_upload.go index 7161962b8..c621d1150 100644 --- a/builder/vsphere/iso/step_remote_upload.go +++ b/builder/vsphere/iso/step_remote_upload.go @@ -21,39 +21,79 @@ func (s *StepRemoteUpload) Run(_ context.Context, state multistep.StateBag) mult d := state.Get("driver").(driver.Driver) if path, ok := state.GetOk("iso_path"); ok { - filename := filepath.Base(path.(string)) - - ds, err := d.FindDatastore(s.Datastore, s.Host) + // user-supplied boot iso + fullRemotePath, err := s.uploadFile(path.(string), d, ui) if err != nil { - state.Put("error", fmt.Errorf("datastore doesn't exist: %v", err)) - return multistep.ActionHalt - } - - remotePath := fmt.Sprintf("packer_cache/%s", filename) - remoteDirectory := fmt.Sprintf("[%s] packer_cache/", ds.Name()) - fullRemotePath := fmt.Sprintf("%s/%s", remoteDirectory, filename) - - ui.Say(fmt.Sprintf("Uploading %s to %s", filename, remotePath)) - - if exists := ds.FileExists(remotePath); exists == true { - ui.Say("File already uploaded; continuing") - state.Put("iso_remote_path", fullRemotePath) - return multistep.ActionContinue - } - - if err := ds.MakeDirectory(remoteDirectory); err != nil { - state.Put("error", err) - return multistep.ActionHalt - } - - if err := ds.UploadFile(path.(string), remotePath, s.Host, s.SetHostForDatastoreUploads); err != nil { state.Put("error", err) return multistep.ActionHalt } state.Put("iso_remote_path", fullRemotePath) } + if cdPath, ok := state.GetOk("cd_path"); ok { + // Packer-created cd_files disk + fullRemotePath, err := s.uploadFile(cdPath.(string), d, ui) + if err != nil { + state.Put("error", err) + return multistep.ActionHalt + } + state.Put("cd_path", fullRemotePath) + } return multistep.ActionContinue } -func (s *StepRemoteUpload) Cleanup(state multistep.StateBag) {} +func (s *StepRemoteUpload) uploadFile(path string, d driver.Driver, ui packer.Ui) (string, error) { + ds, err := d.FindDatastore(s.Datastore, s.Host) + if err != nil { + return "", fmt.Errorf("datastore doesn't exist: %v", err) + } + + filename := filepath.Base(path) + remotePath := fmt.Sprintf("packer_cache/%s", filename) + remoteDirectory := fmt.Sprintf("[%s] packer_cache/", ds.Name()) + fullRemotePath := fmt.Sprintf("%s/%s", remoteDirectory, filename) + + ui.Say(fmt.Sprintf("Uploading %s to %s", filename, remotePath)) + + if exists := ds.FileExists(remotePath); exists == true { + ui.Say(fmt.Sprintf("File %s already uploaded; continuing", filename)) + return fullRemotePath, nil + } + + if err := ds.MakeDirectory(remoteDirectory); err != nil { + return "", err + } + + if err := ds.UploadFile(path, remotePath, s.Host, s.SetHostForDatastoreUploads); err != nil { + return "", err + } + return fullRemotePath, nil +} + +func (s *StepRemoteUpload) Cleanup(state multistep.StateBag) { + _, cancelled := state.GetOk(multistep.StateCancelled) + _, halted := state.GetOk(multistep.StateHalted) + if !cancelled && !halted { + return + } + + ui := state.Get("ui").(packer.Ui) + d := state.Get("driver").(*driver.VCenterDriver) + + 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 + } + + err = ds.Delete(UploadedCDPath.(string)) + if err != nil { + state.Put("error", err) + return + } + + } +}