commit
85e3b00e5a
@ -61,7 +61,10 @@ type config struct {
|
|||||||
SSHUser string `mapstructure:"ssh_username"`
|
SSHUser string `mapstructure:"ssh_username"`
|
||||||
SSHKeyPath string `mapstructure:"ssh_key_path"`
|
SSHKeyPath string `mapstructure:"ssh_key_path"`
|
||||||
|
|
||||||
OutputDir string `mapstructure:"output_directory"`
|
OutputDir string `mapstructure:"output_directory"`
|
||||||
|
ExportFormat string `mapstructure:"export_format"`
|
||||||
|
|
||||||
|
KeepInstance string `mapstructure:"keep_instance"`
|
||||||
|
|
||||||
tpl *packer.ConfigTemplate
|
tpl *packer.ConfigTemplate
|
||||||
}
|
}
|
||||||
@ -84,12 +87,12 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.config.tpl, err = packer.NewConfigTemplate()
|
self.config.tpl, err = packer.NewConfigTemplate()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
self.config.tpl.UserVars = self.config.PackerUserVars
|
||||||
|
|
||||||
// Set default vaules
|
// Set default values
|
||||||
|
|
||||||
if self.config.HostPortMin == 0 {
|
if self.config.HostPortMin == 0 {
|
||||||
self.config.HostPortMin = 5900
|
self.config.HostPortMin = 5900
|
||||||
@ -119,10 +122,39 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
self.config.RawSSHWaitTimeout = "200m"
|
self.config.RawSSHWaitTimeout = "200m"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.config.InstanceMemory == "" {
|
||||||
|
self.config.InstanceMemory = "1024000000"
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.config.CloneTemplate == "" {
|
||||||
|
self.config.CloneTemplate = "Other install media"
|
||||||
|
}
|
||||||
|
|
||||||
if self.config.OutputDir == "" {
|
if self.config.OutputDir == "" {
|
||||||
self.config.OutputDir = fmt.Sprintf("output-%s", self.config.PackerBuildName)
|
self.config.OutputDir = fmt.Sprintf("output-%s", self.config.PackerBuildName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.config.ExportFormat == "" {
|
||||||
|
self.config.ExportFormat = "xva"
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.config.KeepInstance == "" {
|
||||||
|
self.config.KeepInstance = "never"
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(self.config.PlatformArgs) == 0 {
|
||||||
|
pargs := make(map[string]string)
|
||||||
|
pargs["viridian"] = "false"
|
||||||
|
pargs["nx"] = "true"
|
||||||
|
pargs["pae"] = "true"
|
||||||
|
pargs["apic"] = "true"
|
||||||
|
pargs["timeoffset"] = "0"
|
||||||
|
pargs["acpi"] = "1"
|
||||||
|
self.config.PlatformArgs = pargs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Template substitution
|
||||||
|
|
||||||
templates := map[string]*string{
|
templates := map[string]*string{
|
||||||
"username": &self.config.Username,
|
"username": &self.config.Username,
|
||||||
"password": &self.config.Password,
|
"password": &self.config.Password,
|
||||||
@ -146,6 +178,8 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
"ssh_password": &self.config.SSHPassword,
|
"ssh_password": &self.config.SSHPassword,
|
||||||
"ssh_key_path": &self.config.SSHKeyPath,
|
"ssh_key_path": &self.config.SSHKeyPath,
|
||||||
"output_directory": &self.config.OutputDir,
|
"output_directory": &self.config.OutputDir,
|
||||||
|
"export_format": &self.config.ExportFormat,
|
||||||
|
"keep_instance": &self.config.KeepInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
for n, ptr := range templates {
|
for n, ptr := range templates {
|
||||||
@ -156,6 +190,8 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validation
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if self.config.IsoUrl == "" {
|
if self.config.IsoUrl == "" {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
@ -166,7 +202,7 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
self.config.BootWait, err = time.ParseDuration(self.config.RawBootWait)
|
self.config.BootWait, err = time.ParseDuration(self.config.RawBootWait)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
errs, errors.New("Failed to parse boot_wait."))
|
errs, fmt.Errorf("Failed to parse boot_wait: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.config.SSHWaitTimeout, err = time.ParseDuration(self.config.RawSSHWaitTimeout)
|
self.config.SSHWaitTimeout, err = time.ParseDuration(self.config.RawSSHWaitTimeout)
|
||||||
@ -223,17 +259,23 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
errs, errors.New("An instance name must be specified."))
|
errs, errors.New("An instance name must be specified."))
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.config.InstanceMemory == "" {
|
|
||||||
self.config.InstanceMemory = "1024000000"
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.config.RootDiskSize == "" {
|
if self.config.RootDiskSize == "" {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
errs, errors.New("A root disk size must be specified."))
|
errs, errors.New("A root disk size must be specified."))
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.config.CloneTemplate == "" {
|
switch self.config.ExportFormat {
|
||||||
self.config.CloneTemplate = "Other install media"
|
case "xva", "vdi_raw":
|
||||||
|
default:
|
||||||
|
errs = packer.MultiErrorAppend(
|
||||||
|
errs, errors.New("export_format must be one of 'xva', 'vdi_raw'"))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch self.config.KeepInstance {
|
||||||
|
case "always", "never", "on_success":
|
||||||
|
default:
|
||||||
|
errs = packer.MultiErrorAppend(
|
||||||
|
errs, errors.New("keep_instance must be one of 'always', 'never', 'on_success'"))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -243,17 +285,6 @@ func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if len(self.config.PlatformArgs) == 0 {
|
|
||||||
pargs := make(map[string]string)
|
|
||||||
pargs["viridian"] = "false"
|
|
||||||
pargs["nx"] = "true"
|
|
||||||
pargs["pae"] = "true"
|
|
||||||
pargs["apic"] = "true"
|
|
||||||
pargs["timeoffset"] = "0"
|
|
||||||
pargs["acpi"] = "1"
|
|
||||||
self.config.PlatformArgs = pargs
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.config.HTTPPortMin > self.config.HTTPPortMax {
|
if self.config.HTTPPortMin > self.config.HTTPPortMax {
|
||||||
errs = packer.MultiErrorAppend(
|
errs = packer.MultiErrorAppend(
|
||||||
errs, errors.New("the HTTP min port must be less than the max"))
|
errs, errors.New("the HTTP min port must be less than the max"))
|
||||||
@ -392,6 +423,23 @@ func (self *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (pa
|
|||||||
return artifact, nil
|
return artifact, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all steps should check config.ShouldKeepInstance first before cleaning up
|
||||||
|
func (cfg config) ShouldKeepInstance(state multistep.StateBag) bool {
|
||||||
|
switch cfg.KeepInstance {
|
||||||
|
case "always":
|
||||||
|
return true
|
||||||
|
case "never":
|
||||||
|
return false
|
||||||
|
case "on_success":
|
||||||
|
// only keep instance if build was successful
|
||||||
|
_, cancelled := state.GetOk(multistep.StateCancelled)
|
||||||
|
_, halted := state.GetOk(multistep.StateHalted)
|
||||||
|
return !(cancelled || halted)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Unknown keep_instance value '%s'", cfg.KeepInstance))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Builder) Cancel() {
|
func (self *Builder) Cancel() {
|
||||||
if self.runner != nil {
|
if self.runner != nil {
|
||||||
log.Println("Cancelling the step runner...")
|
log.Println("Cancelling the step runner...")
|
||||||
|
25
builder/xenserver/find_port.go
Normal file
25
builder/xenserver/find_port.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package xenserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FindPort finds and starts listening on a port in the range [portMin, portMax]
|
||||||
|
// returns the listener and the port number on success, or nil, 0 on failure
|
||||||
|
func FindPort(portMin uint, portMax uint) (net.Listener, uint) {
|
||||||
|
log.Printf("Looking for an available port between %d and %d", portMin, portMax)
|
||||||
|
|
||||||
|
for port := portMin; port <= portMax; port++ {
|
||||||
|
log.Printf("Trying port: %d", port)
|
||||||
|
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||||
|
if err == nil {
|
||||||
|
return l, port
|
||||||
|
} else {
|
||||||
|
log.Printf("Port %d unavailable: %s", port, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, 0
|
||||||
|
}
|
@ -84,19 +84,22 @@ func execute_ssh_cmd(cmd, host, port, username, password string) (stdout string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func forward(local_conn net.Conn, config *gossh.ClientConfig, server, remote_dest string, remote_port uint) error {
|
func forward(local_conn net.Conn, config *gossh.ClientConfig, server, remote_dest string, remote_port uint) error {
|
||||||
|
defer local_conn.Close()
|
||||||
|
|
||||||
ssh_client_conn, err := gossh.Dial("tcp", server+":22", config)
|
ssh_client_conn, err := gossh.Dial("tcp", server+":22", config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("local ssh.Dial error: %s", err)
|
log.Printf("local ssh.Dial error: %s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer ssh_client_conn.Close()
|
||||||
|
|
||||||
remote_loc := fmt.Sprintf("%s:%d", remote_dest, remote_port)
|
remote_loc := fmt.Sprintf("%s:%d", remote_dest, remote_port)
|
||||||
ssh_conn, err := ssh_client_conn.Dial("tcp", remote_loc)
|
ssh_conn, err := ssh_client_conn.Dial("tcp", remote_loc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("ssh.Dial error: %s", err)
|
log.Printf("ssh.Dial error: %s", err)
|
||||||
ssh_client_conn.Close()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer ssh_conn.Close()
|
||||||
|
|
||||||
txDone := make(chan struct{})
|
txDone := make(chan struct{})
|
||||||
rxDone := make(chan struct{})
|
rxDone := make(chan struct{})
|
||||||
@ -117,12 +120,8 @@ func forward(local_conn net.Conn, config *gossh.ClientConfig, server, remote_des
|
|||||||
close(rxDone)
|
close(rxDone)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
<-txDone
|
||||||
<-txDone
|
<-rxDone
|
||||||
<-rxDone
|
|
||||||
ssh_client_conn.Close()
|
|
||||||
ssh_conn.Close()
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -214,6 +214,11 @@ func (self *stepCreateInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
func (self *stepCreateInstance) Cleanup(state multistep.StateBag) {
|
||||||
|
config := state.Get("config").(config)
|
||||||
|
if config.ShouldKeepInstance(state) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
if self.instance != nil {
|
if self.instance != nil {
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepForwardPortOverSSH struct {
|
type stepForwardPortOverSSH struct {
|
||||||
@ -25,32 +23,15 @@ func (self *stepForwardPortOverSSH) Run(state multistep.StateBag) multistep.Step
|
|||||||
|
|
||||||
// Find a free local port:
|
// Find a free local port:
|
||||||
|
|
||||||
log.Printf("Looking for an available port between %d and %d",
|
l, sshHostPort := FindPort(self.HostPortMin, self.HostPortMax)
|
||||||
self.HostPortMin,
|
|
||||||
self.HostPortMax)
|
|
||||||
|
|
||||||
var sshHostPort uint
|
if l == nil || sshHostPort == 0 {
|
||||||
var foundPort bool
|
ui.Error("Error: unable to find free host port. Try providing a larger range [host_port_min, host_port_max]")
|
||||||
|
|
||||||
foundPort = false
|
|
||||||
|
|
||||||
for i := self.HostPortMin; i < self.HostPortMax; i++ {
|
|
||||||
sshHostPort = i
|
|
||||||
log.Printf("Trying port: %d", sshHostPort)
|
|
||||||
l, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", sshHostPort))
|
|
||||||
if err == nil {
|
|
||||||
l.Close()
|
|
||||||
foundPort = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if !foundPort {
|
|
||||||
ui.Error("Error: unable to find free host port. Try providing a larger range")
|
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.Close()
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Creating a local port forward over SSH on local port %d", sshHostPort))
|
ui.Say(fmt.Sprintf("Creating a local port forward over SSH on local port %d", sshHostPort))
|
||||||
|
|
||||||
remotePort, _ := self.RemotePort(state)
|
remotePort, _ := self.RemotePort(state)
|
||||||
|
@ -6,8 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/multistep"
|
"github.com/mitchellh/multistep"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
|
||||||
"math/rand"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
@ -36,32 +34,18 @@ func (s *stepHTTPServer) Run(state multistep.StateBag) multistep.StepAction {
|
|||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find an available TCP port for our HTTP server
|
s.l, httpPort = FindPort(config.HTTPPortMin, config.HTTPPortMax)
|
||||||
var httpAddr string
|
|
||||||
portRange := int(config.HTTPPortMax - config.HTTPPortMin)
|
|
||||||
for {
|
|
||||||
var err error
|
|
||||||
var offset uint = 0
|
|
||||||
|
|
||||||
if portRange > 0 {
|
if s.l == nil || httpPort == 0 {
|
||||||
// Intn will panic if portRange == 0, so we do a check.
|
ui.Error("Error: unable to find free HTTP server port. Try providing a larger range [http_port_min, http_port_max]")
|
||||||
offset = uint(rand.Intn(portRange))
|
return multistep.ActionHalt
|
||||||
}
|
|
||||||
|
|
||||||
httpPort = offset + config.HTTPPortMin
|
|
||||||
httpAddr = fmt.Sprintf(":%d", httpPort)
|
|
||||||
log.Printf("Trying port: %d", httpPort)
|
|
||||||
s.l, err = net.Listen("tcp", httpAddr)
|
|
||||||
if err == nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
|
ui.Say(fmt.Sprintf("Starting HTTP server on port %d", httpPort))
|
||||||
|
|
||||||
// Start the HTTP server and run it in the background
|
// Start the HTTP server and run it in the background
|
||||||
fileServer := http.FileServer(http.Dir(config.HTTPDir))
|
fileServer := http.FileServer(http.Dir(config.HTTPDir))
|
||||||
server := &http.Server{Addr: httpAddr, Handler: fileServer}
|
server := &http.Server{Addr: fmt.Sprintf(":%d", httpPort), Handler: fileServer}
|
||||||
go server.Serve(s.l)
|
go server.Serve(s.l)
|
||||||
|
|
||||||
// Save the address into the state so it can be accessed in the future
|
// Save the address into the state so it can be accessed in the future
|
||||||
|
@ -65,44 +65,52 @@ func (stepShutdownAndExport) Run(state multistep.StateBag) multistep.StepAction
|
|||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
//Export the VM
|
switch config.ExportFormat {
|
||||||
|
case "xva":
|
||||||
|
// export the VM
|
||||||
|
|
||||||
export_url := fmt.Sprintf("https://%s/export?vm=%s&session_id=%s",
|
export_url := fmt.Sprintf("https://%s/export?vm=%s&session_id=%s",
|
||||||
client.Host,
|
|
||||||
instance.Ref,
|
|
||||||
client.Session.(string),
|
|
||||||
)
|
|
||||||
|
|
||||||
export_filename := fmt.Sprintf("%s/%s.xva", config.OutputDir, config.InstanceName)
|
|
||||||
ui.Say("Getting metadata " + export_url)
|
|
||||||
downloadFile(export_url, export_filename)
|
|
||||||
|
|
||||||
disks, err := instance.GetDisks()
|
|
||||||
if err != nil {
|
|
||||||
ui.Error(fmt.Sprintf("Could not get VM disks: %s", err.Error()))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
for _, disk := range disks {
|
|
||||||
disk_uuid, err := disk.GetUuid()
|
|
||||||
if err != nil {
|
|
||||||
ui.Error(fmt.Sprintf("Could not get disk with UUID '%s': %s", disk_uuid, err.Error()))
|
|
||||||
return multistep.ActionHalt
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic auth in URL request is required as session token is not
|
|
||||||
// accepted for some reason.
|
|
||||||
// @todo: raise with XAPI team.
|
|
||||||
disk_export_url := fmt.Sprintf("https://%s:%s@%s/export_raw_vdi?vdi=%s",
|
|
||||||
client.Username,
|
|
||||||
client.Password,
|
|
||||||
client.Host,
|
client.Host,
|
||||||
disk_uuid,
|
instance_uuid,
|
||||||
|
client.Session.(string),
|
||||||
)
|
)
|
||||||
|
|
||||||
ui.Say("Getting " + disk_export_url)
|
export_filename := fmt.Sprintf("%s/%s.xva", config.OutputDir, config.InstanceName)
|
||||||
disk_export_filename := fmt.Sprintf("%s/%s.raw", config.OutputDir, disk_uuid)
|
ui.Say("Getting XVA " + export_url)
|
||||||
ui.Say("Downloading " + disk_uuid)
|
downloadFile(export_url, export_filename)
|
||||||
downloadFile(disk_export_url, disk_export_filename)
|
|
||||||
|
case "vdi_raw":
|
||||||
|
// export the disks
|
||||||
|
|
||||||
|
disks, err := instance.GetDisks()
|
||||||
|
if err != nil {
|
||||||
|
ui.Error(fmt.Sprintf("Could not get VM disks: %s", err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
for _, disk := range disks {
|
||||||
|
disk_uuid, err := disk.GetUuid()
|
||||||
|
if err != nil {
|
||||||
|
ui.Error(fmt.Sprintf("Could not get disk with UUID '%s': %s", disk_uuid, err.Error()))
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic auth in URL request is required as session token is not
|
||||||
|
// accepted for some reason.
|
||||||
|
// @todo: raise with XAPI team.
|
||||||
|
disk_export_url := fmt.Sprintf("https://%s:%s@%s/export_raw_vdi?vdi=%s",
|
||||||
|
client.Username,
|
||||||
|
client.Password,
|
||||||
|
client.Host,
|
||||||
|
disk_uuid,
|
||||||
|
)
|
||||||
|
|
||||||
|
disk_export_filename := fmt.Sprintf("%s/%s.raw", config.OutputDir, disk_uuid)
|
||||||
|
ui.Say("Getting VDI " + disk_export_url)
|
||||||
|
downloadFile(disk_export_url, disk_export_filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Unknown export_format '%s'", config.ExportFormat))
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say("Download completed: " + config.OutputDir)
|
ui.Say("Download completed: " + config.OutputDir)
|
||||||
|
@ -63,7 +63,7 @@ func (self *stepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction
|
|||||||
log.Printf("Ref: %s", instance.Ref)
|
log.Printf("Ref: %s", instance.Ref)
|
||||||
|
|
||||||
//Check for instance.Ref in map
|
//Check for instance.Ref in map
|
||||||
if vm_ip, ok := ips[himn_vif.Ref]; ok {
|
if vm_ip, ok := ips[himn_vif.Ref]; ok && vm_ip != "" {
|
||||||
ui.Say("Found the VM's IP: " + vm_ip)
|
ui.Say("Found the VM's IP: " + vm_ip)
|
||||||
himn_iface_ip = vm_ip
|
himn_iface_ip = vm_ip
|
||||||
return true, nil
|
return true, nil
|
||||||
@ -76,15 +76,13 @@ func (self *stepStartOnHIMN) Run(state multistep.StateBag) multistep.StepAction
|
|||||||
Timeout: 100 * time.Second,
|
Timeout: 100 * time.Second,
|
||||||
}.Wait(state)
|
}.Wait(state)
|
||||||
|
|
||||||
if err != nil || himn_iface_ip == "" {
|
if err != nil {
|
||||||
ui.Error(fmt.Sprintf("Unable to find an IP on the Host-internal management interface: %s", err.Error()))
|
ui.Error(fmt.Sprintf("Unable to find an IP on the Host-internal management interface: %s", err.Error()))
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
if himn_iface_ip != "" {
|
state.Put("himn_ssh_address", himn_iface_ip)
|
||||||
state.Put("himn_ssh_address", himn_iface_ip)
|
ui.Say("Stored VM's IP " + himn_iface_ip)
|
||||||
ui.Say("Stored VM's IP " + himn_iface_ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the VM to boot, and check we can ping this interface
|
// Wait for the VM to boot, and check we can ping this interface
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
[
|
[
|
||||||
"<tab><wait>",
|
"<tab><wait>",
|
||||||
" ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>"
|
" ks=http://{{ .HTTPIP }}:{{ .HTTPPort }}/centos6-ks.cfg<enter>"
|
||||||
]
|
],
|
||||||
|
"keep_instance": "always"
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user