Adding defaults for Clone template, Network and Storage to avoid having to configure it in the packer file.
Signed-off-by: Rob Dobson <rob.dobson@citrix.com>
This commit is contained in:
parent
4746a397be
commit
4dd435dafe
@ -28,9 +28,9 @@ type config struct {
|
|||||||
InstanceName string `mapstructure:"instance_name"`
|
InstanceName string `mapstructure:"instance_name"`
|
||||||
RootDiskSize string `mapstructure:"root_disk_size"`
|
RootDiskSize string `mapstructure:"root_disk_size"`
|
||||||
CloneTemplate string `mapstructure:"clone_template"`
|
CloneTemplate string `mapstructure:"clone_template"`
|
||||||
IsoUuid string `mapstructure:"iso_uuid"`
|
IsoName string `mapstructure:"iso_name"`
|
||||||
SrUuid string `mapstructure:"sr_uuid"`
|
SrName string `mapstructure:"sr_name"`
|
||||||
NetworkUuid string `mapstructure:"network_uuid"`
|
NetworkName string `mapstructure:"network_name"`
|
||||||
|
|
||||||
HostPortMin uint `mapstructure:"host_port_min"`
|
HostPortMin uint `mapstructure:"host_port_min"`
|
||||||
HostPortMax uint `mapstructure:"host_port_max"`
|
HostPortMax uint `mapstructure:"host_port_max"`
|
||||||
@ -127,9 +127,9 @@ func (self *Builder) Prepare (raws ...interface{}) (params []string, retErr erro
|
|||||||
"instance_name": &self.config.InstanceName,
|
"instance_name": &self.config.InstanceName,
|
||||||
"root_disk_size": &self.config.RootDiskSize,
|
"root_disk_size": &self.config.RootDiskSize,
|
||||||
"clone_template": &self.config.CloneTemplate,
|
"clone_template": &self.config.CloneTemplate,
|
||||||
"iso_uuid": &self.config.IsoUuid,
|
"iso_name": &self.config.IsoName,
|
||||||
"sr_uuid": &self.config.SrUuid,
|
"sr_name": &self.config.SrName,
|
||||||
"network_uuid": &self.config.NetworkUuid,
|
"network_name": &self.config.NetworkName,
|
||||||
"boot_wait": &self.config.RawBootWait,
|
"boot_wait": &self.config.RawBootWait,
|
||||||
"iso_checksum": &self.config.ISOChecksum,
|
"iso_checksum": &self.config.ISOChecksum,
|
||||||
"iso_checksum_type": &self.config.ISOChecksumType,
|
"iso_checksum_type": &self.config.ISOChecksumType,
|
||||||
@ -218,29 +218,15 @@ func (self *Builder) Prepare (raws ...interface{}) (params []string, retErr erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.config.CloneTemplate == "" {
|
if self.config.CloneTemplate == "" {
|
||||||
errs = packer.MultiErrorAppend(
|
self.config.CloneTemplate = "Other install media"
|
||||||
errs, errors.New("A template to clone from must be specified."))
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.config.IsoUuid == "" {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, errors.New("a uuid for the installation iso must be specified."))
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.config.SrUuid == "" {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, errors.New("a uuid for the sr used for the instance must be specified."))
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.config.NetworkUuid == "" {
|
|
||||||
errs = packer.MultiErrorAppend(
|
|
||||||
errs, errors.New("a uuid for the network used for the instance must be specified."))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if self.config.LocalIp == "" {
|
if self.config.LocalIp == "" {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
errs, errors.New("A local IP visible to XenServer's mangement interface is required to serve files."))
|
errs, errors.New("A local IP visible to XenServer's mangement interface is required to serve files."))
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if len(self.config.PlatformArgs) == 0 {
|
if len(self.config.PlatformArgs) == 0 {
|
||||||
pargs := make(map[string]string)
|
pargs := make(map[string]string)
|
||||||
|
@ -60,6 +60,16 @@ type VIF struct {
|
|||||||
Client *XenAPIClient
|
Client *XenAPIClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PIF struct {
|
||||||
|
Ref string
|
||||||
|
Client *XenAPIClient
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pool struct {
|
||||||
|
Ref string
|
||||||
|
Client *XenAPIClient
|
||||||
|
}
|
||||||
|
|
||||||
func (c *XenAPIClient) RPCCall (result interface{}, method string, params []interface{}) (err error) {
|
func (c *XenAPIClient) RPCCall (result interface{}, method string, params []interface{}) (err error) {
|
||||||
fmt.Println(params)
|
fmt.Println(params)
|
||||||
p := new(xmlrpc.Params)
|
p := new(xmlrpc.Params)
|
||||||
@ -129,6 +139,50 @@ func (client *XenAPIClient) GetHosts () (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (client *XenAPIClient) GetPools () (pools []*Pool, err error) {
|
||||||
|
pools = make([]*Pool, 0)
|
||||||
|
result := APIResult{}
|
||||||
|
err = client.APICall(&result, "pool.get_all")
|
||||||
|
if err != nil {
|
||||||
|
return pools, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, elem := range result.Value.([]interface{}) {
|
||||||
|
pool := new(Pool)
|
||||||
|
pool.Ref = elem.(string)
|
||||||
|
pool.Client = client
|
||||||
|
pools = append(pools, pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pools, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (client *XenAPIClient) GetDefaultSR () (sr *SR, err error) {
|
||||||
|
pools, err := client.GetPools()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
pool_rec, err := pools[0].GetRecord()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if pool_rec["default_SR"] == "" {
|
||||||
|
return nil, errors.New("No default_SR specified for the pool.")
|
||||||
|
}
|
||||||
|
|
||||||
|
sr = new(SR)
|
||||||
|
sr.Ref = pool_rec["default_SR"].(string)
|
||||||
|
sr.Client = client
|
||||||
|
|
||||||
|
return sr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (client *XenAPIClient) GetVMByUuid (vm_uuid string) (vm *VM, err error) {
|
func (client *XenAPIClient) GetVMByUuid (vm_uuid string) (vm *VM, err error) {
|
||||||
vm = new(VM)
|
vm = new(VM)
|
||||||
result := APIResult{}
|
result := APIResult{}
|
||||||
@ -141,6 +195,44 @@ func (client *XenAPIClient) GetVMByUuid (vm_uuid string) (vm *VM, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (client *XenAPIClient) GetVMByNameLabel (name_label string) (vms []*VM, err error) {
|
||||||
|
vms = make([]*VM, 0)
|
||||||
|
result := APIResult{}
|
||||||
|
err = client.APICall(&result, "VM.get_by_name_label", name_label)
|
||||||
|
if err != nil {
|
||||||
|
return vms, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, elem := range result.Value.([]interface{}) {
|
||||||
|
vm := new(VM)
|
||||||
|
vm.Ref = elem.(string)
|
||||||
|
vm.Client = client
|
||||||
|
vms = append(vms, vm)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vms, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func (client *XenAPIClient) GetSRByNameLabel (name_label string) (srs []*SR, err error) {
|
||||||
|
srs = make([]*SR, 0)
|
||||||
|
result := APIResult{}
|
||||||
|
err = client.APICall(&result, "SR.get_by_name_label", name_label)
|
||||||
|
if err != nil {
|
||||||
|
return srs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, elem := range result.Value.([]interface{}) {
|
||||||
|
sr := new(SR)
|
||||||
|
sr.Ref = elem.(string)
|
||||||
|
sr.Client = client
|
||||||
|
srs = append(srs, sr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return srs, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (client *XenAPIClient) GetNetworkByUuid (network_uuid string) (network *Network, err error) {
|
func (client *XenAPIClient) GetNetworkByUuid (network_uuid string) (network *Network, err error) {
|
||||||
network = new(Network)
|
network = new(Network)
|
||||||
result := APIResult{}
|
result := APIResult{}
|
||||||
@ -172,6 +264,24 @@ func (client *XenAPIClient) GetNetworkByNameLabel (name_label string) (networks
|
|||||||
return networks, nil
|
return networks, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *XenAPIClient) GetVdiByNameLabel (name_label string) (vdis []*VDI, err error) {
|
||||||
|
vdis = make([]*VDI, 0)
|
||||||
|
result := APIResult{}
|
||||||
|
err = client.APICall(&result, "VDI.get_by_name_label", name_label)
|
||||||
|
if err != nil {
|
||||||
|
return vdis, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, elem := range result.Value.([]interface{}) {
|
||||||
|
vdi := new(VDI)
|
||||||
|
vdi.Ref = elem.(string)
|
||||||
|
vdi.Client = client
|
||||||
|
vdis = append(vdis, vdi)
|
||||||
|
}
|
||||||
|
|
||||||
|
return vdis, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (client *XenAPIClient) GetSRByUuid (sr_uuid string) (sr *SR, err error) {
|
func (client *XenAPIClient) GetSRByUuid (sr_uuid string) (sr *SR, err error) {
|
||||||
sr = new(SR)
|
sr = new(SR)
|
||||||
@ -197,6 +307,22 @@ func (client *XenAPIClient) GetVdiByUuid (vdi_uuid string) (vdi *VDI, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *XenAPIClient) GetPIFs() (pifs []*PIF, err error) {
|
||||||
|
pifs = make([]*PIF, 0)
|
||||||
|
result := APIResult{}
|
||||||
|
err = client.APICall(&result, "PIF.get_all")
|
||||||
|
if err != nil {
|
||||||
|
return pifs, err
|
||||||
|
}
|
||||||
|
for _, elem := range result.Value.([]interface{}) {
|
||||||
|
pif := new(PIF)
|
||||||
|
pif.Ref = elem.(string)
|
||||||
|
pif.Client = client
|
||||||
|
pifs = append(pifs, pif)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pifs, nil
|
||||||
|
}
|
||||||
|
|
||||||
// VM associated functions
|
// VM associated functions
|
||||||
|
|
||||||
@ -532,6 +658,37 @@ func (self *Network) GetAssignedIPs () (ip_map map[string]string, err error) {
|
|||||||
return ip_map, nil
|
return ip_map, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PIF associated functions
|
||||||
|
|
||||||
|
func (self *PIF) GetRecord () (record map[string]interface{}, err error) {
|
||||||
|
record = make(map[string]interface{})
|
||||||
|
result := APIResult{}
|
||||||
|
err = self.Client.APICall(&result, "PIF.get_record", self.Ref)
|
||||||
|
if err != nil {
|
||||||
|
return record, err
|
||||||
|
}
|
||||||
|
for k, v := range result.Value.(xmlrpc.Struct) {
|
||||||
|
record[k] = v
|
||||||
|
}
|
||||||
|
return record, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pool associated functions
|
||||||
|
|
||||||
|
func (self *Pool) GetRecord () (record map[string]interface{}, err error) {
|
||||||
|
record = make(map[string]interface{})
|
||||||
|
result := APIResult{}
|
||||||
|
err = self.Client.APICall(&result, "pool.get_record", self.Ref)
|
||||||
|
if err != nil {
|
||||||
|
return record, err
|
||||||
|
}
|
||||||
|
for k, v := range result.Value.(xmlrpc.Struct) {
|
||||||
|
record[k] = v
|
||||||
|
}
|
||||||
|
return record, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// VBD associated functions
|
// VBD associated functions
|
||||||
func (self *VBD) GetRecord () (record map[string]interface{}, err error) {
|
func (self *VBD) GetRecord () (record map[string]interface{}, err error) {
|
||||||
record = make(map[string]interface{})
|
record = make(map[string]interface{})
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepCreateInstance struct {
|
type stepCreateInstance struct {
|
||||||
@ -21,7 +22,19 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
|
|
||||||
|
|
||||||
// Get the template to clone from
|
// Get the template to clone from
|
||||||
template, _ := client.GetVMByUuid(config.CloneTemplate)
|
|
||||||
|
vms, err := client.GetVMByNameLabel(config.CloneTemplate)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(vms) == 0:
|
||||||
|
log.Fatal(fmt.Sprintf("Couldn't find a template with the name-label '%s'. Aborting.", config.CloneTemplate))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
case len(vms) > 1:
|
||||||
|
log.Fatal(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
|
// Clone that VM template
|
||||||
instance, _ := template.Clone(config.InstanceName)
|
instance, _ := template.Clone(config.InstanceName)
|
||||||
@ -30,13 +43,102 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
instance.SetPlatform(config.PlatformArgs)
|
instance.SetPlatform(config.PlatformArgs)
|
||||||
|
|
||||||
// Create VDI for the instance
|
// Create VDI for the instance
|
||||||
sr, _ := client.GetSRByUuid(config.SrUuid)
|
var sr *SR
|
||||||
|
|
||||||
|
if config.SrName == "" {
|
||||||
|
// Find the default SR
|
||||||
|
default_sr, err := client.GetDefaultSR()
|
||||||
|
sr = default_sr
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Sprintf("Error getting default SR: %s", err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Use the provided name label to find the SR to use
|
||||||
|
srs, err := client.GetSRByNameLabel(config.SrName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Sprintf("Error getting default SR: %s", err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(srs) == 0:
|
||||||
|
log.Fatal(fmt.Sprintf("Couldn't find a SR with the specified name-label '%s'. Aborting.", config.SrName))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
case len(srs) > 1:
|
||||||
|
log.Fatal(fmt.Sprintf("Found more than one SR with the name '%s'. The name must be unique. Aborting.", config.SrName))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
sr = srs[0]
|
||||||
|
}
|
||||||
|
|
||||||
vdi, _ := sr.CreateVdi("Packer-disk", config.RootDiskSize)
|
vdi, _ := sr.CreateVdi("Packer-disk", config.RootDiskSize)
|
||||||
|
|
||||||
instance.ConnectVdi(vdi, false)
|
instance.ConnectVdi(vdi, false)
|
||||||
|
|
||||||
// Connect Network
|
// Connect Network
|
||||||
network, err := client.GetNetworkByUuid(config.NetworkUuid)
|
|
||||||
|
var network *Network
|
||||||
|
|
||||||
|
if config.NetworkName == "" {
|
||||||
|
// No network has be specified. Use the management interface
|
||||||
|
network = new(Network)
|
||||||
|
network.Ref = ""
|
||||||
|
network.Client = &client
|
||||||
|
|
||||||
|
pifs, err := client.GetPIFs()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Sprintf("Error getting PIFs %s", err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pif := range pifs {
|
||||||
|
pif_rec, err := pif.GetRecord()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Sprintf("Error getting PIF record: %s", err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
if pif_rec["management"].(bool) {
|
||||||
|
network.Ref = pif_rec["network"].(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if network.Ref == "" {
|
||||||
|
log.Fatal("Error: couldn't find management network. Aborting.")
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Look up the network by it's name label
|
||||||
|
|
||||||
|
networks, err := client.GetNetworkByNameLabel(config.NetworkName)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Sprintf("Error occured getting Network by name-label: %s", err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(networks) == 0:
|
||||||
|
log.Fatal(fmt.Sprintf("Couldn't find a network with the specified name-label '%s'. Aborting.", config.NetworkName))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
case len(networks) > 1:
|
||||||
|
log.Fatal(fmt.Sprintf("Found more than one SR with the name '%s'. The name must be unique. Aborting.", config.NetworkName))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
network = networks[0]
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Say(err.Error())
|
ui.Say(err.Error())
|
||||||
}
|
}
|
||||||
@ -49,7 +151,22 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
// Connect the ISO
|
// Connect the ISO
|
||||||
//iso_vdi_uuid := state.Get("iso_vdi_uuid").(string)
|
//iso_vdi_uuid := state.Get("iso_vdi_uuid").(string)
|
||||||
|
|
||||||
iso, _ := client.GetVdiByUuid(config.IsoUuid)
|
|
||||||
|
isos, err := client.GetVdiByNameLabel(config.IsoName)
|
||||||
|
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(isos) == 0:
|
||||||
|
log.Fatal(fmt.Sprintf("Couldn't find an ISO named '%s'. Aborting", config.IsoName))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
case len(isos) > 1:
|
||||||
|
log.Fatal(fmt.Sprintf("Found more than one VDI with name '%s'. Name must be unique. Aborting.", config.IsoName))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
iso := isos[0]
|
||||||
|
|
||||||
|
//iso, _ := client.GetVdiByUuid(config.IsoUuid)
|
||||||
//ui.Say("Using VDI: " + iso_vdi_uuid)
|
//ui.Say("Using VDI: " + iso_vdi_uuid)
|
||||||
//iso, _ := client.GetVdiByUuid(iso_vdi_uuid)
|
//iso, _ := client.GetVdiByUuid(iso_vdi_uuid)
|
||||||
instance.ConnectVdi(iso, true)
|
instance.ConnectVdi(iso, true)
|
||||||
|
@ -37,7 +37,9 @@ func (self *stepUploadIso) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
iso_filesize := stat.Size()
|
iso_filesize := stat.Size()
|
||||||
|
|
||||||
// Create a VDI with the write size
|
// Create a VDI with the write size
|
||||||
sr, err := client.GetSRByUuid(config.SrUuid)
|
srs, err := client.GetSRByNameLabel(config.SrName)
|
||||||
|
|
||||||
|
sr := srs[0]
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
|
Loading…
Reference in New Issue
Block a user