769 lines
18 KiB
Go
769 lines
18 KiB
Go
package openstack
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os/exec"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
log "github.com/Sirupsen/logrus"
|
|
"github.com/codegangsta/cli"
|
|
"github.com/docker/docker/utils"
|
|
"github.com/docker/machine/drivers"
|
|
"github.com/docker/machine/ssh"
|
|
"github.com/docker/machine/state"
|
|
)
|
|
|
|
const (
|
|
dockerConfigDir = "/etc/docker"
|
|
)
|
|
|
|
type Driver struct {
|
|
AuthUrl string
|
|
Insecure bool
|
|
Username string
|
|
Password string
|
|
TenantName string
|
|
TenantId string
|
|
Region string
|
|
EndpointType string
|
|
MachineName string
|
|
MachineId string
|
|
FlavorName string
|
|
FlavorId string
|
|
ImageName string
|
|
ImageId string
|
|
KeyPairName string
|
|
NetworkName string
|
|
NetworkId string
|
|
SecurityGroups []string
|
|
FloatingIpPool string
|
|
FloatingIpPoolId string
|
|
SSHUser string
|
|
SSHPort int
|
|
Ip string
|
|
CaCertPath string
|
|
PrivateKeyPath string
|
|
storePath string
|
|
SwarmMaster bool
|
|
SwarmHost string
|
|
SwarmDiscovery string
|
|
client Client
|
|
}
|
|
|
|
type CreateFlags struct {
|
|
AuthUrl *string
|
|
Insecure *bool
|
|
Username *string
|
|
Password *string
|
|
TenantName *string
|
|
TenantId *string
|
|
Region *string
|
|
EndpointType *string
|
|
FlavorName *string
|
|
FlavorId *string
|
|
ImageName *string
|
|
ImageId *string
|
|
NetworkName *string
|
|
NetworkId *string
|
|
SecurityGroups *string
|
|
FloatingIpPool *string
|
|
SSHUser *string
|
|
SSHPort *int
|
|
}
|
|
|
|
func init() {
|
|
drivers.Register("openstack", &drivers.RegisteredDriver{
|
|
New: NewDriver,
|
|
GetCreateFlags: GetCreateFlags,
|
|
})
|
|
}
|
|
|
|
func GetCreateFlags() []cli.Flag {
|
|
return []cli.Flag{
|
|
cli.StringFlag{
|
|
EnvVar: "OS_AUTH_URL",
|
|
Name: "openstack-auth-url",
|
|
Usage: "OpenStack authentication URL",
|
|
Value: "",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "openstack-insecure",
|
|
Usage: "Disable TLS credential checking.",
|
|
},
|
|
cli.StringFlag{
|
|
EnvVar: "OS_USERNAME",
|
|
Name: "openstack-username",
|
|
Usage: "OpenStack username",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
EnvVar: "OS_PASSWORD",
|
|
Name: "openstack-password",
|
|
Usage: "OpenStack password",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
EnvVar: "OS_TENANT_NAME",
|
|
Name: "openstack-tenant-name",
|
|
Usage: "OpenStack tenant name",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
EnvVar: "OS_TENANT_ID",
|
|
Name: "openstack-tenant-id",
|
|
Usage: "OpenStack tenant id",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
EnvVar: "OS_REGION_NAME",
|
|
Name: "openstack-region",
|
|
Usage: "OpenStack region name",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
EnvVar: "OS_ENDPOINT_TYPE",
|
|
Name: "openstack-endpoint-type",
|
|
Usage: "OpenStack endpoint type (adminURL, internalURL or publicURL)",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-flavor-id",
|
|
Usage: "OpenStack flavor id to use for the instance",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-flavor-name",
|
|
Usage: "OpenStack flavor name to use for the instance",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-image-id",
|
|
Usage: "OpenStack image id to use for the instance",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-image-name",
|
|
Usage: "OpenStack image name to use for the instance",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-net-id",
|
|
Usage: "OpenStack network id the machine will be connected on",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-net-name",
|
|
Usage: "OpenStack network name the machine will be connected on",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-sec-groups",
|
|
Usage: "OpenStack comma separated security groups for the machine",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-floatingip-pool",
|
|
Usage: "OpenStack floating IP pool to get an IP from to assign to the instance",
|
|
Value: "",
|
|
},
|
|
cli.StringFlag{
|
|
Name: "openstack-ssh-user",
|
|
Usage: "OpenStack SSH user",
|
|
Value: "root",
|
|
},
|
|
cli.IntFlag{
|
|
Name: "openstack-ssh-port",
|
|
Usage: "OpenStack SSH port",
|
|
Value: 22,
|
|
},
|
|
}
|
|
}
|
|
|
|
func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) {
|
|
log.WithFields(log.Fields{
|
|
"machineName": machineName,
|
|
"storePath": storePath,
|
|
"caCert": caCert,
|
|
"privateKey": privateKey,
|
|
}).Debug("Instantiating OpenStack driver...")
|
|
|
|
return NewDerivedDriver(machineName, storePath, &GenericClient{}, caCert, privateKey)
|
|
}
|
|
|
|
func NewDerivedDriver(machineName string, storePath string, client Client, caCert string, privateKey string) (*Driver, error) {
|
|
return &Driver{
|
|
MachineName: machineName,
|
|
storePath: storePath,
|
|
client: client,
|
|
CaCertPath: caCert,
|
|
PrivateKeyPath: privateKey,
|
|
}, nil
|
|
}
|
|
|
|
func (d *Driver) DriverName() string {
|
|
return "openstack"
|
|
}
|
|
|
|
func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
|
|
d.AuthUrl = flags.String("openstack-auth-url")
|
|
d.Insecure = flags.Bool("openstack-insecure")
|
|
d.Username = flags.String("openstack-username")
|
|
d.Password = flags.String("openstack-password")
|
|
d.TenantName = flags.String("openstack-tenant-name")
|
|
d.TenantId = flags.String("openstack-tenant-id")
|
|
d.Region = flags.String("openstack-region")
|
|
d.EndpointType = flags.String("openstack-endpoint-type")
|
|
d.FlavorId = flags.String("openstack-flavor-id")
|
|
d.FlavorName = flags.String("openstack-flavor-name")
|
|
d.ImageId = flags.String("openstack-image-id")
|
|
d.ImageName = flags.String("openstack-image-name")
|
|
d.NetworkId = flags.String("openstack-net-id")
|
|
d.NetworkName = flags.String("openstack-net-name")
|
|
if flags.String("openstack-sec-groups") != "" {
|
|
d.SecurityGroups = strings.Split(flags.String("openstack-sec-groups"), ",")
|
|
}
|
|
d.FloatingIpPool = flags.String("openstack-floatingip-pool")
|
|
d.SSHUser = flags.String("openstack-ssh-user")
|
|
d.SSHPort = flags.Int("openstack-ssh-port")
|
|
d.SwarmMaster = flags.Bool("swarm-master")
|
|
d.SwarmHost = flags.String("swarm-host")
|
|
d.SwarmDiscovery = flags.String("swarm-discovery")
|
|
|
|
return d.checkConfig()
|
|
}
|
|
|
|
func (d *Driver) GetURL() (string, error) {
|
|
ip, err := d.GetIP()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if ip == "" {
|
|
return "", nil
|
|
}
|
|
return fmt.Sprintf("tcp://%s:2376", ip), nil
|
|
}
|
|
|
|
func (d *Driver) GetIP() (string, error) {
|
|
if d.Ip != "" {
|
|
return d.Ip, nil
|
|
}
|
|
|
|
log.WithField("MachineId", d.MachineId).Debug("Looking for the IP address...")
|
|
|
|
if err := d.initCompute(); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
addressType := Fixed
|
|
if d.FloatingIpPool != "" {
|
|
addressType = Floating
|
|
}
|
|
|
|
// Looking for the IP address in a retry loop to deal with OpenStack latency
|
|
for retryCount := 0; retryCount < 200; retryCount++ {
|
|
addresses, err := d.client.GetInstanceIpAddresses(d)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
for _, a := range addresses {
|
|
if a.AddressType == addressType {
|
|
return a.Address, nil
|
|
}
|
|
}
|
|
time.Sleep(2 * time.Second)
|
|
}
|
|
return "", fmt.Errorf("No IP found for the machine")
|
|
}
|
|
|
|
func (d *Driver) GetState() (state.State, error) {
|
|
log.WithField("MachineId", d.MachineId).Debug("Get status for OpenStack instance...")
|
|
if err := d.initCompute(); err != nil {
|
|
return state.None, err
|
|
}
|
|
|
|
s, err := d.client.GetInstanceState(d)
|
|
if err != nil {
|
|
return state.None, err
|
|
}
|
|
|
|
log.WithFields(log.Fields{
|
|
"MachineId": d.MachineId,
|
|
"State": s,
|
|
}).Debug("State for OpenStack instance")
|
|
|
|
switch s {
|
|
case "ACTIVE":
|
|
return state.Running, nil
|
|
case "PAUSED":
|
|
return state.Paused, nil
|
|
case "SUSPENDED":
|
|
return state.Saved, nil
|
|
case "SHUTOFF":
|
|
return state.Stopped, nil
|
|
case "BUILDING":
|
|
return state.Starting, nil
|
|
case "ERROR":
|
|
return state.Error, nil
|
|
}
|
|
return state.None, nil
|
|
}
|
|
|
|
func (d *Driver) PreCreateCheck() error {
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) Create() error {
|
|
d.KeyPairName = fmt.Sprintf("%s-%s", d.MachineName, utils.GenerateRandomID())
|
|
|
|
if err := d.resolveIds(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.createSSHKey(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.createMachine(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.waitForInstanceActive(); err != nil {
|
|
return err
|
|
}
|
|
if d.FloatingIpPool != "" {
|
|
if err := d.assignFloatingIp(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := d.lookForIpAddress(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.waitForSSHServer(); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) Start() error {
|
|
log.WithField("MachineId", d.MachineId).Info("Starting OpenStack instance...")
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.client.StartInstance(d); err != nil {
|
|
return err
|
|
}
|
|
return d.waitForInstanceToStart()
|
|
}
|
|
|
|
func (d *Driver) Stop() error {
|
|
log.WithField("MachineId", d.MachineId).Info("Stopping OpenStack instance...")
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.client.StopInstance(d); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.WithField("MachineId", d.MachineId).Info("Waiting for the OpenStack instance to stop...")
|
|
if err := d.client.WaitForInstanceStatus(d, "SHUTOFF", 200); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) Remove() error {
|
|
log.WithField("MachineId", d.MachineId).Debug("deleting instance...")
|
|
log.Info("Deleting OpenStack instance...")
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.client.DeleteInstance(d); err != nil {
|
|
return err
|
|
}
|
|
log.WithField("Name", d.KeyPairName).Debug("deleting key pair...")
|
|
if err := d.client.DeleteKeyPair(d, d.KeyPairName); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) Restart() error {
|
|
log.WithField("MachineId", d.MachineId).Info("Restarting OpenStack instance...")
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.client.RestartInstance(d); err != nil {
|
|
return err
|
|
}
|
|
return d.waitForInstanceToStart()
|
|
}
|
|
|
|
func (d *Driver) Kill() error {
|
|
return d.Stop()
|
|
}
|
|
|
|
func (d *Driver) Upgrade() error {
|
|
log.Debugf("Upgrading Docker")
|
|
|
|
cmd, err := d.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 (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 (d *Driver) GetSSHCommand(args ...string) (*exec.Cmd, error) {
|
|
ip, err := d.GetIP()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(args) != 0 && d.SSHUser != "root" {
|
|
cmd := strings.Replace(strings.Join(args, " "), "'", "\\'", -1)
|
|
args = []string{"sudo", "sh", "-c", fmt.Sprintf("'%s'", cmd)}
|
|
}
|
|
|
|
log.WithField("MachineId", d.MachineId).Debug("Command: %s", args)
|
|
return ssh.GetSSHCommand(ip, d.SSHPort, d.SSHUser, d.sshKeyPath(), args...), nil
|
|
}
|
|
|
|
const (
|
|
errorMandatoryEnvOrOption string = "%s must be specified either using the environment variable %s or the CLI option %s"
|
|
errorMandatoryOption string = "%s must be specified using the CLI option %s"
|
|
errorExclusiveOptions string = "Either %s or %s must be specified, not both"
|
|
errorMandatoryTenantNameOrId string = "Tenant id or name must be provided either using one of the environment variables OS_TENANT_ID and OS_TENANT_NAME or one of the CLI options --openstack-tenant-id and --openstack-tenant-name"
|
|
errorWrongEndpointType string = "Endpoint type must be 'publicURL', 'adminURL' or 'internalURL'"
|
|
errorUnknownFlavorName string = "Unable to find flavor named %s"
|
|
errorUnknownImageName string = "Unable to find image named %s"
|
|
errorUnknownNetworkName string = "Unable to find network named %s"
|
|
)
|
|
|
|
func (d *Driver) checkConfig() error {
|
|
if d.AuthUrl == "" {
|
|
return fmt.Errorf(errorMandatoryEnvOrOption, "Autentication URL", "OS_AUTH_URL", "--openstack-auth-url")
|
|
}
|
|
if d.Username == "" {
|
|
return fmt.Errorf(errorMandatoryEnvOrOption, "Username", "OS_USERNAME", "--openstack-username")
|
|
}
|
|
if d.Password == "" {
|
|
return fmt.Errorf(errorMandatoryEnvOrOption, "Password", "OS_PASSWORD", "--openstack-password")
|
|
}
|
|
if d.TenantName == "" && d.TenantId == "" {
|
|
return fmt.Errorf(errorMandatoryTenantNameOrId)
|
|
}
|
|
|
|
if d.FlavorName == "" && d.FlavorId == "" {
|
|
return fmt.Errorf(errorMandatoryOption, "Flavor name or Flavor id", "--openstack-flavor-name or --openstack-flavor-id")
|
|
}
|
|
if d.FlavorName != "" && d.FlavorId != "" {
|
|
return fmt.Errorf(errorExclusiveOptions, "Flavor name", "Flavor id")
|
|
}
|
|
|
|
if d.ImageName == "" && d.ImageId == "" {
|
|
return fmt.Errorf(errorMandatoryOption, "Image name or Image id", "--openstack-image-name or --openstack-image-id")
|
|
}
|
|
if d.ImageName != "" && d.ImageId != "" {
|
|
return fmt.Errorf(errorExclusiveOptions, "Image name", "Image id")
|
|
}
|
|
|
|
if d.NetworkName != "" && d.NetworkId != "" {
|
|
return fmt.Errorf(errorExclusiveOptions, "Network name", "Network id")
|
|
}
|
|
if d.EndpointType != "" && (d.EndpointType != "publicURL" && d.EndpointType != "adminURL" && d.EndpointType != "internalURL") {
|
|
return fmt.Errorf(errorWrongEndpointType)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) resolveIds() error {
|
|
if d.NetworkName != "" {
|
|
if err := d.initNetwork(); err != nil {
|
|
return err
|
|
}
|
|
|
|
networkId, err := d.client.GetNetworkId(d)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if networkId == "" {
|
|
return fmt.Errorf(errorUnknownNetworkName, d.NetworkName)
|
|
}
|
|
|
|
d.NetworkId = networkId
|
|
log.WithFields(log.Fields{
|
|
"Name": d.NetworkName,
|
|
"ID": d.NetworkId,
|
|
}).Debug("Found network id using its name")
|
|
}
|
|
|
|
if d.FlavorName != "" {
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
flavorId, err := d.client.GetFlavorId(d)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if flavorId == "" {
|
|
return fmt.Errorf(errorUnknownFlavorName, d.FlavorName)
|
|
}
|
|
|
|
d.FlavorId = flavorId
|
|
log.WithFields(log.Fields{
|
|
"Name": d.FlavorName,
|
|
"ID": d.FlavorId,
|
|
}).Debug("Found flavor id using its name")
|
|
}
|
|
|
|
if d.ImageName != "" {
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
imageId, err := d.client.GetImageId(d)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if imageId == "" {
|
|
return fmt.Errorf(errorUnknownImageName, d.ImageName)
|
|
}
|
|
|
|
d.ImageId = imageId
|
|
log.WithFields(log.Fields{
|
|
"Name": d.ImageName,
|
|
"ID": d.ImageId,
|
|
}).Debug("Found image id using its name")
|
|
}
|
|
|
|
if d.FloatingIpPool != "" {
|
|
if err := d.initNetwork(); err != nil {
|
|
return err
|
|
}
|
|
f, err := d.client.GetFloatingIpPoolId(d)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if f == "" {
|
|
return fmt.Errorf(errorUnknownNetworkName, d.FloatingIpPool)
|
|
}
|
|
|
|
d.FloatingIpPoolId = f
|
|
log.WithFields(log.Fields{
|
|
"Name": d.FloatingIpPool,
|
|
"ID": d.FloatingIpPoolId,
|
|
}).Debug("Found floating IP pool id using its name")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) initCompute() error {
|
|
if err := d.client.Authenticate(d); err != nil {
|
|
return err
|
|
}
|
|
if err := d.client.InitComputeClient(d); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) initNetwork() error {
|
|
if err := d.client.Authenticate(d); err != nil {
|
|
return err
|
|
}
|
|
if err := d.client.InitNetworkClient(d); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) createSSHKey() error {
|
|
log.WithField("Name", d.KeyPairName).Debug("Creating Key Pair...")
|
|
if err := ssh.GenerateSSHKey(d.sshKeyPath()); err != nil {
|
|
return err
|
|
}
|
|
publicKey, err := ioutil.ReadFile(d.publicSSHKeyPath())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
if err := d.client.CreateKeyPair(d, d.KeyPairName, string(publicKey)); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) createMachine() error {
|
|
log.WithFields(log.Fields{
|
|
"FlavorId": d.FlavorId,
|
|
"ImageId": d.ImageId,
|
|
}).Debug("Creating OpenStack instance...")
|
|
|
|
if err := d.initCompute(); err != nil {
|
|
return err
|
|
}
|
|
instanceId, err := d.client.CreateInstance(d)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
d.MachineId = instanceId
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) assignFloatingIp() error {
|
|
|
|
if err := d.initNetwork(); err != nil {
|
|
return err
|
|
}
|
|
|
|
portId, err := d.client.GetInstancePortId(d)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ips, err := d.client.GetFloatingIPs(d)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var floatingIp *FloatingIp
|
|
|
|
log.WithFields(log.Fields{
|
|
"MachineId": d.MachineId,
|
|
"Pool": d.FloatingIpPool,
|
|
}).Debugf("Looking for an available floating IP")
|
|
|
|
for _, ip := range ips {
|
|
if ip.PortId == "" {
|
|
log.WithFields(log.Fields{
|
|
"MachineId": d.MachineId,
|
|
"IP": ip.Ip,
|
|
}).Debugf("Available floating IP found")
|
|
floatingIp = &ip
|
|
break
|
|
}
|
|
}
|
|
|
|
if floatingIp == nil {
|
|
floatingIp = &FloatingIp{}
|
|
log.WithField("MachineId", d.MachineId).Debugf("No available floating IP found. Allocating a new one...")
|
|
} else {
|
|
log.WithField("MachineId", d.MachineId).Debugf("Assigning floating IP to the instance")
|
|
}
|
|
|
|
if err := d.client.AssignFloatingIP(d, floatingIp, portId); err != nil {
|
|
return err
|
|
}
|
|
d.Ip = floatingIp.Ip
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) waitForInstanceActive() error {
|
|
log.WithField("MachineId", d.MachineId).Debug("Waiting for the OpenStack instance to be ACTIVE...")
|
|
if err := d.client.WaitForInstanceStatus(d, "ACTIVE", 200); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) lookForIpAddress() error {
|
|
ip, err := d.GetIP()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
d.Ip = ip
|
|
log.WithFields(log.Fields{
|
|
"IP": ip,
|
|
"MachineId": d.MachineId,
|
|
}).Debug("IP address found")
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) waitForSSHServer() error {
|
|
ip, err := d.GetIP()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.WithFields(log.Fields{
|
|
"MachineId": d.MachineId,
|
|
"IP": ip,
|
|
}).Debug("Waiting for the SSH server to be started...")
|
|
return ssh.WaitForTCP(fmt.Sprintf("%s:%d", ip, d.SSHPort))
|
|
}
|
|
|
|
func (d *Driver) waitForInstanceToStart() error {
|
|
if err := d.waitForInstanceActive(); err != nil {
|
|
return err
|
|
}
|
|
return d.waitForSSHServer()
|
|
}
|
|
|
|
func (d *Driver) sshExec(commands []string) error {
|
|
for _, command := range commands {
|
|
sshCmd, err := d.GetSSHCommand(command)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := sshCmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (d *Driver) sshKeyPath() string {
|
|
return path.Join(d.storePath, "id_rsa")
|
|
}
|
|
|
|
func (d *Driver) publicSSHKeyPath() string {
|
|
return d.sshKeyPath() + ".pub"
|
|
}
|