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
74cfea407d
@ -28,9 +28,9 @@ type config struct {
|
||||
InstanceName string `mapstructure:"instance_name"`
|
||||
RootDiskSize string `mapstructure:"root_disk_size"`
|
||||
CloneTemplate string `mapstructure:"clone_template"`
|
||||
IsoUuid string `mapstructure:"iso_uuid"`
|
||||
SrUuid string `mapstructure:"sr_uuid"`
|
||||
NetworkUuid string `mapstructure:"network_uuid"`
|
||||
IsoName string `mapstructure:"iso_name"`
|
||||
SrName string `mapstructure:"sr_name"`
|
||||
NetworkName string `mapstructure:"network_name"`
|
||||
|
||||
HostPortMin uint `mapstructure:"host_port_min"`
|
||||
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,
|
||||
"root_disk_size": &self.config.RootDiskSize,
|
||||
"clone_template": &self.config.CloneTemplate,
|
||||
"iso_uuid": &self.config.IsoUuid,
|
||||
"sr_uuid": &self.config.SrUuid,
|
||||
"network_uuid": &self.config.NetworkUuid,
|
||||
"iso_name": &self.config.IsoName,
|
||||
"sr_name": &self.config.SrName,
|
||||
"network_name": &self.config.NetworkName,
|
||||
"boot_wait": &self.config.RawBootWait,
|
||||
"iso_checksum": &self.config.ISOChecksum,
|
||||
"iso_checksum_type": &self.config.ISOChecksumType,
|
||||
@ -218,29 +218,15 @@ func (self *Builder) Prepare (raws ...interface{}) (params []string, retErr erro
|
||||
}
|
||||
|
||||
if self.config.CloneTemplate == "" {
|
||||
errs = packer.MultiErrorAppend(
|
||||
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."))
|
||||
self.config.CloneTemplate = "Other install media"
|
||||
}
|
||||
|
||||
/*
|
||||
if self.config.LocalIp == "" {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, errors.New("A local IP visible to XenServer's mangement interface is required to serve files."))
|
||||
}
|
||||
*/
|
||||
|
||||
if len(self.config.PlatformArgs) == 0 {
|
||||
pargs := make(map[string]string)
|
||||
|
@ -60,6 +60,16 @@ type VIF struct {
|
||||
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) {
|
||||
fmt.Println(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) {
|
||||
vm = new(VM)
|
||||
result := APIResult{}
|
||||
@ -141,6 +195,44 @@ func (client *XenAPIClient) GetVMByUuid (vm_uuid string) (vm *VM, err error) {
|
||||
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) {
|
||||
network = new(Network)
|
||||
result := APIResult{}
|
||||
@ -172,6 +264,24 @@ func (client *XenAPIClient) GetNetworkByNameLabel (name_label string) (networks
|
||||
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) {
|
||||
sr = new(SR)
|
||||
@ -197,6 +307,22 @@ func (client *XenAPIClient) GetVdiByUuid (vdi_uuid string) (vdi *VDI, err error)
|
||||
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
|
||||
|
||||
@ -532,6 +658,37 @@ func (self *Network) GetAssignedIPs () (ip_map map[string]string, err error) {
|
||||
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
|
||||
func (self *VBD) GetRecord () (record map[string]interface{}, err error) {
|
||||
record = make(map[string]interface{})
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
type stepCreateInstance struct {
|
||||
@ -21,7 +22,19 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||
|
||||
|
||||
// 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
|
||||
instance, _ := template.Clone(config.InstanceName)
|
||||
@ -30,13 +43,102 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||
instance.SetPlatform(config.PlatformArgs)
|
||||
|
||||
// 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)
|
||||
|
||||
instance.ConnectVdi(vdi, false)
|
||||
|
||||
// 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 {
|
||||
ui.Say(err.Error())
|
||||
}
|
||||
@ -49,7 +151,22 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
||||
// Connect the ISO
|
||||
//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)
|
||||
//iso, _ := client.GetVdiByUuid(iso_vdi_uuid)
|
||||
instance.ConnectVdi(iso, true)
|
||||
|
@ -37,7 +37,9 @@ func (self *stepUploadIso) Run(state multistep.StateBag) multistep.StepAction {
|
||||
iso_filesize := stat.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 {
|
||||
ui.Error(err.Error())
|
||||
|
Loading…
Reference in New Issue
Block a user