Skip to content

Commit

Permalink
Add support for extra ISO in Proxmox builder
Browse files Browse the repository at this point in the history
  • Loading branch information
jmreyes committed May 17, 2020
1 parent 170520d commit ee8c832
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 32 deletions.
31 changes: 29 additions & 2 deletions builder/proxmox/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) {
return nil, nil, nil
}

const downloadPathKey = "downloaded_iso_path"
const (
downloadPathKey = "downloaded_iso_path"
targetPathKey = "iso_file"
downloadPathKeyExtra = "downloaded_iso_path_extra"
targetPathKeyExtra = "iso_file_extra"
)

func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
var err error
Expand Down Expand Up @@ -73,7 +78,29 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
TargetPath: b.config.TargetPath,
Url: b.config.ISOUrls,
},
&stepUploadISO{},
&common.StepDownload{
Checksum: b.config.extraISOConfig.ISOChecksum,
ChecksumType: b.config.extraISOConfig.ISOChecksumType,
Description: "ISO",
Extension: b.config.TargetExtension,
ResultKey: downloadPathKeyExtra,
TargetPath: b.config.TargetPath,
Url: b.config.extraISOConfig.ISOUrls,
},
&stepUploadISO{
ShouldUpload: b.config.shouldUploadISO,
DownloadPathKey: downloadPathKey,
TargetStoragePathKey: targetPathKey,
ISOUrls: b.config.ISOUrls,
ISOFile: b.config.ISOFile,
},
&stepUploadISO{
ShouldUpload: b.config.shouldUploadExtraISO,
DownloadPathKey: downloadPathKeyExtra,
TargetStoragePathKey: targetPathKeyExtra,
ISOUrls: b.config.extraISOConfig.ISOUrls,
ISOFile: b.config.ISOFileExtra,
},
&stepStartVM{},
&common.StepHTTPServer{
HTTPDir: b.config.HTTPDir,
Expand Down
58 changes: 42 additions & 16 deletions builder/proxmox/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,36 @@ type Config struct {
VMName string `mapstructure:"vm_name"`
VMID int `mapstructure:"vm_id"`

Memory int `mapstructure:"memory"`
Cores int `mapstructure:"cores"`
CPUType string `mapstructure:"cpu_type"`
Sockets int `mapstructure:"sockets"`
OS string `mapstructure:"os"`
VGA vgaConfig `mapstructure:"vga"`
NICs []nicConfig `mapstructure:"network_adapters"`
Disks []diskConfig `mapstructure:"disks"`
ISOFile string `mapstructure:"iso_file"`
ISOStoragePool string `mapstructure:"iso_storage_pool"`
Agent bool `mapstructure:"qemu_agent"`
SCSIController string `mapstructure:"scsi_controller"`
Onboot bool `mapstructure:"onboot"`
Memory int `mapstructure:"memory"`
Cores int `mapstructure:"cores"`
CPUType string `mapstructure:"cpu_type"`
Sockets int `mapstructure:"sockets"`
OS string `mapstructure:"os"`
VGA vgaConfig `mapstructure:"vga"`
NICs []nicConfig `mapstructure:"network_adapters"`
Disks []diskConfig `mapstructure:"disks"`
ISOFile string `mapstructure:"iso_file"`
ISOFileExtra string `mapstructure:"iso_file_extra"`
ISOUrlExtra string `mapstructure:"iso_url_extra"`
ISOChecksumExtra string `mapstructure:"iso_checksum_extra"`
ISOChecksumURLExtra string `mapstructure:"iso_checksum_url_extra"`
ISOChecksumTypeExtra string `mapstructure:"iso_checksum_type_extra"`
ISOStoragePool string `mapstructure:"iso_storage_pool"`
Agent bool `mapstructure:"qemu_agent"`
SCSIController string `mapstructure:"scsi_controller"`
Onboot bool `mapstructure:"onboot"`

TemplateName string `mapstructure:"template_name"`
TemplateDescription string `mapstructure:"template_description"`
UnmountISO bool `mapstructure:"unmount_iso"`
UnmountExtraISO bool `mapstructure:"unmount_extra_iso"`

CloudInit bool `mapstructure:"cloud_init"`
CloudInitStoragePool string `mapstructure:"cloud_init_storage_pool"`

shouldUploadISO bool
shouldUploadISO bool
shouldUploadExtraISO bool
extraISOConfig common.ISOConfig

ctx interpolate.Context
}
Expand Down Expand Up @@ -202,11 +210,29 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
c.shouldUploadISO = true
}

if c.ISOFileExtra != "" {
c.shouldUploadExtraISO = false
} else if c.ISOUrlExtra != "" {
c.extraISOConfig = common.ISOConfig{
RawSingleISOUrl: c.ISOUrlExtra,
ISOChecksum: c.ISOChecksumExtra,
ISOChecksumURL: c.ISOChecksumURLExtra,
ISOChecksumType: c.ISOChecksumTypeExtra,
}
isoWarnings, isoErrors := c.extraISOConfig.Prepare(&c.ctx)
errs = packer.MultiErrorAppend(errs, isoErrors...)
warnings = append(warnings, isoWarnings...)
c.shouldUploadExtraISO = true
}

if (c.ISOFile == "" && len(c.ISOConfig.ISOUrls) == 0) || (c.ISOFile != "" && len(c.ISOConfig.ISOUrls) != 0) {
errs = packer.MultiErrorAppend(errs, errors.New("either iso_file or iso_url, but not both, must be specified"))
}
if len(c.ISOConfig.ISOUrls) != 0 && c.ISOStoragePool == "" {
errs = packer.MultiErrorAppend(errs, errors.New("when specifying iso_url, iso_storage_pool must also be specified"))
if c.ISOFileExtra != "" && c.ISOUrlExtra != "" {
errs = packer.MultiErrorAppend(errs, errors.New("either iso_file_extra or iso_url_extra, but not both, can be specified"))
}
if (len(c.ISOConfig.ISOUrls) != 0 || c.ISOUrlExtra != "") && c.ISOStoragePool == "" {
errs = packer.MultiErrorAppend(errs, errors.New("when specifying iso_url or iso_url_extra, iso_storage_pool must also be specified"))
}

// Required configurations that will display errors if not set
Expand Down
24 changes: 17 additions & 7 deletions builder/proxmox/step_finalize_template_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (s *stepFinalizeTemplateConfig) Run(ctx context.Context, state multistep.St
// set, we need to clear it
changes["description"] = c.TemplateDescription

if c.UnmountISO {
if c.UnmountISO || c.UnmountExtraISO {
vmParams, err := client.GetVmConfig(vmRef)
if err != nil {
err := fmt.Errorf("Error fetching template config: %s", err)
Expand All @@ -47,13 +47,23 @@ func (s *stepFinalizeTemplateConfig) Run(ctx context.Context, state multistep.St
return multistep.ActionHalt
}

if vmParams["ide2"] == nil || !strings.HasSuffix(vmParams["ide2"].(string), "media=cdrom") {
err := fmt.Errorf("Cannot eject ISO from cdrom drive, ide2 is not present, or not a cdrom media")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
devices := []string{}
if c.UnmountISO {
devices = append(devices, "ide2")
}
if c.UnmountExtraISO {
devices = append(devices, "ide3")
}

for _, device := range devices {
if vmParams[device] == nil || !strings.HasSuffix(vmParams[device].(string), "media=cdrom") {
err := fmt.Errorf("Cannot eject ISO from cdrom drive, %v is not present, or not a cdrom media", device)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
changes[device] = "none,media=cdrom"
}
changes["ide2"] = "none,media=cdrom"
}

if c.CloudInit {
Expand Down
2 changes: 2 additions & 0 deletions builder/proxmox/step_start_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist
}

isoFile := state.Get("iso_file").(string)
isoFileExtra := state.Get("iso_file_extra").(string)

ui.Say("Creating VM")
config := proxmox.ConfigQemu{
Expand All @@ -41,6 +42,7 @@ func (s *stepStartVM) Run(ctx context.Context, state multistep.StateBag) multist
QemuOs: c.OS,
QemuVga: generateProxmoxVga(c.VGA),
QemuIso: isoFile,
QemuIsoExtra: isoFileExtra,
QemuNetworks: generateProxmoxNetworkAdapters(c.NICs),
QemuDisks: generateProxmoxDisks(c.Disks),
Scsihw: c.SCSIController,
Expand Down
19 changes: 13 additions & 6 deletions builder/proxmox/step_upload_iso.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ import (
)

// stepUploadISO uploads an ISO file to Proxmox so we can boot from it
type stepUploadISO struct{}
type stepUploadISO struct {
ShouldUpload bool
DownloadPathKey string
TargetStoragePathKey string
ISOUrls []string
ISOFile string
}

type uploader interface {
Upload(node string, storage string, contentType string, filename string, file io.Reader) error
Expand All @@ -26,12 +32,12 @@ func (s *stepUploadISO) Run(ctx context.Context, state multistep.StateBag) multi
client := state.Get("proxmoxClient").(uploader)
c := state.Get("config").(*Config)

if !c.shouldUploadISO {
state.Put("iso_file", c.ISOFile)
if !s.ShouldUpload {
state.Put(s.TargetStoragePathKey, s.ISOFile)
return multistep.ActionContinue
}

p := state.Get(downloadPathKey).(string)
p := state.Get(s.DownloadPathKey).(string)
if p == "" {
err := fmt.Errorf("Path to downloaded ISO was empty")
state.Put("error", err)
Expand All @@ -48,7 +54,8 @@ func (s *stepUploadISO) Run(ctx context.Context, state multistep.StateBag) multi
return multistep.ActionHalt
}

filename := filepath.Base(c.ISOUrls[0])
filename := filepath.Base(s.ISOUrls[0])
ui.Say(fmt.Sprintf("Uploading %s...", filename))
err = client.Upload(c.Node, c.ISOStoragePool, "iso", filename, r)
if err != nil {
state.Put("error", err)
Expand All @@ -57,7 +64,7 @@ func (s *stepUploadISO) Run(ctx context.Context, state multistep.StateBag) multi
}

isoStoragePath := fmt.Sprintf("%s:iso/%s", c.ISOStoragePool, filename)
state.Put("iso_file", isoStoragePath)
state.Put(s.TargetStoragePathKey, isoStoragePath)

return multistep.ActionContinue
}
Expand Down
8 changes: 7 additions & 1 deletion builder/proxmox/step_upload_iso_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,13 @@ func TestUploadISO(t *testing.T) {
state.Put(downloadPathKey, c.downloadPath)
state.Put("proxmoxClient", m)

step := stepUploadISO{}
step := stepUploadISO{
ShouldUpload: c.builderConfig.shouldUploadISO,
DownloadPathKey: downloadPathKey,
TargetStoragePathKey: targetPathKey,
ISOUrls: c.builderConfig.ISOUrls,
ISOFile: c.builderConfig.ISOFile,
}
action := step.Run(context.TODO(), state)
step.Cleanup(state)

Expand Down

0 comments on commit ee8c832

Please sign in to comment.