diff --git a/drivers/amazonec2/amazonec2.go b/drivers/amazonec2/amazonec2.go index 535ead0b81..72dd69e82f 100644 --- a/drivers/amazonec2/amazonec2.go +++ b/drivers/amazonec2/amazonec2.go @@ -470,6 +470,12 @@ func (d *Driver) GetState() (state.State, error) { } } +// GetSSHHostname - +func (d *Driver) GetSSHHostname() (string, error) { + // TODO: use @nathanleclaire retry func here (ehazlett) + return d.GetIP() +} + func (d *Driver) GetSSHUsername() string { if d.SSHUser == "" { d.SSHUser = "ubuntu" diff --git a/drivers/azure/azure.go b/drivers/azure/azure.go index b645ea80f8..27b578c678 100644 --- a/drivers/azure/azure.go +++ b/drivers/azure/azure.go @@ -119,6 +119,10 @@ func NewDriver(hostName, storePath string) drivers.Driver { return d } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) GetSSHUsername() string { if d.SSHUser == "" { d.SSHUser = "ubuntu" diff --git a/drivers/digitalocean/digitalocean.go b/drivers/digitalocean/digitalocean.go index 5232860025..366802d1f5 100644 --- a/drivers/digitalocean/digitalocean.go +++ b/drivers/digitalocean/digitalocean.go @@ -97,6 +97,10 @@ func NewDriver(hostName, storePath string) *Driver { } } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) DriverName() string { return "digitalocean" } @@ -226,6 +230,13 @@ func (d *Driver) GetURL() (string, error) { return fmt.Sprintf("tcp://%s:2376", ip), nil } +func (d *Driver) GetIP() (string, error) { + if d.IPAddress == "" { + return "", fmt.Errorf("IP address is not set") + } + return d.IPAddress, nil +} + func (d *Driver) GetState() (state.State, error) { droplet, _, err := d.getClient().Droplets.Get(d.DropletID) if err != nil { diff --git a/drivers/exoscale/exoscale.go b/drivers/exoscale/exoscale.go index de798f7bf2..e083e3f0d5 100644 --- a/drivers/exoscale/exoscale.go +++ b/drivers/exoscale/exoscale.go @@ -103,6 +103,10 @@ func NewDriver(hostName, storePath string) drivers.Driver { } } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) GetSSHUsername() string { return "ubuntu" } @@ -146,6 +150,13 @@ func (d *Driver) GetURL() (string, error) { return fmt.Sprintf("tcp://%s:2376", ip), nil } +func (d *Driver) GetIP() (string, error) { + if d.IPAddress == "" { + return "", fmt.Errorf("IP address is not set") + } + return d.IPAddress, nil +} + func (d *Driver) GetState() (state.State, error) { client := egoscale.NewClient(d.URL, d.ApiKey, d.ApiSecretKey) vm, err := client.GetVirtualMachine(d.Id) diff --git a/drivers/generic/generic.go b/drivers/generic/generic.go index 311a6d6591..57a47f1702 100644 --- a/drivers/generic/generic.go +++ b/drivers/generic/generic.go @@ -1,12 +1,10 @@ package generic import ( - "errors" "fmt" "net" "os" "path/filepath" - "strconv" "time" "github.com/docker/machine/libmachine/drivers" @@ -18,50 +16,21 @@ import ( type Driver struct { *drivers.BaseDriver - sourceSSHKey string + SSHKey string } const ( - driverName = "generic" + defaultSSHUser = "root" + defaultSSHPort = 22 defaultTimeout = 1 * time.Second ) var ( - defaultSourceSSHKey = filepath.Join(mcnutils.GetHomeDir(), ".ssh", "id_rsa") + defaultSSHKey = filepath.Join(mcnutils.GetHomeDir(), ".ssh", "id_rsa") ) -// NewDriver creates and returns a new instance of the driver -func NewDriver(hostName, storePath string) drivers.Driver { - return &Driver{ - BaseDriver: &drivers.BaseDriver{ - MachineName: hostName, - StorePath: storePath, - }, - sourceSSHKey: defaultSourceSSHKey, - } -} - -func (d *Driver) Create() error { - log.Info("Importing SSH key...") - - // TODO: validate the key is a valid key - if err := mcnutils.CopyFile(d.sourceSSHKey, d.GetSSHKeyPath()); err != nil { - return fmt.Errorf("unable to copy ssh key: %s", err) - } - - if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil { - return fmt.Errorf("unable to set permissions on the ssh key: %s", err) - } - - log.Debugf("IP: %s", d.IPAddress) - - return nil -} - -func (d *Driver) DriverName() string { - return driverName -} - +// GetCreateFlags registers the flags this driver adds to +// "docker hosts create" func (d *Driver) GetCreateFlags() []mcnflag.Flag { return []mcnflag.Flag{ mcnflag.StringFlag{ @@ -71,31 +40,81 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag { mcnflag.StringFlag{ Name: "generic-ssh-user", Usage: "SSH user", - Value: drivers.DefaultSSHUser, + Value: defaultSSHUser, }, mcnflag.StringFlag{ Name: "generic-ssh-key", Usage: "SSH private key path", - Value: defaultSourceSSHKey, + Value: defaultSSHKey, }, mcnflag.IntFlag{ Name: "generic-ssh-port", Usage: "SSH port", - Value: drivers.DefaultSSHPort, + Value: defaultSSHPort, }, } } -func (d *Driver) GetState() (state.State, error) { - address := net.JoinHostPort(d.IPAddress, strconv.Itoa(d.SSHPort)) - _, err := net.DialTimeout("tcp", address, defaultTimeout) - var st state.State - if err != nil { - st = state.Stopped - } else { - st = state.Running +// NewDriver creates and returns a new instance of the driver +func NewDriver(hostName, storePath string) drivers.Driver { + return &Driver{ + SSHKey: defaultSSHKey, + BaseDriver: &drivers.BaseDriver{ + SSHUser: defaultSSHUser, + SSHPort: defaultSSHPort, + MachineName: hostName, + StorePath: storePath, + }, } - return st, nil +} + +func (d *Driver) DriverName() string { + return "generic" +} + +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + +func (d *Driver) GetSSHUsername() string { + return d.SSHUser +} + +func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { + d.IPAddress = flags.String("generic-ip-address") + d.SSHUser = flags.String("generic-ssh-user") + d.SSHKey = flags.String("generic-ssh-key") + d.SSHPort = flags.Int("generic-ssh-port") + + if d.IPAddress == "" { + return fmt.Errorf("generic driver requires the --generic-ip-address option") + } + + if d.SSHKey == "" { + return fmt.Errorf("generic driver requires the --generic-ssh-key option") + } + + return nil +} + +func (d *Driver) PreCreateCheck() error { + return nil +} + +func (d *Driver) Create() error { + log.Infof("Importing SSH key...") + + if err := mcnutils.CopyFile(d.SSHKey, d.GetSSHKeyPath()); err != nil { + return fmt.Errorf("unable to copy ssh key: %s", err) + } + + if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil { + return err + } + + log.Debugf("IP: %s", d.IPAddress) + + return nil } func (d *Driver) GetURL() (string, error) { @@ -106,10 +125,31 @@ func (d *Driver) GetURL() (string, error) { return fmt.Sprintf("tcp://%s:2376", ip), nil } -func (d *Driver) Kill() error { - log.Debug("Killing...") - _, err := drivers.RunSSHCommandFromDriver(d, "sudo shutdown -P now") - return err +func (d *Driver) GetIP() (string, error) { + if d.IPAddress == "" { + return "", fmt.Errorf("IP address is not set") + } + return d.IPAddress, nil +} + +func (d *Driver) GetState() (state.State, error) { + addr := fmt.Sprintf("%s:%d", d.IPAddress, d.SSHPort) + _, err := net.DialTimeout("tcp", addr, defaultTimeout) + var st state.State + if err != nil { + st = state.Stopped + } else { + st = state.Running + } + return st, nil +} + +func (d *Driver) Start() error { + return fmt.Errorf("generic driver does not support start") +} + +func (d *Driver) Stop() error { + return fmt.Errorf("generic driver does not support stop") } func (d *Driver) Remove() error { @@ -118,31 +158,24 @@ func (d *Driver) Remove() error { func (d *Driver) Restart() error { log.Debug("Restarting...") - _, err := drivers.RunSSHCommandFromDriver(d, "sudo shutdown -r now") - return err -} -func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { - d.IPAddress = flags.String("generic-ip-address") - d.SSHUser = flags.String("generic-ssh-user") - d.sourceSSHKey = flags.String("generic-ssh-key") - d.SSHPort = flags.Int("generic-ssh-port") - - if d.IPAddress == "" { - return errors.New("generic driver requires the --generic-ip-address option") - } - - if d.sourceSSHKey == "" { - return errors.New("generic driver requires the --generic-ssh-key option") + if _, err := drivers.RunSSHCommandFromDriver(d, "sudo shutdown -r now"); err != nil { + return err } return nil } -func (d *Driver) Start() error { - return errors.New("generic driver does not support start") +func (d *Driver) Kill() error { + log.Debug("Killing...") + + if _, err := drivers.RunSSHCommandFromDriver(d, "sudo shutdown -P now"); err != nil { + return err + } + + return nil } -func (d *Driver) Stop() error { - return errors.New("generic driver does not support stop") +func (d *Driver) publicSSHKeyPath() string { + return d.GetSSHKeyPath() + ".pub" } diff --git a/drivers/google/google.go b/drivers/google/google.go index acfd566929..4f1f3c1ba4 100644 --- a/drivers/google/google.go +++ b/drivers/google/google.go @@ -120,6 +120,11 @@ func NewDriver(machineName string, storePath string) *Driver { } } +// GetSSHHostname returns hostname for use with ssh +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + // GetSSHUsername returns username for use with ssh func (d *Driver) GetSSHUsername() string { if d.SSHUser == "" { diff --git a/drivers/hyperv/hyperv.go b/drivers/hyperv/hyperv.go index e9619f5e83..c49d5a4e13 100644 --- a/drivers/hyperv/hyperv.go +++ b/drivers/hyperv/hyperv.go @@ -85,6 +85,10 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { return nil } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) GetSSHUsername() string { if d.SSHUser == "" { d.SSHUser = "docker" diff --git a/drivers/openstack/openstack.go b/drivers/openstack/openstack.go index 3aa9af8faa..fc5e9e03ba 100644 --- a/drivers/openstack/openstack.go +++ b/drivers/openstack/openstack.go @@ -218,6 +218,10 @@ func NewDerivedDriver(hostName, storePath string) *Driver { } } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) DriverName() string { return "openstack" } diff --git a/drivers/softlayer/driver.go b/drivers/softlayer/driver.go index f3f06ca191..5352d3406a 100644 --- a/drivers/softlayer/driver.go +++ b/drivers/softlayer/driver.go @@ -73,6 +73,10 @@ func NewDriver(hostName, storePath string) drivers.Driver { } } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) GetCreateFlags() []mcnflag.Flag { // Set hourly billing to true by default since codegangsta cli doesn't take default bool values if os.Getenv("SOFTLAYER_HOURLY_BILLING") == "" { diff --git a/drivers/vmwarefusion/fusion.go b/drivers/vmwarefusion/fusion.go index 631a44fd1b..c33db46d67 100644 --- a/drivers/vmwarefusion/fusion.go +++ b/drivers/vmwarefusion/fusion.go @@ -119,6 +119,10 @@ func NewDriver(hostName, storePath string) drivers.Driver { } } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) GetSSHUsername() string { if d.SSHUser == "" { d.SSHUser = "docker" diff --git a/drivers/vmwarevcloudair/vcloudair.go b/drivers/vmwarevcloudair/vcloudair.go index a09998a4e0..285ada3e80 100644 --- a/drivers/vmwarevcloudair/vcloudair.go +++ b/drivers/vmwarevcloudair/vcloudair.go @@ -138,6 +138,10 @@ func NewDriver(hostName, storePath string) drivers.Driver { } } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + // Driver interface implementation func (d *Driver) DriverName() string { return "vmwarevcloudair" diff --git a/drivers/vmwarevsphere/vsphere.go b/drivers/vmwarevsphere/vsphere.go index 642655c142..0f5000800b 100644 --- a/drivers/vmwarevsphere/vsphere.go +++ b/drivers/vmwarevsphere/vsphere.go @@ -135,6 +135,10 @@ func NewDriver(hostName, storePath string) drivers.Driver { } } +func (d *Driver) GetSSHHostname() (string, error) { + return d.GetIP() +} + func (d *Driver) GetSSHUsername() string { if d.SSHUser == "" { d.SSHUser = "docker" diff --git a/libmachine/drivers/base.go b/libmachine/drivers/base.go index 69b34758b4..17bd097dd8 100644 --- a/libmachine/drivers/base.go +++ b/libmachine/drivers/base.go @@ -1,29 +1,23 @@ package drivers -import ( - "errors" - "fmt" - "net" - "path/filepath" -) - -const ( - DefaultSSHUser = "root" - DefaultSSHPort = 22 -) +import "path/filepath" // BaseDriver - Embed this struct into drivers to provide the common set // of fields and functions. type BaseDriver struct { IPAddress string - MachineName string - SSHKeyPath string - SSHPort int SSHUser string - StorePath string + SSHPort int + MachineName string SwarmMaster bool SwarmHost string SwarmDiscovery string + StorePath string +} + +// GetSSHKeyPath - +func (d *BaseDriver) GetSSHKeyPath() string { + return filepath.Join(d.StorePath, "machines", d.MachineName, "id_rsa") } // DriverName returns the name of the driver @@ -32,39 +26,19 @@ func (d *BaseDriver) DriverName() string { } // GetIP returns the ip -func (d *BaseDriver) GetIP() (string, error) { - if d.IPAddress == "" { - return "", errors.New("IP address is not set") - } - ip := net.ParseIP(d.IPAddress) - if ip == nil { - return "", fmt.Errorf("IP address is invalid: %s", d.IPAddress) - } - return d.IPAddress, nil -} - -// GetMachineName returns the machine name func (d *BaseDriver) GetMachineName() string { return d.MachineName } -// GetSSHHostname returns hostname for use with ssh -func (d *BaseDriver) GetSSHHostname() (string, error) { - return d.GetIP() -} - -// GetSSHKeyPath returns the ssh key path -func (d *BaseDriver) GetSSHKeyPath() string { - if d.SSHKeyPath == "" { - d.SSHKeyPath = d.ResolveStorePath("id_rsa") - } - return d.SSHKeyPath +// ResolveStorePath - +func (d *BaseDriver) ResolveStorePath(file string) string { + return filepath.Join(d.StorePath, "machines", d.MachineName, file) } // GetSSHPort returns the ssh port, 22 if not specified func (d *BaseDriver) GetSSHPort() (int, error) { if d.SSHPort == 0 { - d.SSHPort = DefaultSSHPort + d.SSHPort = 22 } return d.SSHPort, nil @@ -73,7 +47,7 @@ func (d *BaseDriver) GetSSHPort() (int, error) { // GetSSHUsername returns the ssh user name, root if not specified func (d *BaseDriver) GetSSHUsername() string { if d.SSHUser == "" { - d.SSHUser = DefaultSSHUser + d.SSHUser = "root" } return d.SSHUser @@ -83,8 +57,3 @@ func (d *BaseDriver) GetSSHUsername() string { func (d *BaseDriver) PreCreateCheck() error { return nil } - -// ResolveStorePath returns the store path where the machine is -func (d *BaseDriver) ResolveStorePath(file string) string { - return filepath.Join(d.StorePath, "machines", d.MachineName, file) -} diff --git a/libmachine/drivers/base_test.go b/libmachine/drivers/base_test.go deleted file mode 100644 index 3d62f8bb2e..0000000000 --- a/libmachine/drivers/base_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package drivers - -import ( - "errors" - "fmt" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestIP(t *testing.T) { - cases := []struct { - baseDriver *BaseDriver - expectedIp string - expectedErr error - }{ - {&BaseDriver{}, "", errors.New("IP address is not set")}, - {&BaseDriver{IPAddress: "2001:4860:0:2001::68"}, "2001:4860:0:2001::68", nil}, - {&BaseDriver{IPAddress: "192.168.0.1"}, "192.168.0.1", nil}, - {&BaseDriver{IPAddress: "::1"}, "::1", nil}, - {&BaseDriver{IPAddress: "whatever"}, "", fmt.Errorf("IP address is invalid: %s", "whatever")}, - } - - for _, c := range cases { - ip, err := c.baseDriver.GetIP() - assert.Equal(t, c.expectedIp, ip) - assert.Equal(t, c.expectedErr, err) - } -}