2014-12-10 15:56:28 +01:00
package openstack
import (
"fmt"
"io/ioutil"
2015-11-13 12:52:12 +03:00
"net"
2014-12-10 15:56:28 +01:00
"strings"
2014-12-14 22:38:25 +01:00
"time"
2014-12-10 15:56:28 +01:00
2015-08-18 11:26:42 +09:00
"github.com/docker/machine/libmachine/drivers"
"github.com/docker/machine/libmachine/log"
2015-09-02 13:42:13 -07:00
"github.com/docker/machine/libmachine/mcnflag"
2015-08-18 11:26:42 +09:00
"github.com/docker/machine/libmachine/mcnutils"
"github.com/docker/machine/libmachine/ssh"
"github.com/docker/machine/libmachine/state"
2014-12-10 15:56:28 +01:00
)
type Driver struct {
2015-05-27 14:12:36 -04:00
* drivers . BaseDriver
2015-02-23 14:49:28 -05:00
AuthUrl string
2015-08-03 20:32:32 +02:00
ActiveTimeout int
2015-02-19 11:15:24 -05:00
Insecure bool
2015-04-09 17:40:21 +02:00
DomainID string
DomainName string
2015-02-23 14:49:28 -05:00
Username string
Password string
TenantName string
TenantId string
Region string
2015-06-05 17:31:09 -07:00
AvailabilityZone string
2015-02-23 14:49:28 -05:00
EndpointType string
MachineId string
FlavorName string
FlavorId string
ImageName string
ImageId string
KeyPairName string
NetworkName string
NetworkId string
2015-12-15 18:22:38 -08:00
PrivateKeyFile string
2015-02-23 14:49:28 -05:00
SecurityGroups [ ] string
FloatingIpPool string
2015-10-21 13:45:01 -04:00
ComputeNetwork bool
2015-02-23 14:49:28 -05:00
FloatingIpPoolId string
2015-10-04 23:43:42 +09:00
IpVersion int
2015-02-23 14:49:28 -05:00
client Client
2014-12-10 15:56:28 +01:00
}
2015-08-18 11:26:42 +09:00
const (
defaultSSHUser = "root"
defaultSSHPort = 22
defaultActiveTimeout = 200
)
2015-09-02 13:42:13 -07:00
func ( d * Driver ) GetCreateFlags ( ) [ ] mcnflag . Flag {
return [ ] mcnflag . Flag {
mcnflag . StringFlag {
2014-12-13 03:28:54 +01:00
EnvVar : "OS_AUTH_URL" ,
Name : "openstack-auth-url" ,
Usage : "OpenStack authentication URL" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . BoolFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_INSECURE" ,
Name : "openstack-insecure" ,
Usage : "Disable TLS credential checking." ,
2015-02-19 11:15:24 -05:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-04-09 17:40:21 +02:00
EnvVar : "OS_DOMAIN_ID" ,
Name : "openstack-domain-id" ,
Usage : "OpenStack domain ID (identity v3 only)" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-04-09 17:40:21 +02:00
EnvVar : "OS_DOMAIN_NAME" ,
Name : "openstack-domain-name" ,
Usage : "OpenStack domain name (identity v3 only)" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2014-12-13 03:28:54 +01:00
EnvVar : "OS_USERNAME" ,
Name : "openstack-username" ,
Usage : "OpenStack username" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2014-12-13 03:28:54 +01:00
EnvVar : "OS_PASSWORD" ,
Name : "openstack-password" ,
Usage : "OpenStack password" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2014-12-13 03:28:54 +01:00
EnvVar : "OS_TENANT_NAME" ,
Name : "openstack-tenant-name" ,
Usage : "OpenStack tenant name" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2014-12-13 03:28:54 +01:00
EnvVar : "OS_TENANT_ID" ,
Name : "openstack-tenant-id" ,
Usage : "OpenStack tenant id" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2014-12-13 03:28:54 +01:00
EnvVar : "OS_REGION_NAME" ,
Name : "openstack-region" ,
Usage : "OpenStack region name" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-06-05 17:31:09 -07:00
EnvVar : "OS_AVAILABILITY_ZONE" ,
Name : "openstack-availability-zone" ,
Usage : "OpenStack availability zone" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2014-12-13 03:28:54 +01:00
EnvVar : "OS_ENDPOINT_TYPE" ,
Name : "openstack-endpoint-type" ,
Usage : "OpenStack endpoint type (adminURL, internalURL or publicURL)" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_FLAVOR_ID" ,
Name : "openstack-flavor-id" ,
Usage : "OpenStack flavor id to use for the instance" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_FLAVOR_NAME" ,
Name : "openstack-flavor-name" ,
Usage : "OpenStack flavor name to use for the instance" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_IMAGE_ID" ,
Name : "openstack-image-id" ,
Usage : "OpenStack image id to use for the instance" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_IMAGE_NAME" ,
Name : "openstack-image-name" ,
Usage : "OpenStack image name to use for the instance" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-12-15 18:22:38 -08:00
mcnflag . StringFlag {
EnvVar : "OS_KEYPAIR_NAME" ,
Name : "openstack-keypair-name" ,
Usage : "OpenStack keypair to use to SSH to the instance" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_NETWORK_ID" ,
Name : "openstack-net-id" ,
Usage : "OpenStack network id the machine will be connected on" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-12-15 18:22:38 -08:00
mcnflag . StringFlag {
EnvVar : "OS_PRIVATE_KEY_FILE" ,
Name : "openstack-private-key-file" ,
Usage : "Private keyfile to use for SSH (absolute path)" ,
Value : "" ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_NETWORK_NAME" ,
Name : "openstack-net-name" ,
Usage : "OpenStack network name the machine will be connected on" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_SECURITY_GROUPS" ,
Name : "openstack-sec-groups" ,
Usage : "OpenStack comma separated security groups for the machine" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-10-21 13:45:01 -04:00
mcnflag . BoolFlag {
EnvVar : "OS_NOVA_NETWORK" ,
Name : "openstack-nova-network" ,
Usage : "Use the nova networking services instead of neutron." ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_FLOATINGIP_POOL" ,
Name : "openstack-floatingip-pool" ,
Usage : "OpenStack floating IP pool to get an IP from to assign to the instance" ,
Value : "" ,
2014-12-13 03:28:54 +01:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . IntFlag {
2015-10-04 23:43:42 +09:00
EnvVar : "OS_IP_VERSION" ,
Name : "openstack-ip-version" ,
Usage : "OpenStack version of IP address assigned for the machine" ,
Value : 4 ,
} ,
2015-09-02 13:42:13 -07:00
mcnflag . StringFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_SSH_USER" ,
Name : "openstack-ssh-user" ,
Usage : "OpenStack SSH user" ,
Value : defaultSSHUser ,
2014-12-13 03:28:54 +01:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . IntFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_SSH_PORT" ,
Name : "openstack-ssh-port" ,
Usage : "OpenStack SSH port" ,
Value : defaultSSHPort ,
2014-12-13 03:28:54 +01:00
} ,
2015-09-02 13:42:13 -07:00
mcnflag . IntFlag {
2015-09-18 15:36:13 +02:00
EnvVar : "OS_ACTIVE_TIMEOUT" ,
Name : "openstack-active-timeout" ,
Usage : "OpenStack active timeout" ,
Value : defaultActiveTimeout ,
2015-08-03 20:32:32 +02:00
} ,
2014-12-13 03:28:54 +01:00
}
2014-12-10 15:56:28 +01:00
}
2015-08-18 11:26:42 +09:00
func NewDriver ( hostName , storePath string ) drivers . Driver {
return NewDerivedDriver ( hostName , storePath )
2014-12-11 10:14:49 -05:00
}
2015-08-18 11:26:42 +09:00
func NewDerivedDriver ( hostName , storePath string ) * Driver {
return & Driver {
client : & GenericClient { } ,
ActiveTimeout : defaultActiveTimeout ,
BaseDriver : & drivers . BaseDriver {
SSHUser : defaultSSHUser ,
SSHPort : defaultSSHPort ,
MachineName : hostName ,
StorePath : storePath ,
} ,
}
2015-03-09 23:27:17 -04:00
}
2015-10-26 18:47:09 +01:00
func ( d * Driver ) GetSSHHostname ( ) ( string , error ) {
return d . GetIP ( )
}
2015-11-06 18:16:15 +00:00
func ( d * Driver ) SetClient ( client Client ) {
d . client = client
}
2015-11-05 18:04:40 -08:00
// DriverName returns the name of the driver
2014-12-10 15:56:28 +01:00
func ( d * Driver ) DriverName ( ) string {
return "openstack"
}
2014-12-13 03:28:54 +01:00
func ( d * Driver ) SetConfigFromFlags ( flags drivers . DriverOptions ) error {
d . AuthUrl = flags . String ( "openstack-auth-url" )
2015-08-03 20:32:32 +02:00
d . ActiveTimeout = flags . Int ( "openstack-active-timeout" )
2015-02-19 11:15:24 -05:00
d . Insecure = flags . Bool ( "openstack-insecure" )
2015-04-09 17:40:21 +02:00
d . DomainID = flags . String ( "openstack-domain-id" )
d . DomainName = flags . String ( "openstack-domain-name" )
2014-12-13 03:28:54 +01:00
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" )
2015-06-05 17:31:09 -07:00
d . AvailabilityZone = flags . String ( "openstack-availability-zone" )
2014-12-13 03:28:54 +01:00
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" ) , "," )
2014-12-10 15:56:28 +01:00
}
2014-12-13 03:28:54 +01:00
d . FloatingIpPool = flags . String ( "openstack-floatingip-pool" )
2015-10-04 23:43:42 +09:00
d . IpVersion = flags . Int ( "openstack-ip-version" )
2015-10-21 13:45:01 -04:00
d . ComputeNetwork = flags . Bool ( "openstack-nova-network" )
2014-12-13 03:28:54 +01:00
d . SSHUser = flags . String ( "openstack-ssh-user" )
d . SSHPort = flags . Int ( "openstack-ssh-port" )
2015-12-15 18:22:38 -08:00
d . KeyPairName = flags . String ( "openstack-keypair-name" )
d . PrivateKeyFile = flags . String ( "openstack-private-key-file" )
2015-12-29 10:14:53 +01:00
d . SetSwarmConfigFromFlags ( flags )
2014-12-15 02:34:41 +01:00
2014-12-10 15:56:28 +01:00
return d . checkConfig ( )
}
func ( d * Driver ) GetURL ( ) ( string , error ) {
ip , err := d . GetIP ( )
if err != nil {
return "" , err
}
if ip == "" {
return "" , nil
}
2015-11-13 12:52:12 +03:00
return fmt . Sprintf ( "tcp://%s" , net . JoinHostPort ( ip , "2376" ) ) , nil
2014-12-10 15:56:28 +01:00
}
func ( d * Driver ) GetIP ( ) ( string , error ) {
2015-04-21 21:39:06 -04:00
if d . IPAddress != "" {
return d . IPAddress , nil
2014-12-11 13:46:58 -05:00
}
2015-12-03 17:22:36 +01:00
log . Debug ( "Looking for the IP address..." , map [ string ] string { "MachineId" : d . MachineId } )
2014-12-14 22:38:25 +01:00
if err := d . initCompute ( ) ; err != nil {
2014-12-10 15:56:28 +01:00
return "" , err
}
2014-12-14 22:38:25 +01:00
addressType := Fixed
if d . FloatingIpPool != "" {
addressType = Floating
}
2014-12-10 15:56:28 +01:00
2014-12-14 22:38:25 +01:00
// Looking for the IP address in a retry loop to deal with OpenStack latency
for retryCount := 0 ; retryCount < 200 ; retryCount ++ {
2015-11-05 18:04:40 -08:00
addresses , err := d . client . GetInstanceIPAddresses ( d )
2014-12-14 22:38:25 +01:00
if err != nil {
return "" , err
2014-12-10 15:56:28 +01:00
}
2014-12-14 22:38:25 +01:00
for _ , a := range addresses {
2015-10-04 23:43:42 +09:00
if a . AddressType == addressType && a . Version == d . IpVersion {
2014-12-14 22:38:25 +01:00
return a . Address , nil
}
2014-12-10 15:56:28 +01:00
}
2014-12-14 22:38:25 +01:00
time . Sleep ( 2 * time . Second )
2014-12-10 15:56:28 +01:00
}
return "" , fmt . Errorf ( "No IP found for the machine" )
}
func ( d * Driver ) GetState ( ) ( state . State , error ) {
2015-12-03 17:22:36 +01:00
log . Debug ( "Get status for OpenStack instance..." , map [ string ] string { "MachineId" : d . MachineId } )
2014-12-11 13:46:58 -05:00
if err := d . initCompute ( ) ; err != nil {
return state . None , err
}
2014-12-10 15:56:28 +01:00
s , err := d . client . GetInstanceState ( d )
if err != nil {
return state . None , err
}
2015-12-03 17:22:36 +01:00
log . Debug ( "State for OpenStack instance" , map [ string ] string {
2014-12-10 15:56:28 +01:00
"MachineId" : d . MachineId ,
"State" : s ,
2015-12-03 17:22:36 +01:00
} )
2014-12-10 15:56:28 +01:00
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 ) Create ( ) error {
2014-12-11 17:37:23 +01:00
if err := d . resolveIds ( ) ; err != nil {
return err
}
2015-12-15 18:22:38 -08:00
if d . KeyPairName != "" {
if err := d . loadSSHKey ( ) ; err != nil {
return err
}
} else {
d . KeyPairName = fmt . Sprintf ( "%s-%s" , d . MachineName , mcnutils . GenerateRandomID ( ) )
if err := d . createSSHKey ( ) ; err != nil {
return err
}
2014-12-10 15:56:28 +01:00
}
if err := d . createMachine ( ) ; err != nil {
return err
}
2014-12-14 22:38:25 +01:00
if err := d . waitForInstanceActive ( ) ; err != nil {
return err
}
if d . FloatingIpPool != "" {
2015-11-05 18:04:40 -08:00
if err := d . assignFloatingIP ( ) ; err != nil {
2014-12-14 22:38:25 +01:00
return err
}
}
2015-11-05 18:04:40 -08:00
if err := d . lookForIPAddress ( ) ; err != nil {
2014-12-14 22:38:25 +01:00
return err
}
2014-12-10 15:56:28 +01:00
return nil
}
func ( d * Driver ) Start ( ) error {
2014-12-11 13:46:58 -05:00
if err := d . initCompute ( ) ; err != nil {
return err
}
2015-12-30 11:50:39 +01:00
return d . client . StartInstance ( d )
2014-12-10 15:56:28 +01:00
}
func ( d * Driver ) Stop ( ) error {
2014-12-11 13:46:58 -05:00
if err := d . initCompute ( ) ; err != nil {
return err
}
2014-12-10 15:56:28 +01:00
2015-12-30 11:50:39 +01:00
return d . client . StopInstance ( d )
2014-12-10 15:56:28 +01:00
}
2015-12-30 11:57:37 +01:00
func ( d * Driver ) Restart ( ) error {
if err := d . initCompute ( ) ; err != nil {
2014-12-10 15:56:28 +01:00
return err
}
2015-12-30 11:57:37 +01:00
return d . client . RestartInstance ( d )
}
2015-12-30 12:05:12 +01:00
func ( d * Driver ) Kill ( ) error {
return d . Stop ( )
2014-12-10 15:56:28 +01:00
}
func ( d * Driver ) Remove ( ) error {
2015-12-03 17:22:36 +01:00
log . Debug ( "deleting instance..." , map [ string ] string { "MachineId" : d . MachineId } )
2015-02-24 11:02:49 -05:00
log . Info ( "Deleting OpenStack instance..." )
2014-12-11 13:46:58 -05:00
if err := d . initCompute ( ) ; err != nil {
return err
}
2014-12-10 15:56:28 +01:00
if err := d . client . DeleteInstance ( d ) ; err != nil {
return err
}
2015-12-03 17:22:36 +01:00
log . Debug ( "deleting key pair..." , map [ string ] string { "Name" : d . KeyPairName } )
2015-12-15 18:22:38 -08:00
// TODO (fsoppelsa) maybe we want to check this, in case of shared keypairs, before removal
2014-12-10 15:56:28 +01:00
if err := d . client . DeleteKeyPair ( d , d . KeyPairName ) ; err != nil {
return err
}
return 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"
2014-12-11 17:37:23 +01:00
errorExclusiveOptions string = "Either %s or %s must be specified, not both"
2015-12-15 18:22:38 -08:00
errorBothOptions string = "Both %s and %s must be specified"
2015-11-05 18:04:40 -08:00
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"
2014-12-10 15:56:28 +01:00
errorWrongEndpointType string = "Endpoint type must be 'publicURL', 'adminURL' or 'internalURL'"
2014-12-11 17:37:23 +01:00
errorUnknownFlavorName string = "Unable to find flavor named %s"
errorUnknownImageName string = "Unable to find image named %s"
errorUnknownNetworkName string = "Unable to find network named %s"
2015-12-15 22:30:49 +00:00
errorUnknownTenantName string = "Unable to find tenant named %s"
2014-12-10 15:56:28 +01:00
)
func ( d * Driver ) checkConfig ( ) error {
if d . AuthUrl == "" {
2015-03-23 18:31:34 -05:00
return fmt . Errorf ( errorMandatoryEnvOrOption , "Authentication URL" , "OS_AUTH_URL" , "--openstack-auth-url" )
2014-12-10 15:56:28 +01:00
}
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 == "" {
2015-11-05 18:04:40 -08:00
return fmt . Errorf ( errorMandatoryTenantNameOrID )
2014-12-10 15:56:28 +01:00
}
2014-12-11 17:37:23 +01:00
if d . FlavorName == "" && d . FlavorId == "" {
return fmt . Errorf ( errorMandatoryOption , "Flavor name or Flavor id" , "--openstack-flavor-name or --openstack-flavor-id" )
2014-12-10 15:56:28 +01:00
}
2014-12-11 17:37:23 +01:00
if d . FlavorName != "" && d . FlavorId != "" {
return fmt . Errorf ( errorExclusiveOptions , "Flavor name" , "Flavor id" )
2014-12-10 15:56:28 +01:00
}
2014-12-11 17:37:23 +01:00
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" )
}
2014-12-11 14:34:30 -05:00
if d . EndpointType != "" && ( d . EndpointType != "publicURL" && d . EndpointType != "adminURL" && d . EndpointType != "internalURL" ) {
2014-12-10 15:56:28 +01:00
return fmt . Errorf ( errorWrongEndpointType )
}
2015-12-15 18:22:38 -08:00
if ( d . KeyPairName != "" && d . PrivateKeyFile == "" ) || ( d . KeyPairName == "" && d . PrivateKeyFile != "" ) {
return fmt . Errorf ( errorBothOptions , "KeyPairName" , "PrivateKeyFile" )
}
2014-12-10 15:56:28 +01:00
return nil
}
2014-12-11 17:37:23 +01:00
func ( d * Driver ) resolveIds ( ) error {
2015-10-21 13:45:01 -04:00
if d . NetworkName != "" && ! d . ComputeNetwork {
2014-12-12 10:00:40 -05:00
if err := d . initNetwork ( ) ; err != nil {
return err
}
2015-11-05 18:04:40 -08:00
networkID , err := d . client . GetNetworkID ( d )
2014-12-11 17:37:23 +01:00
if err != nil {
return err
}
2015-11-05 18:04:40 -08:00
if networkID == "" {
2014-12-11 17:37:23 +01:00
return fmt . Errorf ( errorUnknownNetworkName , d . NetworkName )
}
2015-11-05 18:04:40 -08:00
d . NetworkId = networkID
2015-12-03 17:22:36 +01:00
log . Debug ( "Found network id using its name" , map [ string ] string {
2014-12-11 17:37:23 +01:00
"Name" : d . NetworkName ,
"ID" : d . NetworkId ,
2015-12-03 17:22:36 +01:00
} )
2014-12-11 17:37:23 +01:00
}
if d . FlavorName != "" {
2014-12-12 10:00:40 -05:00
if err := d . initCompute ( ) ; err != nil {
return err
}
2015-11-05 18:04:40 -08:00
flavorID , err := d . client . GetFlavorID ( d )
2014-12-11 17:37:23 +01:00
if err != nil {
return err
}
2015-11-05 18:04:40 -08:00
if flavorID == "" {
2014-12-11 17:37:23 +01:00
return fmt . Errorf ( errorUnknownFlavorName , d . FlavorName )
}
2015-11-05 18:04:40 -08:00
d . FlavorId = flavorID
2015-12-03 17:22:36 +01:00
log . Debug ( "Found flavor id using its name" , map [ string ] string {
2014-12-11 17:37:23 +01:00
"Name" : d . FlavorName ,
"ID" : d . FlavorId ,
2015-12-03 17:22:36 +01:00
} )
2014-12-11 17:37:23 +01:00
}
if d . ImageName != "" {
2014-12-12 10:00:40 -05:00
if err := d . initCompute ( ) ; err != nil {
return err
}
2015-11-05 18:04:40 -08:00
imageID , err := d . client . GetImageID ( d )
2014-12-11 17:37:23 +01:00
if err != nil {
return err
}
2015-11-05 18:04:40 -08:00
if imageID == "" {
2014-12-11 17:37:23 +01:00
return fmt . Errorf ( errorUnknownImageName , d . ImageName )
}
2015-11-05 18:04:40 -08:00
d . ImageId = imageID
2015-12-03 17:22:36 +01:00
log . Debug ( "Found image id using its name" , map [ string ] string {
2014-12-11 17:37:23 +01:00
"Name" : d . ImageName ,
"ID" : d . ImageId ,
2015-12-03 17:22:36 +01:00
} )
2014-12-11 17:37:23 +01:00
}
2015-10-21 13:45:01 -04:00
if d . FloatingIpPool != "" && ! d . ComputeNetwork {
2014-12-14 22:38:25 +01:00
if err := d . initNetwork ( ) ; err != nil {
return err
}
2015-11-05 18:04:40 -08:00
f , err := d . client . GetFloatingIPPoolID ( d )
2014-12-14 22:38:25 +01:00
if err != nil {
return err
}
if f == "" {
return fmt . Errorf ( errorUnknownNetworkName , d . FloatingIpPool )
}
d . FloatingIpPoolId = f
2015-12-03 17:22:36 +01:00
log . Debug ( "Found floating IP pool id using its name" , map [ string ] string {
2014-12-14 22:38:25 +01:00
"Name" : d . FloatingIpPool ,
"ID" : d . FloatingIpPoolId ,
2015-12-03 17:22:36 +01:00
} )
2014-12-14 22:38:25 +01:00
}
2016-01-11 13:45:42 -05:00
if d . TenantName != "" && d . TenantId == "" {
2015-12-15 22:30:49 +00:00
if err := d . initIdentity ( ) ; err != nil {
return err
}
tenantId , err := d . client . GetTenantID ( d )
if err != nil {
return err
}
if tenantId == "" {
return fmt . Errorf ( errorUnknownTenantName , d . TenantName )
}
d . TenantId = tenantId
log . Debug ( "Found tenant id using its name" , map [ string ] string {
"Name" : d . TenantName ,
"ID" : d . TenantId ,
} )
}
2014-12-12 10:00:40 -05:00
return nil
}
2014-12-11 13:46:58 -05:00
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
}
2015-12-15 22:30:49 +00:00
func ( d * Driver ) initIdentity ( ) error {
if err := d . client . Authenticate ( d ) ; err != nil {
return err
}
if err := d . client . InitIdentityClient ( d ) ; err != nil {
return err
}
return nil
}
2014-12-11 13:46:58 -05:00
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
}
2014-12-11 17:37:23 +01:00
return nil
}
2015-12-15 18:22:38 -08:00
func ( d * Driver ) loadSSHKey ( ) error {
log . Debug ( "Loading Key Pair" , d . KeyPairName )
if err := d . initCompute ( ) ; err != nil {
return err
}
log . Debug ( "Loading Private Key from" , d . PrivateKeyFile )
privateKey , err := ioutil . ReadFile ( d . PrivateKeyFile )
if err != nil {
return err
}
publicKey , err := d . client . GetPublicKey ( d . KeyPairName )
if err != nil {
return err
}
if err := ioutil . WriteFile ( d . privateSSHKeyPath ( ) , privateKey , 0600 ) ; err != nil {
return err
}
if err := ioutil . WriteFile ( d . publicSSHKeyPath ( ) , publicKey , 0600 ) ; err != nil {
return err
}
return nil
}
2014-12-10 15:56:28 +01:00
func ( d * Driver ) createSSHKey ( ) error {
2015-12-05 15:56:51 -08:00
sanitizeKeyPairName ( & d . KeyPairName )
2015-12-03 17:22:36 +01:00
log . Debug ( "Creating Key Pair..." , map [ string ] string { "Name" : d . KeyPairName } )
2015-03-09 23:29:52 -04:00
if err := ssh . GenerateSSHKey ( d . GetSSHKeyPath ( ) ) ; err != nil {
2014-12-10 15:56:28 +01:00
return err
}
publicKey , err := ioutil . ReadFile ( d . publicSSHKeyPath ( ) )
if err != nil {
return err
}
2014-12-11 13:46:58 -05:00
if err := d . initCompute ( ) ; err != nil {
return err
}
2014-12-10 15:56:28 +01:00
if err := d . client . CreateKeyPair ( d , d . KeyPairName , string ( publicKey ) ) ; err != nil {
return err
}
return nil
}
func ( d * Driver ) createMachine ( ) error {
2015-12-03 17:22:36 +01:00
log . Debug ( "Creating OpenStack instance..." , map [ string ] string {
2014-12-10 15:56:28 +01:00
"FlavorId" : d . FlavorId ,
"ImageId" : d . ImageId ,
2015-12-03 17:22:36 +01:00
} )
2014-12-11 13:46:58 -05:00
if err := d . initCompute ( ) ; err != nil {
return err
}
2015-11-05 18:04:40 -08:00
instanceID , err := d . client . CreateInstance ( d )
2014-12-10 15:56:28 +01:00
if err != nil {
return err
}
2015-11-05 18:04:40 -08:00
d . MachineId = instanceID
2014-12-10 15:56:28 +01:00
return nil
}
2015-11-05 18:04:40 -08:00
func ( d * Driver ) assignFloatingIP ( ) error {
2015-10-21 13:45:01 -04:00
var err error
2014-12-14 22:38:25 +01:00
2015-10-21 13:45:01 -04:00
if d . ComputeNetwork {
err = d . initCompute ( )
} else {
err = d . initNetwork ( )
2014-12-14 22:38:25 +01:00
}
if err != nil {
return err
}
ips , err := d . client . GetFloatingIPs ( d )
if err != nil {
return err
}
2015-11-05 18:04:40 -08:00
var floatingIP * FloatingIP
2014-12-14 22:38:25 +01:00
2015-12-03 17:22:36 +01:00
log . Debugf ( "Looking for an available floating IP" , map [ string ] string {
2014-12-14 22:38:25 +01:00
"MachineId" : d . MachineId ,
"Pool" : d . FloatingIpPool ,
2015-12-03 17:22:36 +01:00
} )
2014-12-14 22:38:25 +01:00
for _ , ip := range ips {
if ip . PortId == "" {
2015-12-03 17:22:36 +01:00
log . Debug ( "Available floating IP found" , map [ string ] string {
2014-12-14 22:38:25 +01:00
"MachineId" : d . MachineId ,
"IP" : ip . Ip ,
2015-12-03 17:22:36 +01:00
} )
2015-11-05 18:04:40 -08:00
floatingIP = & ip
2014-12-14 22:38:25 +01:00
break
}
}
2015-11-05 18:04:40 -08:00
if floatingIP == nil {
floatingIP = & FloatingIP { }
2015-12-03 17:22:36 +01:00
log . Debug ( "No available floating IP found. Allocating a new one..." , map [ string ] string { "MachineId" : d . MachineId } )
2014-12-14 22:38:25 +01:00
} else {
2015-12-03 17:22:36 +01:00
log . Debug ( "Assigning floating IP to the instance" , map [ string ] string { "MachineId" : d . MachineId } )
2014-12-14 22:38:25 +01:00
}
2015-11-05 18:04:40 -08:00
if err := d . client . AssignFloatingIP ( d , floatingIP ) ; err != nil {
2014-12-14 22:38:25 +01:00
return err
}
2015-11-05 18:04:40 -08:00
d . IPAddress = floatingIP . Ip
2014-12-14 22:38:25 +01:00
return nil
}
func ( d * Driver ) waitForInstanceActive ( ) error {
2015-12-03 17:22:36 +01:00
log . Debug ( "Waiting for the OpenStack instance to be ACTIVE..." , map [ string ] string { "MachineId" : d . MachineId } )
2015-06-01 00:41:41 +02:00
if err := d . client . WaitForInstanceStatus ( d , "ACTIVE" ) ; err != nil {
2014-12-10 15:56:28 +01:00
return err
}
2014-12-14 22:38:25 +01:00
return nil
}
2015-11-05 18:04:40 -08:00
func ( d * Driver ) lookForIPAddress ( ) error {
2014-12-10 15:56:28 +01:00
ip , err := d . GetIP ( )
if err != nil {
return err
}
2015-04-21 21:39:06 -04:00
d . IPAddress = ip
2015-12-03 17:22:36 +01:00
log . Debug ( "IP address found" , map [ string ] string {
2014-12-14 22:38:25 +01:00
"IP" : ip ,
"MachineId" : d . MachineId ,
2015-12-03 17:22:36 +01:00
} )
2014-12-14 22:38:25 +01:00
return nil
}
2015-12-15 18:22:38 -08:00
func ( d * Driver ) privateSSHKeyPath ( ) string {
return d . GetSSHKeyPath ( )
}
2014-12-10 15:56:28 +01:00
func ( d * Driver ) publicSSHKeyPath ( ) string {
2015-03-09 23:29:52 -04:00
return d . GetSSHKeyPath ( ) + ".pub"
2014-12-10 15:56:28 +01:00
}
2015-12-05 15:56:51 -08:00
func sanitizeKeyPairName ( s * string ) {
* s = strings . Replace ( * s , "." , "_" , - 1 )
}