packer-plugin-xenserver/builder/xenserver/iso/step_create_instance.go

246 lines
7.3 KiB
Go
Raw Normal View History

package iso
import (
2021-01-03 16:08:24 -06:00
"context"
2014-12-08 09:34:48 -06:00
"fmt"
"log"
"github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer-plugin-sdk/packer"
2020-09-13 03:21:07 -05:00
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 {
2020-09-13 03:21:07 -05:00
instance *xsclient.VMRef
vdi *xsclient.VDIRef
}
2021-01-03 16:08:24 -06:00
func (self *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
2020-09-13 03:21:07 -05:00
c := state.Get("client").(*xscommon.Connection)
config := state.Get("config").(xscommon.Config)
2014-12-08 09:34:48 -06:00
ui := state.Get("ui").(packer.Ui)
2014-12-08 09:34:48 -06:00
ui.Say("Step: Create Instance")
2014-12-08 09:34:48 -06:00
// Get the template to clone from
2020-09-13 03:21:07 -05:00
vms, err := c.GetClient().VM.GetByNameLabel(c.GetSessionRef(), config.CloneTemplate)
2014-12-08 09:34:48 -06:00
switch {
case len(vms) == 0:
ui.Error(fmt.Sprintf("Couldn't find a template with the name-label '%s'. Aborting.", config.CloneTemplate))
2014-12-08 09:34:48 -06:00
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))
2014-12-08 09:34:48 -06:00
return multistep.ActionHalt
}
2014-12-08 09:34:48 -06:00
template := vms[0]
2014-12-08 09:34:48 -06:00
// Clone that VM template
2020-09-13 03:21:07 -05:00
instance, err := c.GetClient().VM.Clone(c.GetSessionRef(), template, config.VMName)
2014-12-09 08:02:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Error cloning VM: %s", err.Error()))
return multistep.ActionHalt
}
2020-09-13 03:21:07 -05:00
self.instance = &instance
2014-12-09 08:02:48 -06:00
2020-09-13 03:21:07 -05:00
err = c.GetClient().VM.SetIsATemplate(c.GetSessionRef(), instance, false)
2014-12-09 08:02:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Error setting is_a_template=false: %s", err.Error()))
return multistep.ActionHalt
}
2020-09-13 03:21:07 -05:00
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
}
2020-09-13 03:21:07 -05:00
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
}
2014-12-09 08:02:48 -06:00
2020-09-13 03:21:07 -05:00
err = c.GetClient().VM.SetPlatform(c.GetSessionRef(), instance, config.PlatformArgs)
2014-12-09 08:02:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Error setting VM platform: %s", err.Error()))
return multistep.ActionHalt
}
2020-09-13 03:21:07 -05:00
err = c.GetClient().VM.SetNameDescription(c.GetSessionRef(), instance, config.VMDescription)
2015-05-01 19:45:43 -05:00
if err != nil {
ui.Error(fmt.Sprintf("Error setting VM description: %s", err.Error()))
return multistep.ActionHalt
}
if len(config.VMOtherConfig) != 0 {
2020-09-13 03:21:07 -05:00
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
}
2020-09-13 03:21:07 -05:00
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
}
}
2014-12-08 09:34:48 -06:00
// Create VDI for the instance
sr, err := config.GetSR(c)
2014-12-15 08:17:20 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Unable to get SR: %s", err.Error()))
return multistep.ActionHalt
2014-12-08 09:34:48 -06:00
}
ui.Say(fmt.Sprintf("Using the following SR for the VM: %s", sr))
2020-09-13 03:21:07 -05:00
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,
2020-09-13 03:21:07 -05:00
OtherConfig: map[string]string{
"temp": "temp",
},
})
2014-12-09 08:02:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Unable to create packer disk VDI: %s", err.Error()))
return multistep.ActionHalt
}
2020-09-13 03:21:07 -05:00
self.vdi = &vdi
2020-09-13 03:21:07 -05:00
err = xscommon.ConnectVdi(c, instance, vdi, xsclient.VbdTypeDisk)
2014-12-09 08:02:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Unable to connect packer disk VDI: %s", err.Error()))
return multistep.ActionHalt
}
2014-12-08 09:34:48 -06:00
// Connect Network
2020-09-13 03:21:07 -05:00
var network xsclient.NetworkRef
if len(config.NetworkNames) == 0 {
2014-12-08 09:34:48 -06:00
// No network has be specified. Use the management interface
log.Println("No network name given, attempting to use management interface")
2020-09-13 03:21:07 -05:00
pifs, err := c.GetClient().PIF.GetAll(c.GetSessionRef())
2014-12-08 09:34:48 -06:00
if err != nil {
2014-12-09 08:02:48 -06:00
ui.Error(fmt.Sprintf("Error getting PIFs: %s", err.Error()))
2014-12-08 09:34:48 -06:00
return multistep.ActionHalt
}
2014-12-08 09:34:48 -06:00
for _, pif := range pifs {
2020-09-13 03:21:07 -05:00
pif_rec, err := c.GetClient().PIF.GetRecord(c.GetSessionRef(), pif)
2014-12-08 09:34:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Error getting PIF record: %s", err.Error()))
2014-12-08 09:34:48 -06:00
return multistep.ActionHalt
}
2020-09-13 03:21:07 -05:00
if pif_rec.Management {
network = pif_rec.Network
2014-12-08 09:34:48 -06:00
}
2014-12-08 09:34:48 -06:00
}
2020-09-13 03:21:07 -05:00
if string(network) == "" {
ui.Error("Error: couldn't find management network. Aborting.")
2014-12-08 09:34:48 -06:00
return multistep.ActionHalt
}
log.Printf("Creating VIF on network '%s' on VM '%s'\n", network, instance)
2020-09-13 03:21:07 -05:00
_, err = xscommon.ConnectNetwork(c, network, instance, "0")
2014-12-08 09:34:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Failed to create VIF with error: %v", err))
return multistep.ActionHalt
2014-12-08 09:34:48 -06:00
}
} else {
log.Printf("Using provided network names: %v\n", config.NetworkNames)
// Look up each network by it's name label
for i, networkNameLabel := range config.NetworkNames {
2020-09-13 03:21:07 -05:00
networks, err := c.GetClient().Network.GetByNameLabel(c.GetSessionRef(), networkNameLabel)
2014-12-08 09:34:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Error occured getting Network by name-label: %s", err.Error()))
return multistep.ActionHalt
}
2014-12-08 09:34:48 -06:00
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
}
2014-12-08 09:34:48 -06:00
//we need the VIF index string
vifIndexString := fmt.Sprintf("%d", i)
2020-09-13 03:21:07 -05:00
_, err = xscommon.ConnectNetwork(c, networks[0], instance, vifIndexString)
if err != nil {
2020-09-13 03:21:07 -05:00
ui.Say(fmt.Sprintf("Failed to connect VIF with error: %v", err.Error()))
}
}
2014-12-08 09:34:48 -06:00
}
2020-09-13 03:21:07 -05:00
instanceId, err := c.GetClient().VM.GetUUID(c.GetSessionRef(), instance)
2014-12-09 08:02:48 -06:00
if err != nil {
ui.Error(fmt.Sprintf("Unable to get VM UUID: %s", err.Error()))
return multistep.ActionHalt
}
2014-12-09 10:40:32 -06:00
state.Put("instance_uuid", instanceId)
ui.Say(fmt.Sprintf("Created instance '%s'", instanceId))
2014-12-08 09:34:48 -06:00
return multistep.ActionContinue
}
func (self *stepCreateInstance) Cleanup(state multistep.StateBag) {
config := state.Get("config").(xscommon.Config)
if config.ShouldKeepVM(state) {
return
}
2014-12-09 10:40:32 -06:00
ui := state.Get("ui").(packer.Ui)
2020-09-13 03:21:07 -05:00
c := state.Get("client").(*xscommon.Connection)
2014-12-09 10:40:32 -06:00
if self.instance != nil {
ui.Say("Destroying VM")
2020-09-13 03:21:07 -05:00
_ = c.GetClient().VM.HardShutdown(c.GetSessionRef(), *self.instance) // redundant, just in case
err := c.GetClient().VM.Destroy(c.GetSessionRef(), *self.instance)
2014-12-09 10:40:32 -06:00
if err != nil {
ui.Error(err.Error())
}
2014-12-08 09:34:48 -06:00
}
2014-12-09 10:40:32 -06:00
if self.vdi != nil {
ui.Say("Destroying VDI")
2020-09-13 03:21:07 -05:00
err := c.GetClient().VDI.Destroy(c.GetSessionRef(), *self.vdi)
2014-12-09 10:40:32 -06:00
if err != nil {
ui.Error(err.Error())
}
}
}