mirror of https://github.com/docker/docs.git
Fix issue where GetIP failes due to no SSH
The main goal of this patch was to make the VirtualBox driver wait for SSH before trying to get the IP of the VM. The generic WaitForSSH method required a Host struct as an arg. This patch moves most of the logic to the driver package so that drivers can call WaitForSSH. The existing functions in host are just wrappers to the real implementation in drivers now. Signed-off-by: Darren Shepherd <darren@rancher.com>
This commit is contained in:
parent
e4b6ff1ae9
commit
8afe967a80
|
@ -8,7 +8,6 @@ import (
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/docker/machine/log"
|
"github.com/docker/machine/log"
|
||||||
"github.com/docker/machine/provider"
|
"github.com/docker/machine/provider"
|
||||||
"github.com/docker/machine/ssh"
|
|
||||||
"github.com/docker/machine/state"
|
"github.com/docker/machine/state"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -173,34 +172,6 @@ type DriverOptions interface {
|
||||||
Bool(key string) bool
|
Bool(key string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunSSHCommandFromDriver(d Driver, args string) (ssh.Output, error) {
|
|
||||||
var output ssh.Output
|
|
||||||
|
|
||||||
host, err := d.GetSSHHostname()
|
|
||||||
if err != nil {
|
|
||||||
return output, err
|
|
||||||
}
|
|
||||||
|
|
||||||
port, err := d.GetSSHPort()
|
|
||||||
if err != nil {
|
|
||||||
return output, err
|
|
||||||
}
|
|
||||||
|
|
||||||
user := d.GetSSHUsername()
|
|
||||||
keyPath := d.GetSSHKeyPath()
|
|
||||||
|
|
||||||
auth := &ssh.Auth{
|
|
||||||
Keys: []string{keyPath},
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := ssh.NewClient(user, host, port, auth)
|
|
||||||
if err != nil {
|
|
||||||
return output, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return client.Run(args)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MachineInState(d Driver, desiredState state.State) func() bool {
|
func MachineInState(d Driver, desiredState state.State) func() bool {
|
||||||
return func() bool {
|
return func() bool {
|
||||||
currentState, err := d.GetState()
|
currentState, err := d.GetState()
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package drivers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/docker/machine/log"
|
||||||
|
"github.com/docker/machine/ssh"
|
||||||
|
"github.com/docker/machine/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RunSSHCommandFromDriver(d Driver, command string) (ssh.Output, error) {
|
||||||
|
var output ssh.Output
|
||||||
|
|
||||||
|
addr, err := d.GetSSHHostname()
|
||||||
|
if err != nil {
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
|
||||||
|
port, err := d.GetSSHPort()
|
||||||
|
if err != nil {
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
|
||||||
|
auth := &ssh.Auth{
|
||||||
|
Keys: []string{d.GetSSHKeyPath()},
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := ssh.NewClient(d.GetSSHUsername(), addr, port, auth)
|
||||||
|
if err != nil {
|
||||||
|
return output, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.Run(command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sshAvailableFunc(d Driver) func() bool {
|
||||||
|
return func() bool {
|
||||||
|
log.Debug("Getting to WaitForSSH function...")
|
||||||
|
hostname, err := d.GetSSHHostname()
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("Error getting IP address waiting for SSH: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
port, err := d.GetSSHPort()
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("Error getting SSH port: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if err := ssh.WaitForTCP(fmt.Sprintf("%s:%d", hostname, port)); err != nil {
|
||||||
|
log.Debugf("Error waiting for TCP waiting for SSH: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := RunSSHCommandFromDriver(d, "exit 0"); err != nil {
|
||||||
|
log.Debugf("Error getting ssh command 'exit 0' : %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WaitForSSH(d Driver) error {
|
||||||
|
if err := utils.WaitFor(sshAvailableFunc(d)); err != nil {
|
||||||
|
return fmt.Errorf("Too many retries. Last error: %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -393,6 +393,10 @@ func (d *Driver) Start() error {
|
||||||
log.Infof("VM not in restartable state")
|
log.Infof("VM not in restartable state")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := drivers.WaitForSSH(d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
d.IPAddress, err = d.GetIP()
|
d.IPAddress, err = d.GetIP()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,25 +136,7 @@ func (h *Host) Create(name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Host) RunSSHCommand(command string) (ssh.Output, error) {
|
func (h *Host) RunSSHCommand(command string) (ssh.Output, error) {
|
||||||
var output ssh.Output
|
return drivers.RunSSHCommandFromDriver(h.Driver, command)
|
||||||
|
|
||||||
addr, err := h.Driver.GetSSHHostname()
|
|
||||||
if err != nil {
|
|
||||||
return output, err
|
|
||||||
}
|
|
||||||
|
|
||||||
port, err := h.Driver.GetSSHPort()
|
|
||||||
if err != nil {
|
|
||||||
return output, err
|
|
||||||
}
|
|
||||||
|
|
||||||
auth := &ssh.Auth{
|
|
||||||
Keys: []string{h.Driver.GetSSHKeyPath()},
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := ssh.NewClient(h.Driver.GetSSHUsername(), addr, port, auth)
|
|
||||||
|
|
||||||
return client.Run(command)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Host) CreateSSHShell() error {
|
func (h *Host) CreateSSHShell() error {
|
||||||
|
@ -352,37 +334,8 @@ func (h *Host) PrintIP() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sshAvailableFunc(h *Host) func() bool {
|
|
||||||
return func() bool {
|
|
||||||
log.Debug("Getting to WaitForSSH function...")
|
|
||||||
hostname, err := h.Driver.GetSSHHostname()
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf("Error getting IP address waiting for SSH: %s", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
port, err := h.Driver.GetSSHPort()
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf("Error getting SSH port: %s", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if err := ssh.WaitForTCP(fmt.Sprintf("%s:%d", hostname, port)); err != nil {
|
|
||||||
log.Debugf("Error waiting for TCP waiting for SSH: %s", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := h.RunSSHCommand("exit 0"); err != nil {
|
|
||||||
log.Debugf("Error getting ssh command 'exit 0' : %s", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WaitForSSH(h *Host) error {
|
func WaitForSSH(h *Host) error {
|
||||||
if err := utils.WaitFor(sshAvailableFunc(h)); err != nil {
|
return drivers.WaitForSSH(h.Driver)
|
||||||
return fmt.Errorf("Too many retries. Last error: %s", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHostState(host Host, hostListItemsChan chan<- HostListItem) {
|
func getHostState(host Host, hostListItemsChan chan<- HostListItem) {
|
||||||
|
|
18
ssh/ssh.go
18
ssh/ssh.go
|
@ -1,18 +1,22 @@
|
||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import "net"
|
import (
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/machine/log"
|
||||||
|
)
|
||||||
|
|
||||||
func WaitForTCP(addr string) error {
|
func WaitForTCP(addr string) error {
|
||||||
for {
|
for {
|
||||||
conn, err := net.Dial("tcp", addr)
|
log.Debugf("Testing TCP connection to: %s", addr)
|
||||||
|
conn, err := net.DialTimeout("tcp", addr, 2*time.Second)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
if _, err = conn.Read(make([]byte, 1)); err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue