Merge pull request #1426 from jasonberanek/vnc-fixes
vmware-iso/esxi: fix multiple issues with VNC address discovery
This commit is contained in:
commit
caca50324e
|
@ -16,7 +16,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -148,29 +147,57 @@ func (d *ESX5Driver) HostIP() (string, error) {
|
||||||
return host, err
|
return host, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ESX5Driver) VNCAddress(portMin, portMax uint) (string, uint) {
|
func (d *ESX5Driver) VNCAddress(portMin, portMax uint) (string, uint, error) {
|
||||||
var vncPort uint
|
var vncPort uint
|
||||||
// TODO(dougm) use esxcli network ip connection list
|
|
||||||
|
//Process ports ESXi is listening on to determine which are available
|
||||||
|
r, err := d.esxcli("network", "ip", "connection", "list")
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Could not retrieve network information for ESXi: %v", err)
|
||||||
|
return "", 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
listenPorts := make(map[string]bool)
|
||||||
|
for record, err := r.read(); record != nil && err == nil; record, err = r.read() {
|
||||||
|
if record["State"] == "LISTEN" {
|
||||||
|
splitAddress := strings.Split(record["LocalAddress"], ":")
|
||||||
|
log.Print(splitAddress)
|
||||||
|
port := splitAddress[len(splitAddress)-1]
|
||||||
|
log.Printf("ESXi Listening on: %s", port)
|
||||||
|
listenPorts[port] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for port := portMin; port <= portMax; port++ {
|
for port := portMin; port <= portMax; port++ {
|
||||||
|
if _, ok := listenPorts[fmt.Sprintf("%d", port)]; ok {
|
||||||
|
log.Printf("Port %d in use", port)
|
||||||
|
continue
|
||||||
|
}
|
||||||
address := fmt.Sprintf("%s:%d", d.Host, port)
|
address := fmt.Sprintf("%s:%d", d.Host, port)
|
||||||
log.Printf("Trying address: %s...", address)
|
log.Printf("Trying address: %s...", address)
|
||||||
l, err := net.DialTimeout("tcp", address, 1*time.Second)
|
l, err := net.DialTimeout("tcp", address, 1*time.Second)
|
||||||
|
|
||||||
if err == nil {
|
if err != nil {
|
||||||
log.Printf("%s in use", address)
|
if e, ok := err.(*net.OpError); ok {
|
||||||
l.Close()
|
if e.Timeout() {
|
||||||
} else if e, ok := err.(*net.OpError); ok {
|
log.Printf("Timeout connecting to: %s (check firewall rules)", address)
|
||||||
if e.Err == syscall.ECONNREFUSED {
|
} else {
|
||||||
// then port should be available for listening
|
|
||||||
vncPort = port
|
vncPort = port
|
||||||
break
|
break
|
||||||
} else if e.Timeout() {
|
|
||||||
log.Printf("Timeout connecting to: %s (check firewall rules)", address)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
defer l.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.Host, vncPort
|
if vncPort == 0 {
|
||||||
|
err := fmt.Errorf("Unable to find available VNC port between %d and %d",
|
||||||
|
portMin, portMax)
|
||||||
|
return d.Host, vncPort, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return d.Host, vncPort, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ESX5Driver) SSHAddress(state multistep.StateBag) (string, error) {
|
func (d *ESX5Driver) SSHAddress(state multistep.StateBag) (string, error) {
|
||||||
|
|
|
@ -24,17 +24,22 @@ import (
|
||||||
type stepConfigureVNC struct{}
|
type stepConfigureVNC struct{}
|
||||||
|
|
||||||
type VNCAddressFinder interface {
|
type VNCAddressFinder interface {
|
||||||
VNCAddress(uint, uint) (string, uint)
|
VNCAddress(uint, uint) (string, uint, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (stepConfigureVNC) VNCAddress(portMin, portMax uint) (string, uint) {
|
func (stepConfigureVNC) VNCAddress(portMin, portMax uint) (string, uint, error) {
|
||||||
// Find an open VNC port. Note that this can still fail later on
|
// Find an open VNC port. Note that this can still fail later on
|
||||||
// because we have to release the port at some point. But this does its
|
// because we have to release the port at some point. But this does its
|
||||||
// best.
|
// best.
|
||||||
var vncPort uint
|
var vncPort uint
|
||||||
portRange := int(portMax - portMin)
|
portRange := int(portMax - portMin)
|
||||||
for {
|
for {
|
||||||
|
if portRange > 0 {
|
||||||
vncPort = uint(rand.Intn(portRange)) + portMin
|
vncPort = uint(rand.Intn(portRange)) + portMin
|
||||||
|
} else {
|
||||||
|
vncPort = portMin
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Trying port: %d", vncPort)
|
log.Printf("Trying port: %d", vncPort)
|
||||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", vncPort))
|
l, err := net.Listen("tcp", fmt.Sprintf(":%d", vncPort))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -42,7 +47,7 @@ func (stepConfigureVNC) VNCAddress(portMin, portMax uint) (string, uint) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "127.0.0.1", vncPort
|
return "127.0.0.1", vncPort, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
func (s *stepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
|
@ -74,10 +79,8 @@ func (s *stepConfigureVNC) Run(state multistep.StateBag) multistep.StepAction {
|
||||||
vncFinder = s
|
vncFinder = s
|
||||||
}
|
}
|
||||||
log.Printf("Looking for available port between %d and %d", config.VNCPortMin, config.VNCPortMax)
|
log.Printf("Looking for available port between %d and %d", config.VNCPortMin, config.VNCPortMax)
|
||||||
vncIp, vncPort := vncFinder.VNCAddress(config.VNCPortMin, config.VNCPortMax)
|
vncIp, vncPort, err := vncFinder.VNCAddress(config.VNCPortMin, config.VNCPortMax)
|
||||||
if vncPort == 0 {
|
if err != nil {
|
||||||
err := fmt.Errorf("Unable to find available VNC port between %d and %d",
|
|
||||||
config.VNCPortMin, config.VNCPortMax)
|
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
|
|
Loading…
Reference in New Issue