Adding legacy support for exporting VDI's as VHDs using the Transfer VM.

Signed-off-by: Rob Dobson <rob.dobson@citrix.com>
This commit is contained in:
Rob Dobson 2015-02-25 19:03:13 +00:00
parent d63518195d
commit a0e9c97c89
2 changed files with 1176 additions and 13 deletions

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ import (
type StepExport struct{} type StepExport struct{}
func downloadFile(url, filename string) (err error) { func downloadFile(url, filename string, ui packer.Ui) (err error) {
// Create the file // Create the file
fh, err := os.Create(filename) fh, err := os.Create(filename)
@ -37,7 +37,42 @@ func downloadFile(url, filename string) (err error) {
} }
defer resp.Body.Close() defer resp.Body.Close()
io.Copy(fh, resp.Body)
var progress uint
var total uint
var percentage uint
var marker_len uint
progress = uint(0)
total = uint(resp.ContentLength)
percentage = uint(0)
marker_len = uint(5)
var buffer [4096]byte
for {
n, err := resp.Body.Read(buffer[:])
if err != nil && err != io.EOF {
return err
}
progress += uint(n)
if _, write_err := fh.Write(buffer[:n]); write_err != nil {
return write_err
}
if err == io.EOF {
break
}
// Increment percentage in multiples of marker_len
cur_percentage := ((progress * 100 / total) / marker_len) * marker_len
if cur_percentage > percentage {
percentage = cur_percentage
ui.Message(fmt.Sprintf("Downloading... %d%%", percentage))
}
}
return nil return nil
} }
@ -75,7 +110,7 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
export_filename := fmt.Sprintf("%s/%s.xva", config.OutputDir, config.VMName) export_filename := fmt.Sprintf("%s/%s.xva", config.OutputDir, config.VMName)
ui.Say("Getting XVA " + export_url) ui.Say("Getting XVA " + export_url)
err = downloadFile(export_url, export_filename) err = downloadFile(export_url, export_filename, ui)
if err != nil { if err != nil {
ui.Error(fmt.Sprintf("Could not download XVA: %s", err.Error())) ui.Error(fmt.Sprintf("Could not download XVA: %s", err.Error()))
return multistep.ActionHalt return multistep.ActionHalt
@ -100,24 +135,63 @@ func (StepExport) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt return multistep.ActionHalt
} }
// Basic auth in URL request is required as session token is not // Work out XenServer version
// accepted for some reason. hosts, err := client.GetHosts()
// @todo: raise with XAPI team.
disk_export_url := fmt.Sprintf("https://%s:%s@%s/export_raw_vdi?vdi=%s%s", if err != nil {
client.Username, ui.Error(fmt.Sprintf("Could not retrieve hosts in the pool: %s", err.Error()))
client.Password, return multistep.ActionHalt
client.Host, }
disk_uuid, host := hosts[0]
extrauri) host_software_versions, err := host.GetSoftwareVersion()
xs_version := host_software_versions["product_version"].(string)
if err != nil {
ui.Error(fmt.Sprintf("Could not get the software version: %s", err.Error()))
return multistep.ActionHalt
}
var disk_export_url string
// @todo: check for 6.5 SP1
if xs_version <= "6.5.0" && config.Format == "vdi_vhd" {
// Export the VHD using a Transfer VM
disk_export_url, err = disk.Expose("vhd")
if err != nil {
ui.Error(fmt.Sprintf("Failed to expose disk %s: %s", disk_uuid, err.Error()))
return multistep.ActionHalt
}
} else {
// Use the preferred direct export from XAPI
// Basic auth in URL request is required as session token is not
// accepted for some reason.
// @todo: raise with XAPI team.
disk_export_url = fmt.Sprintf("https://%s:%s@%s/export_raw_vdi?vdi=%s%s",
client.Username,
client.Password,
client.Host,
disk_uuid,
extrauri)
}
disk_export_filename := fmt.Sprintf("%s/%s%s", config.OutputDir, disk_uuid, suffix) disk_export_filename := fmt.Sprintf("%s/%s%s", config.OutputDir, disk_uuid, suffix)
ui.Say("Getting VDI " + disk_export_url) ui.Say("Getting VDI " + disk_export_url)
err = downloadFile(disk_export_url, disk_export_filename) err = downloadFile(disk_export_url, disk_export_filename, ui)
if err != nil { if err != nil {
ui.Error(fmt.Sprintf("Could not download VDI: %s", err.Error())) ui.Error(fmt.Sprintf("Could not download VDI: %s", err.Error()))
return multistep.ActionHalt return multistep.ActionHalt
} }
// Call unexpose in case a TVM was used. The call is harmless
// if that is not the case.
disk.Unexpose()
} }
default: default: