diff --git a/commands/ls.go b/commands/ls.go index 4204e4be27..86303993f8 100644 --- a/commands/ls.go +++ b/commands/ls.go @@ -15,6 +15,7 @@ import ( "github.com/docker/machine/libmachine/engine" "github.com/docker/machine/libmachine/host" "github.com/docker/machine/libmachine/log" + "github.com/docker/machine/libmachine/mcndockerclient" "github.com/docker/machine/libmachine/persist" "github.com/docker/machine/libmachine/state" "github.com/docker/machine/libmachine/swarm" @@ -269,17 +270,35 @@ func matchesLabel(host *host.Host, labels []string) bool { return false } +// PERFORMANCE: The code of this function is complicated because we try +// to call the underlying drivers as less as possible to get the information +// we need. func attemptGetHostState(h *host.Host, stateQueryChan chan<- HostListItem) { url := "" - hostError := "" + currentState := state.None dockerVersion := "Unknown" + hostError := "" - currentState, err := h.Driver.GetState() + url, err := h.URL() + + // PERFORMANCE: if we have the url, it's ok to assume the host is running + // This reduces the number of calls to the drivers if err == nil { - url, err = h.URL() + if url != "" { + currentState = state.Running + } else { + currentState, err = h.Driver.GetState() + } + } else { + currentState, _ = h.Driver.GetState() } - if err == nil { - dockerVersion, err = h.DockerVersion() + + if err == nil && url != "" { + // PERFORMANCE: Reuse the url instead of asking the host again. + // This reduces the number of calls to the drivers + dockerHost := &mcndockerclient.RemoteDocker{url, h.AuthOptions()} + dockerVersion, err = mcndockerclient.DockerVersion(dockerHost) + if err != nil { dockerVersion = "Unknown" } else { diff --git a/commands/version.go b/commands/version.go index 467af675e4..a1a539040f 100644 --- a/commands/version.go +++ b/commands/version.go @@ -7,6 +7,7 @@ import ( "os" "github.com/docker/machine/libmachine" + "github.com/docker/machine/libmachine/mcndockerclient" ) func cmdVersion(c CommandLine, api libmachine.API) error { @@ -28,7 +29,7 @@ func printVersion(c CommandLine, api libmachine.API, out io.Writer) error { return err } - version, err := host.DockerVersion() + version, err := mcndockerclient.DockerVersion(host) if err != nil { return err } diff --git a/libmachine/host/host.go b/libmachine/host/host.go index b9cfb8fa6b..f2778ac0af 100644 --- a/libmachine/host/host.go +++ b/libmachine/host/host.go @@ -11,7 +11,6 @@ import ( "github.com/docker/machine/libmachine/drivers" "github.com/docker/machine/libmachine/engine" "github.com/docker/machine/libmachine/log" - "github.com/docker/machine/libmachine/mcndockerclient" "github.com/docker/machine/libmachine/mcnutils" "github.com/docker/machine/libmachine/provision" "github.com/docker/machine/libmachine/provision/pkgaction" @@ -165,13 +164,12 @@ func (h *Host) URL() (string, error) { } func (h *Host) AuthOptions() *auth.Options { + if h.HostOptions == nil { + return nil + } return h.HostOptions.AuthOptions } -func (h *Host) DockerVersion() (string, error) { - return mcndockerclient.DockerVersion(h) -} - func (h *Host) ConfigureAuth() error { provisioner, err := provision.DetectProvisioner(h.Driver) if err != nil { diff --git a/libmachine/mcndockerclient/docker_client.go b/libmachine/mcndockerclient/docker_client.go index 438bddd6ab..bfa3769c07 100644 --- a/libmachine/mcndockerclient/docker_client.go +++ b/libmachine/mcndockerclient/docker_client.go @@ -20,3 +20,26 @@ func DockerClient(host DockerHost) (*dockerclient.DockerClient, error) { return dockerclient.NewDockerClient(url, tlsConfig) } + +//CreateContainer creates a docker container. +func CreateContainer(dockerHost RemoteDocker, config *dockerclient.ContainerConfig, name string) error { + docker, err := DockerClient(dockerHost) + if err != nil { + return err + } + + if err = docker.PullImage(config.Image, nil); err != nil { + return fmt.Errorf("Unable to Pull Image: %s", err) + } + + containerID, err := docker.CreateContainer(config, name) + if err != nil { + return fmt.Errorf("Error while creating container: %s", err) + } + + if err = docker.StartContainer(containerID, &config.HostConfig); err != nil { + return fmt.Errorf("Error while starting container: %s", err) + } + + return nil +} diff --git a/libmachine/mcndockerclient/docker_host.go b/libmachine/mcndockerclient/docker_host.go index d9b10f3c5f..bcefd52f90 100644 --- a/libmachine/mcndockerclient/docker_host.go +++ b/libmachine/mcndockerclient/docker_host.go @@ -1,12 +1,18 @@ package mcndockerclient -import "github.com/docker/machine/libmachine/auth" +import ( + "fmt" + + "github.com/docker/machine/libmachine/auth" +) type URLer interface { + // URL returns the Docker host URL URL() (string, error) } type AuthOptionser interface { + // AuthOptions returns the authOptions AuthOptions() *auth.Options } @@ -14,3 +20,22 @@ type DockerHost interface { URLer AuthOptionser } + +type RemoteDocker struct { + HostURL string + AuthOption *auth.Options +} + +// URL returns the Docker host URL +func (rd RemoteDocker) URL() (string, error) { + if rd.HostURL == "" { + return "", fmt.Errorf("Docker Host URL not set") + } + + return rd.HostURL, nil +} + +// AuthOptions returns the authOptions +func (rd RemoteDocker) AuthOptions() *auth.Options { + return rd.AuthOption +} diff --git a/libmachine/provision/configure_swarm.go b/libmachine/provision/configure_swarm.go index 3576776648..9486eb05d7 100644 --- a/libmachine/provision/configure_swarm.go +++ b/libmachine/provision/configure_swarm.go @@ -7,6 +7,7 @@ import ( "github.com/docker/machine/libmachine/auth" "github.com/docker/machine/libmachine/log" + "github.com/docker/machine/libmachine/mcndockerclient" "github.com/docker/machine/libmachine/swarm" "github.com/samalba/dockerclient" ) @@ -34,11 +35,10 @@ func configureSwarm(p Provisioner, swarmOptions swarm.Options, authOptions auth. dockerPort := "2376" dockerDir := p.GetDockerOptionsDir() dockerHost := fmt.Sprintf("tcp://%s:%s", ip, dockerPort) - dockerClient := DockerClient{dockerHost, authOptions} + dockerClient := mcndockerclient.RemoteDocker{dockerHost, &authOptions} advertiseInfo := fmt.Sprintf("%s:%s", ip, dockerPort) if swarmOptions.Master { - cmd := fmt.Sprintf("manage --tlsverify --tlscacert=%s --tlscert=%s --tlskey=%s -H %s --strategy %s --advertise %s", authOptions.CaCertRemotePath, authOptions.ServerCertRemotePath, @@ -78,11 +78,10 @@ func configureSwarm(p Provisioner, swarmOptions swarm.Options, authOptions auth. HostConfig: masterHostConfig, } - err = CreateContainer(dockerClient, swarmMasterConfig, "swarm-agent-master") + err = mcndockerclient.CreateContainer(dockerClient, swarmMasterConfig, "swarm-agent-master") if err != nil { return err } - } workerHostConfig := dockerclient.HostConfig{ @@ -105,9 +104,5 @@ func configureSwarm(p Provisioner, swarmOptions swarm.Options, authOptions auth. HostConfig: workerHostConfig, } - if err = CreateContainer(dockerClient, swarmWorkerConfig, "swarm-agent"); err != nil { - return err - } - - return nil + return mcndockerclient.CreateContainer(dockerClient, swarmWorkerConfig, "swarm-agent") } diff --git a/libmachine/provision/docker.go b/libmachine/provision/docker.go deleted file mode 100644 index 754c36ab2e..0000000000 --- a/libmachine/provision/docker.go +++ /dev/null @@ -1,53 +0,0 @@ -package provision - -import ( - "fmt" - - "github.com/docker/machine/libmachine/auth" - "github.com/docker/machine/libmachine/mcndockerclient" - "github.com/samalba/dockerclient" -) - -// DockerClient implements DockerHost(mcndockerclient) interface -type DockerClient struct { - HostURL string - AuthOption auth.Options -} - -// URL returns the Docker host URL -func (dc DockerClient) URL() (string, error) { - if dc.HostURL == "" { - return "", fmt.Errorf("Docker Host URL not set") - } - - return dc.HostURL, nil -} - -// AuthOptions returns the authOptions -func (dc DockerClient) AuthOptions() *auth.Options { - return &dc.AuthOption -} - -//CreateContainer creates a docker container. -func CreateContainer(dockerHost DockerClient, config *dockerclient.ContainerConfig, name string) error { - - docker, err := mcndockerclient.DockerClient(dockerHost) - if err != nil { - return err - } - - if err = docker.PullImage(config.Image, nil); err != nil { - return fmt.Errorf("Unable to Pull Image: %s", err) - } - - containerID, err := docker.CreateContainer(config, name) - if err != nil { - return fmt.Errorf("Error while creating container: %s", err) - } - - if err = docker.StartContainer(containerID, &config.HostConfig); err != nil { - return fmt.Errorf("Error while starting container: %s", err) - } - - return nil -}