From 0f9f0c2d15ee5c1af32d0dd949405d0df5c4b4b8 Mon Sep 17 00:00:00 2001 From: Dongyu Zheng Date: Wed, 26 Oct 2016 20:08:26 -0700 Subject: [PATCH 1/5] Added iso_name uuid:// and documentation --- builder/xenserver/common/step_find_vdi.go | 9 ++++++ docs/builders/xenserver-iso.html.markdown | 37 ++++++++++++++--------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/builder/xenserver/common/step_find_vdi.go b/builder/xenserver/common/step_find_vdi.go index 34912317..88adf2ab 100644 --- a/builder/xenserver/common/step_find_vdi.go +++ b/builder/xenserver/common/step_find_vdi.go @@ -20,6 +20,15 @@ func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { // Ignore if VdiName is not specified if self.VdiName == "" { return multistep.ActionContinue + } else if len(self.VdiName) >= 7 && self.VdiName[:7] == "uuid://" { + vdiUuid:= self.VdiName[7:] + _, err := client.GetVdiByUuid(vdiUuid) + if err != nil { + ui.Error(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error())) + return multistep.ActionHalt + } + state.Put(self.VdiUuidKey, vdiUuid) + return multistep.ActionContinue } vdis, err := client.GetVdiByNameLabel(self.VdiName) diff --git a/docs/builders/xenserver-iso.html.markdown b/docs/builders/xenserver-iso.html.markdown index bc7c00e3..b00ab1ac 100644 --- a/docs/builders/xenserver-iso.html.markdown +++ b/docs/builders/xenserver-iso.html.markdown @@ -54,21 +54,28 @@ 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" + +* 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. From c8b8a2f046584e592e6d0222bd729002404ff5c5 Mon Sep 17 00:00:00 2001 From: Dongyu Zheng Date: Wed, 26 Oct 2016 20:14:44 -0700 Subject: [PATCH 2/5] Ran gofmt -s -w . --- builder/xenserver/common/step_find_vdi.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/xenserver/common/step_find_vdi.go b/builder/xenserver/common/step_find_vdi.go index 88adf2ab..ceeedac0 100644 --- a/builder/xenserver/common/step_find_vdi.go +++ b/builder/xenserver/common/step_find_vdi.go @@ -21,7 +21,7 @@ func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { if self.VdiName == "" { return multistep.ActionContinue } else if len(self.VdiName) >= 7 && self.VdiName[:7] == "uuid://" { - vdiUuid:= self.VdiName[7:] + vdiUuid := self.VdiName[7:] _, err := client.GetVdiByUuid(vdiUuid) if err != nil { ui.Error(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error())) From 59c87aee87ca237032fa7c8047f91d00b4eff44b Mon Sep 17 00:00:00 2001 From: Dongyu Zheng Date: Thu, 27 Oct 2016 18:31:59 -0700 Subject: [PATCH 3/5] Use iso_url as fallback if iso_name fails --- builder/xenserver/common/step_find_vdi.go | 56 +++++++++++++------ builder/xenserver/iso/builder.go | 33 +++++++---- builder/xenserver/iso/step_create_instance.go | 2 +- docs/builders/xenserver-iso.html.markdown | 1 + 4 files changed, 64 insertions(+), 28 deletions(-) diff --git a/builder/xenserver/common/step_find_vdi.go b/builder/xenserver/common/step_find_vdi.go index ceeedac0..8e930a16 100644 --- a/builder/xenserver/common/step_find_vdi.go +++ b/builder/xenserver/common/step_find_vdi.go @@ -8,50 +8,72 @@ 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) Run(state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packer.Ui) - client := state.Get("client").(xsclient.XenAPIClient) +func (self *StepFindVdi) ErrorHandler(msg string) multistep.StepAction { + self.PreviousResult = "FAILURE" + self.PreviousStepAction = self.ErrorFunc(msg) + return self.PreviousStepAction +} +func (self *StepFindVdi) GetUuid(ui packer.Ui, client xsclient.XenAPIClient, state multistep.StateBag) multistep.StepAction { // Ignore if VdiName is not specified if self.VdiName == "" { return multistep.ActionContinue - } else if len(self.VdiName) >= 7 && self.VdiName[:7] == "uuid://" { + } + + 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 { - ui.Error(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error())) - return multistep.ActionHalt + return self.ErrorHandler(fmt.Sprintf("Unable to get VDI from UUID '%s': %s", vdiUuid, err.Error())) } state.Put(self.VdiUuidKey, vdiUuid) - return multistep.ActionContinue + 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 self.PreviousStepAction +} - return multistep.ActionContinue +func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packer.Ui) + client := state.Get("client").(xsclient.XenAPIClient) + return self.GetUuid(ui, client, state) } func (self *StepFindVdi) Cleanup(state multistep.StateBag) {} diff --git a/builder/xenserver/iso/builder.go b/builder/xenserver/iso/builder.go index 03f26cf7..1c2cd7bf 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,22 @@ 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.GetUuid(ui, client, 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 +268,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 +333,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 b00ab1ac..2ab7fee4 100644 --- a/docs/builders/xenserver-iso.html.markdown +++ b/docs/builders/xenserver-iso.html.markdown @@ -58,6 +58,7 @@ each category, the available options are alphabetized and described. * `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: From b8376b488e5d02e4ce328d28c5aaf6cf84cfef7d Mon Sep 17 00:00:00 2001 From: Dongyu Zheng Date: Thu, 27 Oct 2016 18:34:33 -0700 Subject: [PATCH 4/5] Add missing period --- docs/builders/xenserver-iso.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/builders/xenserver-iso.html.markdown b/docs/builders/xenserver-iso.html.markdown index 2ab7fee4..2ca60b7b 100644 --- a/docs/builders/xenserver-iso.html.markdown +++ b/docs/builders/xenserver-iso.html.markdown @@ -57,7 +57,7 @@ each category, the available options are alphabetized and described. * 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" + 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: From 3da8618e184d5a7a399482cd4c25149b4e92b58b Mon Sep 17 00:00:00 2001 From: Dongyu Zheng Date: Thu, 27 Oct 2016 19:56:53 -0700 Subject: [PATCH 5/5] Moved getUuid code into Run --- builder/xenserver/common/step_find_vdi.go | 11 ++++------- builder/xenserver/iso/builder.go | 5 ++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/builder/xenserver/common/step_find_vdi.go b/builder/xenserver/common/step_find_vdi.go index 8e930a16..1f48b9d4 100644 --- a/builder/xenserver/common/step_find_vdi.go +++ b/builder/xenserver/common/step_find_vdi.go @@ -21,7 +21,10 @@ func (self *StepFindVdi) ErrorHandler(msg string) multistep.StepAction { return self.PreviousStepAction } -func (self *StepFindVdi) GetUuid(ui packer.Ui, client xsclient.XenAPIClient, state multistep.StateBag) multistep.StepAction { +func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { + ui := state.Get("ui").(packer.Ui) + client := state.Get("client").(xsclient.XenAPIClient) + // Ignore if VdiName is not specified if self.VdiName == "" { return multistep.ActionContinue @@ -70,10 +73,4 @@ func (self *StepFindVdi) GetUuid(ui packer.Ui, client xsclient.XenAPIClient, sta return self.PreviousStepAction } -func (self *StepFindVdi) Run(state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packer.Ui) - client := state.Get("client").(xsclient.XenAPIClient) - return self.GetUuid(ui, client, state) -} - func (self *StepFindVdi) Cleanup(state multistep.StateBag) {} diff --git a/builder/xenserver/iso/builder.go b/builder/xenserver/iso/builder.go index 1c2cd7bf..02b1b3e7 100644 --- a/builder/xenserver/iso/builder.go +++ b/builder/xenserver/iso/builder.go @@ -220,7 +220,10 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa }, } - step_find_vdi_iso_name.GetUuid(ui, client, state) + 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))