diff --git a/builder/xenserver/common/step_find_vdi.go b/builder/xenserver/common/step_find_vdi.go index 34912317..1f48b9d4 100644 --- a/builder/xenserver/common/step_find_vdi.go +++ b/builder/xenserver/common/step_find_vdi.go @@ -8,9 +8,17 @@ import ( ) type StepFindVdi struct { - VdiName string - ImagePathFunc func() string - VdiUuidKey string + VdiName string + VdiUuidKey string + PreviousResult string + PreviousStepAction multistep.StepAction + ErrorFunc func(errString string) multistep.StepAction +} + +func (self *StepFindVdi) ErrorHandler(msg string) multistep.StepAction { + self.PreviousResult = "FAILURE" + self.PreviousStepAction = self.ErrorFunc(msg) + return self.PreviousStepAction } func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { @@ -22,27 +30,47 @@ func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionContinue } + if self.PreviousResult != "" { + return self.PreviousStepAction + } + + self.PreviousResult = "SUCCESS" + self.PreviousStepAction = multistep.ActionContinue + + if self.ErrorFunc == nil { + self.ErrorFunc = func(errString string) multistep.StepAction { + ui.Error(errString) + return multistep.ActionHalt + } + } + + if len(self.VdiName) >= 7 && self.VdiName[:7] == "uuid://" { + vdiUuid := self.VdiName[7:] + _, err := client.GetVdiByUuid(vdiUuid) + if err != nil { + return self.ErrorHandler(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error())) + } + state.Put(self.VdiUuidKey, vdiUuid) + return self.PreviousStepAction + } + vdis, err := client.GetVdiByNameLabel(self.VdiName) switch { case len(vdis) == 0: - ui.Error(fmt.Sprintf("Couldn't find a VDI named '%s'", self.VdiName)) - return multistep.ActionHalt + return self.ErrorHandler(fmt.Sprintf("Couldn't find a VDI named '%s'", self.VdiName)) case len(vdis) > 1: - ui.Error(fmt.Sprintf("Found more than one VDI with name '%s'. Name must be unique", self.VdiName)) - return multistep.ActionHalt + return self.ErrorHandler(fmt.Sprintf("Found more than one VDI with name '%s'. Name must be unique", self.VdiName)) } vdi := vdis[0] vdiUuid, err := vdi.GetUuid() if err != nil { - ui.Error(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", self.VdiName, err.Error())) - return multistep.ActionHalt + return self.ErrorHandler(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", self.VdiName, err.Error())) } state.Put(self.VdiUuidKey, vdiUuid) - - return multistep.ActionContinue + return self.PreviousStepAction } func (self *StepFindVdi) Cleanup(state multistep.StateBag) {} diff --git a/builder/xenserver/iso/builder.go b/builder/xenserver/iso/builder.go index 03f26cf7..02b1b3e7 100644 --- a/builder/xenserver/iso/builder.go +++ b/builder/xenserver/iso/builder.go @@ -118,7 +118,11 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error errs, fmt.Errorf("Failed to parse install_timeout: %s", err)) } - if self.config.ISOName == "" { + if self.config.ISOUrl == "" && self.config.ISOName == "" { + errs = packer.MultiErrorAppend(errs, fmt.Errorf("Either iso_url or iso_name must be specified")) + } + + if self.config.ISOUrl != "" { // If ISO name is not specified, assume a URL and checksum has been provided. @@ -162,10 +166,6 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error errs, fmt.Errorf("Failed to parse iso_urls[%d]: %s", i, err)) } } - } else { - - // An ISO name has been provided. It should be attached from an available SR. - } if len(errs.Errors) > 0 { @@ -210,6 +210,25 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa }, } + step_find_vdi_iso_name := &xscommon.StepFindVdi{ + VdiName: self.config.ISOName, + VdiUuidKey: "isoname_vdi_uuid", + ErrorFunc: func(errString string) multistep.StepAction { + ui.Error(errString) + ui.Error("Defaulting to use \"iso_url\".") + return multistep.ActionContinue + }, + } + + step_find_vdi_iso_name_runner := &multistep.BasicRunner{Steps: []multistep.Step{ + step_find_vdi_iso_name, + }} + step_find_vdi_iso_name_runner.Run(state) + + if step_find_vdi_iso_name.PreviousResult == "FAILURE" && self.config.ISOUrl == "" { + return nil, errors.New(fmt.Sprintf("Failed to find \"iso_name\": \"%s\" and \"iso_url\" is empty. Aborting.", self.config.ISOName)) + } + steps := []multistep.Step{ &xscommon.StepPrepareOutputDir{ Force: self.config.PackerForce, @@ -252,10 +271,7 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa VdiName: self.config.ToolsIsoName, VdiUuidKey: "tools_vdi_uuid", }, - &xscommon.StepFindVdi{ - VdiName: self.config.ISOName, - VdiUuidKey: "isoname_vdi_uuid", - }, + step_find_vdi_iso_name, new(stepCreateInstance), &xscommon.StepAttachVdi{ VdiUuidKey: "floppy_vdi_uuid", @@ -320,7 +336,7 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa new(xscommon.StepExport), } - if self.config.ISOName == "" { + if self.config.ISOName == "" || (self.config.ISOUrl != "" && step_find_vdi_iso_name.PreviousResult == "FAILURE") { steps = append(download_steps, steps...) } diff --git a/builder/xenserver/iso/step_create_instance.go b/builder/xenserver/iso/step_create_instance.go index a973af45..0980031a 100644 --- a/builder/xenserver/iso/step_create_instance.go +++ b/builder/xenserver/iso/step_create_instance.go @@ -39,7 +39,7 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi // Clone that VM template instance, err := template.Clone(config.VMName) if err != nil { - ui.Error(fmt.Sprintf("Error cloning VM: %s", err.Error())) + ui.Error(fmt.Sprintf("Error cloning template: %s", err.Error())) return multistep.ActionHalt } self.instance = instance diff --git a/docs/builders/xenserver-iso.html.markdown b/docs/builders/xenserver-iso.html.markdown index bc7c00e3..2ca60b7b 100644 --- a/docs/builders/xenserver-iso.html.markdown +++ b/docs/builders/xenserver-iso.html.markdown @@ -54,21 +54,29 @@ each category, the available options are alphabetized and described. ### Required: -* `iso_checksum` (string) - The checksum for the OS ISO file. Because ISO - files are so large, this is required and Packer will verify it prior - to booting a virtual machine with the ISO attached. The type of the - checksum is specified with `iso_checksum_type`, documented below. - -* `iso_checksum_type` (string) - The type of the checksum specified in - `iso_checksum`. Valid values are "none", "md5", "sha1", "sha256", or - "sha512" currently. While "none" will skip checksumming, this is not - recommended since ISO files are generally large and corruption does happen - from time to time. - -* `iso_url` (string) - A URL to the ISO containing the installation image. - This URL can be either an HTTP URL or a file URL (or path to a file). - If this is an HTTP URL, Packer will download it and cache it between - runs. +* Either: + + * `iso_name` (string) - Unique name of an ISO available in XenCenter's storage repositories. + Or it can be the UUID of the ISO's VDI prefixed by "uuid://". For example: "uuid://aa2f2c86-b79a-4345-a35f-ce244f43c97a". + If this fails and `iso_url` is given, `iso_url` will be tried. + +* OR: + + * `iso_checksum` (string) - The checksum for the OS ISO file. Because ISO + files are so large, this is required and Packer will verify it prior + to booting a virtual machine with the ISO attached. The type of the + checksum is specified with `iso_checksum_type`, documented below. + + * `iso_checksum_type` (string) - The type of the checksum specified in + `iso_checksum`. Valid values are "none", "md5", "sha1", "sha256", or + "sha512" currently. While "none" will skip checksumming, this is not + recommended since ISO files are generally large and corruption does happen + from time to time. + + * `iso_url` (string) - A URL to the ISO containing the installation image. + This URL can be either an HTTP URL or a file URL (or path to a file). + If this is an HTTP URL, Packer will download it and cache it between + runs. * `remote_host` (string) - The host of the remote machine.