packer-plugin-xenserver/builder/xenserver/common/step_upload_vdi.go

153 lines
3.8 KiB
Go
Raw Normal View History

package common
import (
"fmt"
"log"
"os"
"time"
2020-09-13 03:21:07 -05:00
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
xenapi "github.com/terra-farm/go-xen-api-client"
)
type StepUploadVdi struct {
VdiNameFunc func() string
ImagePathFunc func() string
VdiUuidKey string
}
func (self *StepUploadVdi) Run(state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
2020-09-13 03:21:07 -05:00
c := state.Get("client").(*Connection)
imagePath := self.ImagePathFunc()
vdiName := self.VdiNameFunc()
if imagePath == "" {
// skip if no disk image to attach
return multistep.ActionContinue
}
ui.Say(fmt.Sprintf("Step: Upload VDI '%s'", vdiName))
// Create VDI for the image
2020-09-13 03:21:07 -05:00
srs, err := c.client.SR.GetAll(c.session)
ui.Say(fmt.Sprintf("Step: Found SRs '%v'", srs))
// TODO (ddelnano): This must be changed to match the ISO Storage repository available
nameLabel := "LocalISO"
// nameLabel := "ISOs"
srs, err = c.client.SR.GetByNameLabel(c.session, nameLabel)
if len(srs) != 1 {
ui.Error(fmt.Sprintf("expected to find a single storage repository with name '%s', instead found '%d' storage repositories", nameLabel, len(srs)))
}
2020-09-13 03:21:07 -05:00
sr := srs[0]
ui.Say(fmt.Sprintf("Step: Found SRs '%v' Choosing: '%v'", srs, sr))
if err != nil {
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
return multistep.ActionHalt
}
2014-12-31 09:21:54 -06:00
// Open the file for reading (NB: HTTPUpload closes the file for us)
fh, err := os.Open(imagePath)
if err != nil {
ui.Error(fmt.Sprintf("Unable to open disk image '%s': %s", imagePath, err.Error()))
return multistep.ActionHalt
}
// Get file length
fstat, err := fh.Stat()
if err != nil {
ui.Error(fmt.Sprintf("Unable to stat disk image '%s': %s", imagePath, err.Error()))
return multistep.ActionHalt
}
fileLength := fstat.Size()
// Create the VDI
2020-09-13 03:21:07 -05:00
// vdi, err := sr.CreateVdi(vdiName, fileLength)
vdi, err := c.client.VDI.Create(c.session, xenapi.VDIRecord{
NameLabel: vdiName,
VirtualSize: int(fileLength),
Type: "user",
Sharable: false,
ReadOnly: false,
SR: sr,
OtherConfig: map[string]string{
"temp": "temp",
},
})
if err != nil {
ui.Error(fmt.Sprintf("Unable to create VDI '%s': %s", vdiName, err.Error()))
return multistep.ActionHalt
}
2020-09-13 03:21:07 -05:00
vdiUuid, err := c.client.VDI.GetUUID(c.session, vdi)
if err != nil {
ui.Error(fmt.Sprintf("Unable to get UUID of VDI '%s': %s", vdiName, err.Error()))
return multistep.ActionHalt
}
state.Put(self.VdiUuidKey, vdiUuid)
2014-12-31 09:21:54 -06:00
_, err = HTTPUpload(fmt.Sprintf("https://%s/import_raw_vdi?vdi=%s&session_id=%s",
2020-09-13 03:21:07 -05:00
c.Host,
vdi,
c.GetSession(),
2014-12-31 09:21:15 -06:00
), fh, state)
if err != nil {
2014-12-31 09:21:15 -06:00
ui.Error(fmt.Sprintf("Unable to upload VDI: %s", err.Error()))
return multistep.ActionHalt
}
return multistep.ActionContinue
}
func (self *StepUploadVdi) Cleanup(state multistep.StateBag) {
config := state.Get("commonconfig").(CommonConfig)
ui := state.Get("ui").(packer.Ui)
2020-09-13 03:21:07 -05:00
c := state.Get("client").(*Connection)
vdiName := self.VdiNameFunc()
if config.ShouldKeepVM(state) {
return
}
vdiUuidRaw, ok := state.GetOk(self.VdiUuidKey)
if !ok {
// VDI doesn't exist
return
}
vdiUuid := vdiUuidRaw.(string)
if vdiUuid == "" {
// VDI already cleaned up
return
}
2020-09-13 03:21:07 -05:00
vdi, err := c.client.VDI.GetByUUID(c.session, vdiUuid)
if err != nil {
ui.Error(fmt.Sprintf("Can't get VDI '%s': %s", vdiUuid, err.Error()))
return
}
// an interrupted import_raw_vdi takes a while to release the VDI
// so try several times
for i := 0; i < 3; i++ {
log.Printf("Trying to destroy VDI...")
2020-09-13 03:21:07 -05:00
err = c.client.VDI.Destroy(c.session, vdi)
if err == nil {
break
}
time.Sleep(1 * time.Second)
}
if err != nil {
ui.Error(fmt.Sprintf("Can't destroy VDI '%s': %s", vdiUuid, err.Error()))
return
}
ui.Say(fmt.Sprintf("Destroyed VDI '%s'", vdiName))
state.Put(self.VdiUuidKey, "")
}