Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions builder/xenserver/common/common_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ type CommonConfig struct {

RawBootWait string `mapstructure:"boot_wait"`
BootWait time.Duration
RawDhcpWait string `mapstructure:"dhcp_wait"`
DhcpWait time.Duration

ToolsIsoName string `mapstructure:"tools_iso_name"`

Expand Down Expand Up @@ -82,6 +84,10 @@ func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig
c.RawBootWait = "5s"
}

if c.RawDhcpWait == "" {
c.RawDhcpWait = "500ms"
}

if c.HTTPPortMin == 0 {
c.HTTPPortMin = 8000
}
Expand Down Expand Up @@ -163,6 +169,11 @@ func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig
errs = append(errs, fmt.Errorf("Failed to parse boot_wait: %s", err))
}

c.DhcpWait, err = time.ParseDuration(c.RawDhcpWait)
if err != nil {
errs = append(errs, fmt.Errorf("Failed to parse dhcp_wait: %s", err))
}

if c.SSHKeyPath != "" {
if _, err := os.Stat(c.SSHKeyPath); err != nil {
errs = append(errs, fmt.Errorf("ssh_key_path is invalid: %s", err))
Expand Down
11 changes: 9 additions & 2 deletions builder/xenserver/common/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
gossh "golang.org/x/crypto/ssh"
)

type RemoteDestFunc func() (string, error)

func SSHAddress(state multistep.StateBag) (string, error) {
sshIP := state.Get("ssh_address").(string)
sshHostPort := state.Get("ssh_port").(uint)
Expand Down Expand Up @@ -157,8 +159,7 @@ func forward(local_conn net.Conn, config *gossh.ClientConfig, server string, ser
return nil
}

func ssh_port_forward(local_listener net.Listener, remote_port int, remote_dest, host string, host_ssh_port int, username, password string) error {

func ssh_port_forward(local_listener net.Listener, remote_port int, host string, host_ssh_port int, username, password string, get_remote_dest RemoteDestFunc) error {
config := &gossh.ClientConfig{
User: username,
Auth: []gossh.AuthMethod{
Expand All @@ -175,6 +176,12 @@ func ssh_port_forward(local_listener net.Listener, remote_port int, remote_dest,
return err
}

remote_dest, err := get_remote_dest()

if err != nil {
return err
}

// Forward to a remote port
go forward(local_connection, config, host, host_ssh_port, remote_dest, uint(remote_port))
}
Expand Down
3 changes: 2 additions & 1 deletion builder/xenserver/common/step_forward_port_over_ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ func (self *StepForwardPortOverSSH) Run(ctx context.Context, state multistep.Sta
hostSshPort, _ := state.Get("ssh_port").(int)
remotePort, _ := self.RemotePort(state)
remoteDest, _ := self.RemoteDest(state)
remoteDestFunc := RemoteDestFunc(func() (string, error) { return self.RemoteDest(state) })

go ssh_port_forward(l, remotePort, remoteDest, hostAddress, hostSshPort, config.Username, config.Password)
go ssh_port_forward(l, remotePort, hostAddress, hostSshPort, config.Username, config.Password, remoteDestFunc)
ui.Say(fmt.Sprintf("Port forward setup. %d ---> %s:%d on %s", sshHostPort, remoteDest, remotePort, hostAddress))

// Provide the local port to future steps.
Expand Down
52 changes: 35 additions & 17 deletions builder/xenserver/common/step_wait_for_ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,47 +29,65 @@ func (self *StepWaitForIP) Run(ctx context.Context, state multistep.StateBag) mu
return multistep.ActionHalt
}

var ip string
err = InterruptibleWait{
Timeout: self.Timeout,
PredicateInterval: 5 * time.Second,
Predicate: func() (result bool, err error) {
go func(c Connection, ui packer.Ui, config CommonConfig) {
state.Put("instance_ssh_address", "")
var ip string

if config.IPGetter == "auto" || config.IPGetter == "http" {
for true {
time.Sleep(500 * time.Millisecond)

if config.IPGetter == "auto" || config.IPGetter == "http" {
// Snoop IP from HTTP fetch
select {
case ip = <-self.Chan:
ui.Message(fmt.Sprintf("Got IP '%s' from HTTP request", ip))
return true, nil
case new_ip := <-self.Chan:
if ip != new_ip {
ip = new_ip
ui.Message(fmt.Sprintf("Got IP '%s' from HTTP request", ip))
state.Put("instance_ssh_address", ip)
}
continue
default:
}

}

if config.IPGetter == "auto" || config.IPGetter == "tools" {

// Look for PV IP
m, err := c.client.VM.GetGuestMetrics(c.session, instance)
if err != nil {
return false, err
continue
}
if m != "" {
metrics, err := c.client.VMGuestMetrics.GetRecord(c.session, m)
if err != nil {
return false, err
continue
}
networks := metrics.Networks
var ok bool
if ip, ok = networks["0/ip"]; ok {
if ip != "" {
if new_ip, ok := networks["0/ip"]; ok {
if new_ip != "" && ip != new_ip {
ip = new_ip
ui.Message(fmt.Sprintf("Got IP '%s' from XenServer tools", ip))
return true, nil
state.Put("instance_ssh_address", ip)
}
}
}

}
}
}(*c, ui, config)

time.Sleep(config.DhcpWait)

var ip string

err = InterruptibleWait{
Timeout: self.Timeout,
PredicateInterval: 5 * time.Second,
Predicate: func() (result bool, err error) {

var ok bool
if ip, ok = state.Get("instance_ssh_address").(string); ok && ip != "" {
return true, nil
}

return false, nil
},
Expand Down
3 changes: 1 addition & 2 deletions builder/xenserver/xva/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package xva
import (
"context"
"errors"
"time"

"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer-plugin-sdk/communicator"
Expand Down Expand Up @@ -181,7 +180,7 @@ func (self *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (p
},
&xscommon.StepWaitForIP{
Chan: httpReqChan,
Timeout: 300 * time.Minute, /*self.config.InstallTimeout*/ // @todo change this
Timeout: self.config.InstallTimeout,
},
&xscommon.StepForwardPortOverSSH{
RemotePort: xscommon.InstanceSSHPort,
Expand Down
6 changes: 6 additions & 0 deletions docs/builders/iso/xenserver-iso.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ each category, the available options are alphabetized and described.
run `xe template-list`. Setting the correct value hints to XenServer how to
optimize the virtual hardware to work best with that operating system.

* `dhcp_wait` (string) - The time to wait for the virtual machine to retrieve
an initial IP address via DHCP. The value of this should be
a duration. Examples are `500ms` and `10s` which will cause Packer to wait
500 milliseconds and 10 seconds, respectively. If this isn't specified,
the default is 500 milliseconds.

* `disk_name` (string) - The name of the hard disk to create for the VM.
By default, the name is "Packer-disk".

Expand Down