Skip to content

Commit

Permalink
Add support for IP address changes
Browse files Browse the repository at this point in the history
This commit improves upon the existing "Wait for IP step", by
continuously checking for changes to the IP address for the VM, even
after the IP address has been retrieved.

The implementation is using a simple goroutine which encapsulates the
existing method used to wait for the IP address. When an IP address has
been found, the goroutine will put the IP address directly in the state,
which will be queried when the IP address should be retrieved.
  • Loading branch information
Erik142 committed Jan 18, 2024
1 parent bc21b3c commit 2376943
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 20 deletions.
9 changes: 7 additions & 2 deletions builder/xenserver/common/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,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, remote_dest_func func() (string, error)) error {
config := &gossh.ClientConfig{
User: username,
Auth: []gossh.AuthMethod{
Expand All @@ -175,6 +174,12 @@ func ssh_port_forward(local_listener net.Listener, remote_port int, remote_dest,
return err
}

remote_dest, err := remote_dest_func()

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
2 changes: 1 addition & 1 deletion builder/xenserver/common/step_forward_port_over_ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (self *StepForwardPortOverSSH) Run(ctx context.Context, state multistep.Sta
remotePort, _ := self.RemotePort(state)
remoteDest, _ := 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, func() (string, error) { return self.RemoteDest(state) })
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
49 changes: 32 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,62 @@ 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

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 temp_ip := <-self.Chan:
if ip != temp_ip {
ip = temp_ip
ui.Message(fmt.Sprintf("Got IP '%s' from HTTP request", ip))
state.Put("instance_ssh_address", ip)
}
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 temp_ip, ok := networks["0/ip"]; ok {
if temp_ip != "" && ip != temp_ip {
ip = temp_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(500 * time.Millisecond)

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

0 comments on commit 2376943

Please sign in to comment.