Merge pull request #2936 from nathanleclaire/poll_daemon_start

Wait for Docker daemon on host start
This commit is contained in:
David Gageot 2016-01-27 09:27:34 +01:00
commit 62db9eb370
6 changed files with 72 additions and 13 deletions

View File

@ -1,5 +1,9 @@
package engine
const (
DefaultPort = 2376
)
type Options struct {
ArbitraryFlags []string
DNS []string `json:"Dns"`

View File

@ -111,6 +111,17 @@ func (h *Host) Start() error {
}
log.Infof("Machine %q was started.", h.Name)
provisioner, err := provision.DetectProvisioner(h.Driver)
if err != nil {
return err
}
// TODO: Migrate away from using hardcoded daemon port.
if err := provision.WaitForDocker(provisioner, engine.DefaultPort); err != nil {
return err
}
return nil
}

View File

@ -3,7 +3,10 @@ package host
import (
"testing"
"github.com/docker/machine/drivers/fakedriver"
_ "github.com/docker/machine/drivers/none"
"github.com/docker/machine/libmachine/provision"
"github.com/docker/machine/libmachine/state"
)
func TestValidateHostnameValid(t *testing.T) {
@ -35,3 +38,47 @@ func TestValidateHostnameInvalid(t *testing.T) {
}
}
}
type NetstatProvisioner struct {
*provision.FakeProvisioner
}
func (p *NetstatProvisioner) SSHCommand(args string) (string, error) {
return `Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN
tcp 0 72 192.168.25.141:ssh 192.168.25.1:63235 ESTABLISHED
tcp 0 0 :::2376 :::* LISTEN
tcp 0 0 :::ssh :::* LISTEN
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 17990 /var/run/acpid.socket
unix 2 [ ACC ] SEQPACKET LISTENING 14233 /run/udev/control
unix 2 [ ACC ] STREAM LISTENING 19365 /var/run/docker.sock
unix 3 [ ] STREAM CONNECTED 19774
unix 3 [ ] STREAM CONNECTED 19775
unix 3 [ ] DGRAM 14243
unix 3 [ ] DGRAM 14242`, nil
}
func NewNetstatProvisioner() provision.Provisioner {
return &NetstatProvisioner{
&provision.FakeProvisioner{},
}
}
func TestStart(t *testing.T) {
provision.SetDetector(&provision.FakeDetector{
NewNetstatProvisioner(),
})
host := &Host{
Driver: &fakedriver.Driver{
MockState: state.Stopped,
},
}
if err := host.Start(); err != nil {
t.Fatalf("Expected no error but got one: %s", err)
}
}

View File

@ -194,35 +194,31 @@ func (provisioner *Boot2DockerProvisioner) AttemptIPContact(dockerPort int) {
}
if conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, dockerPort), 5*time.Second); err != nil {
log.Warn(`
log.Warnf(`
This machine has been allocated an IP address, but Docker Machine could not
reach it successfully.
SSH for the machine should still work, but connecting to exposed ports, such as
the Docker daemon port (usually <ip>:2376), may not work properly.
the Docker daemon port (usually <ip>:%d), may not work properly.
You may need to add the route manually, or use another related workaround.
This could be due to a VPN, proxy, or host file configuration issue.
You also might want to clear any VirtualBox host only interfaces you are not using.`)
You also might want to clear any VirtualBox host only interfaces you are not using.`, engine.DefaultPort)
} else {
conn.Close()
}
}
func (provisioner *Boot2DockerProvisioner) Provision(swarmOptions swarm.Options, authOptions auth.Options, engineOptions engine.Options) error {
const (
dockerPort = 2376
)
var (
err error
)
defer func() {
if err == nil {
provisioner.AttemptIPContact(dockerPort)
provisioner.AttemptIPContact(engine.DefaultPort)
}
}()
@ -241,7 +237,7 @@ func (provisioner *Boot2DockerProvisioner) Provision(swarmOptions swarm.Options,
// b2d hosts need to wait for the daemon to be up
// before continuing with provisioning
if err = waitForDocker(provisioner, dockerPort); err != nil {
if err = WaitForDocker(provisioner, engine.DefaultPort); err != nil {
return err
}

View File

@ -13,6 +13,7 @@ import (
"github.com/docker/machine/libmachine/auth"
"github.com/docker/machine/libmachine/cert"
"github.com/docker/machine/libmachine/engine"
"github.com/docker/machine/libmachine/log"
"github.com/docker/machine/libmachine/mcnutils"
"github.com/docker/machine/libmachine/provision/serviceaction"
@ -161,7 +162,7 @@ func ConfigureAuth(p Provisioner) error {
if err != nil {
return err
}
dockerPort := 2376
dockerPort := engine.DefaultPort
parts := strings.Split(u.Host, ":")
if len(parts) == 2 {
dPort, err := strconv.Atoi(parts[1])
@ -186,7 +187,7 @@ func ConfigureAuth(p Provisioner) error {
return err
}
return waitForDocker(p, dockerPort)
return WaitForDocker(p, dockerPort)
}
func matchNetstatOut(reDaemonListening, netstatOut string) bool {
@ -262,7 +263,7 @@ func checkDaemonUp(p Provisioner, dockerPort int) func() bool {
}
}
func waitForDocker(p Provisioner, dockerPort int) error {
func WaitForDocker(p Provisioner, dockerPort int) error {
if err := mcnutils.WaitForSpecific(checkDaemonUp(p, dockerPort), 10, 3*time.Second); err != nil {
return NewErrDaemonAvailable(err)
}

View File

@ -102,7 +102,7 @@ func TestMachinePortBoot2Docker(t *testing.T) {
p := &Boot2DockerProvisioner{
Driver: &fakedriver.Driver{},
}
dockerPort := 2376
dockerPort := engine.DefaultPort
bindURL := fmt.Sprintf("tcp://0.0.0.0:%d", dockerPort)
p.AuthOptions = auth.Options{
CaCertRemotePath: "/test/ca-cert",