FIX #2663 reduce calls to the driver in ls

Signed-off-by: David Gageot <david@gageot.net>
This commit is contained in:
David Gageot 2015-12-23 12:20:20 +01:00
parent 9f6764ccd3
commit 670c4808ed
7 changed files with 82 additions and 74 deletions

View File

@ -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 {

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}

View File

@ -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")
}

View File

@ -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
}