diff --git a/drivers/drivers.go b/drivers/drivers.go index 6b43f501cd..2c86432912 100644 --- a/drivers/drivers.go +++ b/drivers/drivers.go @@ -8,7 +8,6 @@ import ( "github.com/codegangsta/cli" "github.com/docker/machine/log" "github.com/docker/machine/provider" - "github.com/docker/machine/ssh" "github.com/docker/machine/state" ) @@ -173,34 +172,6 @@ type DriverOptions interface { 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 { return func() bool { currentState, err := d.GetState() diff --git a/drivers/utils.go b/drivers/utils.go new file mode 100644 index 0000000000..793ec3630e --- /dev/null +++ b/drivers/utils.go @@ -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 +} diff --git a/drivers/virtualbox/virtualbox.go b/drivers/virtualbox/virtualbox.go index c1acf6f018..8a8116b0d5 100644 --- a/drivers/virtualbox/virtualbox.go +++ b/drivers/virtualbox/virtualbox.go @@ -393,6 +393,10 @@ func (d *Driver) Start() error { log.Infof("VM not in restartable state") } + if err := drivers.WaitForSSH(d); err != nil { + return err + } + d.IPAddress, err = d.GetIP() return err } diff --git a/libmachine/host.go b/libmachine/host.go index 5f28861ff7..7b2a432bf0 100644 --- a/libmachine/host.go +++ b/libmachine/host.go @@ -136,25 +136,7 @@ func (h *Host) Create(name string) error { } func (h *Host) RunSSHCommand(command string) (ssh.Output, error) { - var output ssh.Output - - 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) + return drivers.RunSSHCommandFromDriver(h.Driver, command) } func (h *Host) CreateSSHShell() error { @@ -352,37 +334,8 @@ func (h *Host) PrintIP() error { 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 { - if err := utils.WaitFor(sshAvailableFunc(h)); err != nil { - return fmt.Errorf("Too many retries. Last error: %s", err) - } - return nil + return drivers.WaitForSSH(h.Driver) } func getHostState(host Host, hostListItemsChan chan<- HostListItem) { diff --git a/ssh/ssh.go b/ssh/ssh.go index baaf92443a..3abb264a23 100644 --- a/ssh/ssh.go +++ b/ssh/ssh.go @@ -1,18 +1,22 @@ package ssh -import "net" +import ( + "net" + "time" + + "github.com/docker/machine/log" +) func WaitForTCP(addr string) error { 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 { continue } + defer conn.Close() - if _, err = conn.Read(make([]byte, 1)); err != nil { - continue - } - break + return nil } - return nil }