239 lines
6.9 KiB
Go
239 lines
6.9 KiB
Go
package iso
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/mitchellh/multistep"
|
|
"github.com/mitchellh/packer/packer"
|
|
xenapi "github.com/terra-farm/go-xen-api-client"
|
|
xsclient "github.com/terra-farm/go-xen-api-client"
|
|
xscommon "github.com/xenserver/packer-builder-xenserver/builder/xenserver/common"
|
|
)
|
|
|
|
type stepCreateInstance struct {
|
|
instance *xsclient.VMRef
|
|
vdi *xsclient.VDIRef
|
|
}
|
|
|
|
func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction {
|
|
|
|
c := state.Get("client").(*xscommon.Connection)
|
|
config := state.Get("config").(config)
|
|
ui := state.Get("ui").(packer.Ui)
|
|
|
|
ui.Say("Step: Create Instance")
|
|
|
|
// Get the template to clone from
|
|
|
|
vms, err := c.GetClient().VM.GetByNameLabel(c.GetSessionRef(), config.CloneTemplate)
|
|
|
|
switch {
|
|
case len(vms) == 0:
|
|
ui.Error(fmt.Sprintf("Couldn't find a template with the name-label '%s'. Aborting.", config.CloneTemplate))
|
|
return multistep.ActionHalt
|
|
case len(vms) > 1:
|
|
ui.Error(fmt.Sprintf("Found more than one template with the name '%s'. The name must be unique. Aborting.", config.CloneTemplate))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
template := vms[0]
|
|
|
|
// Clone that VM template
|
|
instance, err := c.GetClient().VM.Clone(c.GetSessionRef(), template, config.VMName)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error cloning VM: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
self.instance = &instance
|
|
|
|
err = c.GetClient().VM.SetIsATemplate(c.GetSessionRef(), instance, false)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error setting is_a_template=false: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
err = c.GetClient().VM.SetVCPUsMax(c.GetSessionRef(), instance, int(config.VCPUsMax))
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error setting VM VCPUs Max=%d: %s", config.VCPUsMax, err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
err = c.GetClient().VM.SetVCPUsAtStartup(c.GetSessionRef(), instance, int(config.VCPUsAtStartup))
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error setting VM VCPUs At Startup=%d: %s", config.VCPUsAtStartup, err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
memory := int(config.VMMemory * 1024 * 1024)
|
|
err = c.GetClient().VM.SetMemoryLimits(c.GetSessionRef(), instance, memory, memory, memory, memory)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error setting VM memory=%d: %s", memory, err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
err = c.GetClient().VM.SetPlatform(c.GetSessionRef(), instance, config.PlatformArgs)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error setting VM platform: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
err = c.GetClient().VM.SetNameDescription(c.GetSessionRef(), instance, config.VMDescription)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error setting VM description: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
if len(config.VMOtherConfig) != 0 {
|
|
vm_other_config, err := c.GetClient().VM.GetOtherConfig(c.GetSessionRef(), instance)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error getting VM other-config: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
for key, value := range config.VMOtherConfig {
|
|
vm_other_config[key] = value
|
|
}
|
|
err = c.GetClient().VM.SetOtherConfig(c.GetSessionRef(), instance, vm_other_config)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error setting VM other-config: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
}
|
|
|
|
// Create VDI for the instance
|
|
|
|
srs, err := c.GetClient().SR.GetByNameLabel(c.GetSessionRef(), "Local storage")
|
|
sr := srs[0]
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
vdi, err := c.GetClient().VDI.Create(c.GetSessionRef(), xenapi.VDIRecord{
|
|
NameLabel: "Packer-disk",
|
|
VirtualSize: int(config.DiskSize * 1024 * 1024),
|
|
Type: "user",
|
|
Sharable: false,
|
|
ReadOnly: false,
|
|
SR: sr,
|
|
OtherConfig: map[string]string{
|
|
"temp": "temp",
|
|
},
|
|
})
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Unable to create packer disk VDI: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
self.vdi = &vdi
|
|
|
|
err = xscommon.ConnectVdi(c, instance, vdi, xsclient.VbdTypeDisk)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Unable to connect packer disk VDI: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
// Connect Network
|
|
|
|
var network xsclient.NetworkRef
|
|
|
|
if len(config.NetworkNames) == 0 {
|
|
// No network has be specified. Use the management interface
|
|
pifs, err := c.GetClient().PIF.GetAll(c.GetSessionRef())
|
|
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error getting PIFs: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
for _, pif := range pifs {
|
|
pif_rec, err := c.GetClient().PIF.GetRecord(c.GetSessionRef(), pif)
|
|
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error getting PIF record: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
if pif_rec.Management {
|
|
network = pif_rec.Network
|
|
}
|
|
|
|
}
|
|
|
|
if string(network) == "" {
|
|
ui.Error("Error: couldn't find management network. Aborting.")
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
_, err = xscommon.ConnectNetwork(c, network, instance, "0")
|
|
|
|
if err != nil {
|
|
ui.Say(err.Error())
|
|
}
|
|
|
|
} else {
|
|
// Look up each network by it's name label
|
|
for i, networkNameLabel := range config.NetworkNames {
|
|
networks, err := c.GetClient().Network.GetByNameLabel(c.GetSessionRef(), networkNameLabel)
|
|
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Error occured getting Network by name-label: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
switch {
|
|
case len(networks) == 0:
|
|
ui.Error(fmt.Sprintf("Couldn't find a network with the specified name-label '%s'. Aborting.", networkNameLabel))
|
|
return multistep.ActionHalt
|
|
case len(networks) > 1:
|
|
ui.Error(fmt.Sprintf("Found more than one network with the name '%s'. The name must be unique. Aborting.", networkNameLabel))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
//we need the VIF index string
|
|
vifIndexString := fmt.Sprintf("%d", i)
|
|
_, err = xscommon.ConnectNetwork(c, networks[0], instance, vifIndexString)
|
|
|
|
if err != nil {
|
|
ui.Say(fmt.Sprintf("Failed to connect VIF with error: %v", err.Error()))
|
|
}
|
|
}
|
|
}
|
|
|
|
instanceId, err := c.GetClient().VM.GetUUID(c.GetSessionRef(), instance)
|
|
if err != nil {
|
|
ui.Error(fmt.Sprintf("Unable to get VM UUID: %s", err.Error()))
|
|
return multistep.ActionHalt
|
|
}
|
|
|
|
state.Put("instance_uuid", instanceId)
|
|
ui.Say(fmt.Sprintf("Created instance '%s'", instanceId))
|
|
|
|
return multistep.ActionContinue
|
|
}
|
|
|
|
func (self *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
|
config := state.Get("config").(config)
|
|
if config.ShouldKeepVM(state) {
|
|
return
|
|
}
|
|
|
|
ui := state.Get("ui").(packer.Ui)
|
|
c := state.Get("client").(*xscommon.Connection)
|
|
|
|
if self.instance != nil {
|
|
ui.Say("Destroying VM")
|
|
_ = c.GetClient().VM.HardShutdown(c.GetSessionRef(), *self.instance) // redundant, just in case
|
|
err := c.GetClient().VM.Destroy(c.GetSessionRef(), *self.instance)
|
|
if err != nil {
|
|
ui.Error(err.Error())
|
|
}
|
|
}
|
|
|
|
if self.vdi != nil {
|
|
ui.Say("Destroying VDI")
|
|
err := c.GetClient().VDI.Destroy(c.GetSessionRef(), *self.vdi)
|
|
if err != nil {
|
|
ui.Error(err.Error())
|
|
}
|
|
}
|
|
}
|