diff --git a/commands.go b/commands.go index fad11d7fbd..0b65108a1a 100644 --- a/commands.go +++ b/commands.go @@ -16,7 +16,7 @@ import ( "github.com/docker/machine/drivers" _ "github.com/docker/machine/drivers/amazonec2" - //_ "github.com/docker/machine/drivers/azure" + _ "github.com/docker/machine/drivers/azure" _ "github.com/docker/machine/drivers/digitalocean" //_ "github.com/docker/machine/drivers/google" //_ "github.com/docker/machine/drivers/hyperv" diff --git a/drivers/azure/azure.go b/drivers/azure/azure.go index 8af46b119c..3a311494cd 100644 --- a/drivers/azure/azure.go +++ b/drivers/azure/azure.go @@ -16,6 +16,7 @@ import ( "github.com/codegangsta/cli" "github.com/docker/docker/utils" "github.com/docker/machine/drivers" + "github.com/docker/machine/provider" "github.com/docker/machine/ssh" "github.com/docker/machine/state" ) @@ -31,9 +32,9 @@ type Driver struct { PublishSettingsFilePath string Location string Size string - UserName string UserPassword string Image string + SSHUser string SSHPort int DockerPort int CaCertPath string @@ -51,7 +52,7 @@ func init() { }) } -// GetCreateFlags registers the flags this driver adds to +// GetCreateFlags registers the flags this d adds to // "docker hosts create" func GetCreateFlags() []cli.Flag { return []cli.Flag{ @@ -111,16 +112,48 @@ func GetCreateFlags() []cli.Flag { } func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) { - driver := &Driver{MachineName: machineName, storePath: storePath, CaCertPath: caCert, PrivateKeyPath: privateKey} - return driver, nil + d := &Driver{MachineName: machineName, storePath: storePath, CaCertPath: caCert, PrivateKeyPath: privateKey} + return d, nil } -func (driver *Driver) DriverName() string { +func (d *Driver) AuthorizePort(ports []*drivers.Port) error { + return nil +} + +func (d *Driver) DeauthorizePort(ports []*drivers.Port) error { + return nil +} + +func (d *Driver) GetMachineName() string { + return d.MachineName +} + +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + +func (d *Driver) GetSSHKeyPath() string { + return filepath.Join(d.storePath, "id_rsa") +} + +func (d *Driver) GetSSHPort() (int, error) { + return d.SSHPort, nil +} + +func (d *Driver) GetSSHUsername() string { + return d.SSHUser +} + +func (d *Driver) GetProviderType() provider.ProviderType { + return provider.Remote +} + +func (d *Driver) DriverName() string { return "azure" } -func (driver *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { - driver.SubscriptionID = flags.String("azure-subscription-id") +func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { + d.SubscriptionID = flags.String("azure-subscription-id") cert := flags.String("azure-subscription-cert") publishSettings := flags.String("azure-publish-settings-file") @@ -131,51 +164,51 @@ func (driver *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { if _, err := os.Stat(cert); os.IsNotExist(err) { return err } - driver.SubscriptionCert = cert + d.SubscriptionCert = cert } if publishSettings != "" { if _, err := os.Stat(publishSettings); os.IsNotExist(err) { return err } - driver.PublishSettingsFilePath = publishSettings + d.PublishSettingsFilePath = publishSettings } - if (driver.SubscriptionID == "" || driver.SubscriptionCert == "") && driver.PublishSettingsFilePath == "" { + if (d.SubscriptionID == "" || d.SubscriptionCert == "") && d.PublishSettingsFilePath == "" { return fmt.Errorf("Please specify azure subscription params using options: --azure-subscription-id and --azure-subscription-cert or --azure-publish-settings-file") } if image == "" { - driver.Image = "b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04_1-LTS-amd64-server-20140927-en-us-30GB" + d.Image = "b39f27a8b8c64d52b05eac6a62ebad85__Ubuntu-14_04_1-LTS-amd64-server-20140927-en-us-30GB" } else { - driver.Image = image + d.Image = image } - driver.Location = flags.String("azure-location") - driver.Size = flags.String("azure-size") + d.Location = flags.String("azure-location") + d.Size = flags.String("azure-size") if strings.ToLower(username) == "docker" { return fmt.Errorf("'docker' is not valid user name for docker host. Please specify another user name") } - driver.UserName = username - driver.UserPassword = flags.String("azure-password") - driver.DockerPort = flags.Int("azure-docker-port") - driver.SSHPort = flags.Int("azure-ssh-port") - driver.SwarmMaster = flags.Bool("swarm-master") - driver.SwarmHost = flags.String("swarm-host") - driver.SwarmDiscovery = flags.String("swarm-discovery") + d.SSHUser = username + d.UserPassword = flags.String("azure-password") + d.DockerPort = flags.Int("azure-docker-port") + d.SSHPort = flags.Int("azure-ssh-port") + d.SwarmMaster = flags.Bool("swarm-master") + d.SwarmHost = flags.String("swarm-host") + d.SwarmDiscovery = flags.String("swarm-discovery") return nil } -func (driver *Driver) PreCreateCheck() error { - if err := driver.setUserSubscription(); err != nil { +func (d *Driver) PreCreateCheck() error { + if err := d.setUserSubscription(); err != nil { return err } // check azure DNS to make sure name is available - available, response, err := vmClient.CheckHostedServiceNameAvailability(driver.MachineName) + available, response, err := vmClient.CheckHostedServiceNameAvailability(d.MachineName) if err != nil { return err } @@ -187,83 +220,69 @@ func (driver *Driver) PreCreateCheck() error { return nil } -func (driver *Driver) Create() error { - if err := driver.setUserSubscription(); err != nil { +func (d *Driver) Create() error { + if err := d.setUserSubscription(); err != nil { return err } log.Info("Creating Azure machine...") - vmConfig, err := vmClient.CreateAzureVMConfiguration(driver.MachineName, driver.Size, driver.Image, driver.Location) + vmConfig, err := vmClient.CreateAzureVMConfiguration(d.MachineName, d.Size, d.Image, d.Location) if err != nil { return err } log.Debug("Generating certificate for Azure...") - if err := driver.generateCertForAzure(); err != nil { + if err := d.generateCertForAzure(); err != nil { return err } log.Debug("Adding Linux provisioning...") - vmConfig, err = vmClient.AddAzureLinuxProvisioningConfig(vmConfig, driver.UserName, driver.UserPassword, driver.azureCertPath(), driver.SSHPort) + user := d.GetSSHUsername() + port, err := d.GetSSHPort() + if err != nil { + return err + } + vmConfig, err = vmClient.AddAzureLinuxProvisioningConfig(vmConfig, user, d.UserPassword, d.azureCertPath(), port) if err != nil { return err } log.Debug("Authorizing ports...") - if err := driver.addDockerEndpoint(vmConfig); err != nil { + if err := d.addDockerEndpoint(vmConfig); err != nil { return err } log.Debug("Creating VM...") - if err := vmClient.CreateAzureVM(vmConfig, driver.MachineName, driver.Location); err != nil { + if err := vmClient.CreateAzureVM(vmConfig, d.MachineName, d.Location); err != nil { return err } log.Info("Waiting for SSH...") - log.Debugf("Host: %s SSH Port: %d", driver.getHostname(), driver.SSHPort) + log.Debugf("Host: %s SSH Port: %d", d.getHostname(), d.SSHPort) - if err := ssh.WaitForTCP(fmt.Sprintf("%s:%d", driver.getHostname(), driver.SSHPort)); err != nil { + if err := ssh.WaitForTCP(fmt.Sprintf("%s:%d", d.getHostname(), d.SSHPort)); err != nil { return err } return nil } -func (driver *Driver) runSSHCommand(command string, retries int) error { - cmd, err := driver.GetSSHCommand(command) - if err != nil { - return err - } - if err := cmd.Run(); err != nil { - if err.Error() == "exit status 255" { - if retries == 0 { - return err - } - return driver.runSSHCommand(command, retries-1) - } - - return err - } - - return nil -} - -func (driver *Driver) GetURL() (string, error) { - url := fmt.Sprintf("tcp://%s:%v", driver.getHostname(), driver.DockerPort) +func (d *Driver) GetURL() (string, error) { + url := fmt.Sprintf("tcp://%s:%v", d.getHostname(), d.DockerPort) return url, nil } -func (driver *Driver) GetIP() (string, error) { - return driver.getHostname(), nil +func (d *Driver) GetIP() (string, error) { + return d.getHostname(), nil } -func (driver *Driver) GetState() (state.State, error) { - err := driver.setUserSubscription() +func (d *Driver) GetState() (state.State, error) { + err := d.setUserSubscription() if err != nil { return state.Error, err } - dockerVM, err := vmClient.GetVMDeployment(driver.MachineName, driver.MachineName) + dockerVM, err := vmClient.GetVMDeployment(d.MachineName, d.MachineName) if err != nil { if strings.Contains(err.Error(), "Code: ResourceNotFound") { return state.Error, fmt.Errorf("Azure host was not found. Please check your Azure subscription.") @@ -285,13 +304,13 @@ func (driver *Driver) GetState() (state.State, error) { return state.None, nil } -func (driver *Driver) Start() error { - err := driver.setUserSubscription() +func (d *Driver) Start() error { + err := d.setUserSubscription() if err != nil { return err } - vmState, err := driver.GetState() + vmState, err := d.GetState() if err != nil { return err } @@ -300,29 +319,29 @@ func (driver *Driver) Start() error { return nil } - log.Debugf("starting %s", driver.MachineName) + log.Debugf("starting %s", d.MachineName) - err = vmClient.StartRole(driver.MachineName, driver.MachineName, driver.MachineName) + err = vmClient.StartRole(d.MachineName, d.MachineName, d.MachineName) if err != nil { return err } - err = driver.waitForSSH() + err = d.waitForSSH() if err != nil { return err } - err = driver.waitForDocker() + err = d.waitForDocker() if err != nil { return err } return nil } -func (driver *Driver) Stop() error { - err := driver.setUserSubscription() +func (d *Driver) Stop() error { + err := d.setUserSubscription() if err != nil { return err } - vmState, err := driver.GetState() + vmState, err := d.GetState() if err != nil { return err } @@ -331,21 +350,21 @@ func (driver *Driver) Stop() error { return nil } - log.Debugf("stopping %s", driver.MachineName) + log.Debugf("stopping %s", d.MachineName) - err = vmClient.ShutdownRole(driver.MachineName, driver.MachineName, driver.MachineName) + err = vmClient.ShutdownRole(d.MachineName, d.MachineName, d.MachineName) if err != nil { return err } return nil } -func (driver *Driver) Remove() error { - err := driver.setUserSubscription() +func (d *Driver) Remove() error { + err := d.setUserSubscription() if err != nil { return err } - available, _, err := vmClient.CheckHostedServiceNameAvailability(driver.MachineName) + available, _, err := vmClient.CheckHostedServiceNameAvailability(d.MachineName) if err != nil { return err } @@ -353,9 +372,9 @@ func (driver *Driver) Remove() error { return nil } - log.Debugf("removing %s", driver.MachineName) + log.Debugf("removing %s", d.MachineName) - err = vmClient.DeleteHostedService(driver.MachineName) + err = vmClient.DeleteHostedService(d.MachineName) if err != nil { return err } @@ -363,12 +382,12 @@ func (driver *Driver) Remove() error { return nil } -func (driver *Driver) Restart() error { - err := driver.setUserSubscription() +func (d *Driver) Restart() error { + err := d.setUserSubscription() if err != nil { return err } - vmState, err := driver.GetState() + vmState, err := d.GetState() if err != nil { return err } @@ -376,29 +395,29 @@ func (driver *Driver) Restart() error { return fmt.Errorf("Host is already stopped, use start command to run it") } - log.Debugf("restarting %s", driver.MachineName) + log.Debugf("restarting %s", d.MachineName) - err = vmClient.RestartRole(driver.MachineName, driver.MachineName, driver.MachineName) + err = vmClient.RestartRole(d.MachineName, d.MachineName, d.MachineName) if err != nil { return err } - err = driver.waitForSSH() + err = d.waitForSSH() if err != nil { return err } - err = driver.waitForDocker() + err = d.waitForDocker() if err != nil { return err } return nil } -func (driver *Driver) Kill() error { - err := driver.setUserSubscription() +func (d *Driver) Kill() error { + err := d.setUserSubscription() if err != nil { return err } - vmState, err := driver.GetState() + vmState, err := d.GetState() if err != nil { return err } @@ -407,102 +426,40 @@ func (driver *Driver) Kill() error { return nil } - log.Debugf("killing %s", driver.MachineName) + log.Debugf("killing %s", d.MachineName) - err = vmClient.ShutdownRole(driver.MachineName, driver.MachineName, driver.MachineName) + err = vmClient.ShutdownRole(d.MachineName, d.MachineName, d.MachineName) if err != nil { return err } return nil } -func (d *Driver) StartDocker() error { - log.Debug("Starting Docker...") - - cmd, err := d.GetSSHCommand("sudo service docker start") - if err != nil { - return err - } - if err := cmd.Run(); err != nil { - return err - } - - return nil -} - -func (d *Driver) StopDocker() error { - log.Debug("Stopping Docker...") - - cmd, err := d.GetSSHCommand("sudo service docker stop") - if err != nil { - return err - } - if err := cmd.Run(); err != nil { - return err - } - - return nil -} - func (d *Driver) GetDockerConfigDir() string { return dockerConfigDir } -func (driver *Driver) GetSSHCommand(args ...string) (*exec.Cmd, error) { - err := driver.setUserSubscription() - if err != nil { - return nil, err - } - - vmState, err := driver.GetState() - if err != nil { - return nil, err - } - - if vmState == state.Stopped { - return nil, fmt.Errorf("Azure host is stopped. Please start it before using ssh command.") - } - - return ssh.GetSSHCommand(driver.getHostname(), driver.SSHPort, driver.UserName, driver.sshKeyPath(), args...), nil -} - -func (driver *Driver) Upgrade() error { - log.Debugf("Upgrading Docker") - - cmd, err := driver.GetSSHCommand("sudo apt-get update && sudo apt-get install --upgrade lxc-docker") - if err != nil { - return err - - } - if err := cmd.Run(); err != nil { - return err - - } - - return cmd.Run() -} - func generateVMName() string { randomID := utils.TruncateID(utils.GenerateRandomID()) return fmt.Sprintf("docker-host-%s", randomID) } -func (driver *Driver) setUserSubscription() error { - if len(driver.PublishSettingsFilePath) != 0 { - err := azure.ImportPublishSettingsFile(driver.PublishSettingsFilePath) +func (d *Driver) setUserSubscription() error { + if len(d.PublishSettingsFilePath) != 0 { + err := azure.ImportPublishSettingsFile(d.PublishSettingsFilePath) if err != nil { return err } return nil } - err := azure.ImportPublishSettings(driver.SubscriptionID, driver.SubscriptionCert) + err := azure.ImportPublishSettings(d.SubscriptionID, d.SubscriptionCert) if err != nil { return err } return nil } -func (driver *Driver) addDockerEndpoint(vmConfig *vmClient.Role) error { +func (d *Driver) addDockerEndpoint(vmConfig *vmClient.Role) error { configSets := vmConfig.ConfigurationSets.ConfigurationSet if len(configSets) == 0 { return fmt.Errorf("no configuration set") @@ -514,17 +471,17 @@ func (driver *Driver) addDockerEndpoint(vmConfig *vmClient.Role) error { ep := vmClient.InputEndpoint{} ep.Name = "docker" ep.Protocol = "tcp" - ep.Port = driver.DockerPort - ep.LocalPort = driver.DockerPort + ep.Port = d.DockerPort + ep.LocalPort = d.DockerPort configSets[i].InputEndpoints.InputEndpoint = append(configSets[i].InputEndpoints.InputEndpoint, ep) - log.Debugf("added Docker endpoint (port %d) to configuration", driver.DockerPort) + log.Debugf("added Docker endpoint (port %d) to configuration", d.DockerPort) } return nil } -func (driver *Driver) waitForSSH() error { +func (d *Driver) waitForSSH() error { log.Infof("Waiting for SSH...") - err := ssh.WaitForTCP(fmt.Sprintf("%s:%v", driver.getHostname(), driver.SSHPort)) + err := ssh.WaitForTCP(fmt.Sprintf("%s:%v", d.getHostname(), d.SSHPort)) if err != nil { return err } @@ -532,10 +489,10 @@ func (driver *Driver) waitForSSH() error { return nil } -func (driver *Driver) waitForDocker() error { +func (d *Driver) waitForDocker() error { log.Infof("Waiting for docker daemon on host to be available...") maxRepeats := 48 - url := fmt.Sprintf("%s:%v", driver.getHostname(), driver.DockerPort) + url := fmt.Sprintf("%s:%v", d.getHostname(), d.DockerPort) success := waitForDockerEndpoint(url, maxRepeats) if !success { return fmt.Errorf("Can not run docker daemon on remote machine. Please try again.") @@ -561,12 +518,14 @@ func waitForDockerEndpoint(url string, maxRepeats int) bool { return true } -func (driver *Driver) generateCertForAzure() error { - if err := ssh.GenerateSSHKey(driver.sshKeyPath()); err != nil { +func (d *Driver) generateCertForAzure() error { + keyPath := d.GetSSHKeyPath() + + if err := ssh.GenerateSSHKey(keyPath); err != nil { return err } - cmd := exec.Command("openssl", "req", "-x509", "-key", driver.sshKeyPath(), "-nodes", "-days", "365", "-newkey", "rsa:2048", "-out", driver.azureCertPath(), "-subj", "/C=AU/ST=Some-State/O=InternetWidgitsPtyLtd/CN=\\*") + cmd := exec.Command("openssl", "req", "-x509", "-key", keyPath, "-nodes", "-days", "365", "-newkey", "rsa:2048", "-out", d.azureCertPath(), "-subj", "/C=AU/ST=Some-State/O=InternetWidgitsPtyLtd/CN=\\*") if err := cmd.Run(); err != nil { return err } @@ -574,18 +533,14 @@ func (driver *Driver) generateCertForAzure() error { return nil } -func (driver *Driver) sshKeyPath() string { - return filepath.Join(driver.storePath, "id_rsa") +func (d *Driver) publicSSHKeyPath() string { + return d.GetSSHKeyPath() + ".pub" } -func (driver *Driver) publicSSHKeyPath() string { - return driver.sshKeyPath() + ".pub" +func (d *Driver) azureCertPath() string { + return filepath.Join(d.storePath, "azure_cert.pem") } -func (driver *Driver) azureCertPath() string { - return filepath.Join(driver.storePath, "azure_cert.pem") -} - -func (driver *Driver) getHostname() string { - return driver.MachineName + ".cloudapp.net" +func (d *Driver) getHostname() string { + return d.MachineName + ".cloudapp.net" } diff --git a/drivers/drivers.go b/drivers/drivers.go index d0627b5549..46ad7eacdb 100644 --- a/drivers/drivers.go +++ b/drivers/drivers.go @@ -3,10 +3,12 @@ package drivers import ( "errors" "fmt" + "os/exec" "sort" "github.com/codegangsta/cli" "github.com/docker/machine/provider" + "github.com/docker/machine/ssh" "github.com/docker/machine/state" ) @@ -156,3 +158,20 @@ type DriverOptions interface { Int(key string) int Bool(key string) bool } + +func GetSSHCommandFromDriver(d Driver, args ...string) (*exec.Cmd, error) { + host, err := d.GetSSHHostname() + if err != nil { + return nil, err + } + + port, err := d.GetSSHPort() + if err != nil { + return nil, err + } + + user := d.GetSSHUsername() + keyPath := d.GetSSHKeyPath() + + return ssh.GetSSHCommand(host, port, user, keyPath, args...), nil +} diff --git a/drivers/virtualbox/virtualbox.go b/drivers/virtualbox/virtualbox.go index 21e53f84f4..d218a00745 100644 --- a/drivers/virtualbox/virtualbox.go +++ b/drivers/virtualbox/virtualbox.go @@ -461,24 +461,6 @@ func (d *Driver) setMachineNameIfNotSet() { } } -// getSSHCommand returns a command suitable for ssh -func (d *Driver) getSSHCommand(args ...string) (*exec.Cmd, error) { - host, err := d.GetSSHHostname() - if err != nil { - return nil, err - } - - port, err := d.GetSSHPort() - if err != nil { - return nil, err - } - - user := d.GetSSHUsername() - keyPath := d.GetSSHKeyPath() - - return ssh.GetSSHCommand(host, port, user, keyPath, args...), nil -} - func (d *Driver) GetIP() (string, error) { // DHCP is used to get the IP, so virtualbox hosts don't have IPs unless // they are running @@ -489,7 +471,7 @@ func (d *Driver) GetIP() (string, error) { if s != state.Running { return "", drivers.ErrHostIsNotRunning } - cmd, err := d.getSSHCommand("ip addr show dev eth1") + cmd, err := drivers.GetSSHCommandFromDriver(d, "ip addr show dev eth1") if err != nil { return "", err } diff --git a/host.go b/host.go index 7ff301a995..f365270533 100644 --- a/host.go +++ b/host.go @@ -117,6 +117,8 @@ func (h *Host) GetDockerConfigDir() (string, error) { return "/var/lib/boot2docker", nil case provider.Remote: return "/etc/default", nil + case provider.None: + return "", nil default: return "", ErrUnknownHypervisorType }