Ian Delahorne 8bf935beb8 Force IPv4 addresses from address pools in Openstack. Fixes #1258
Rackspace defaults to a public IPv4 and IPv6 address. These are returned in
random order, with the sprintf further on generating an incorrect connection
string if on IPv6. Force IPv4 until support for correct connection strings and
a configuration flag for logging in over IPv6 is added.
2014-06-15 02:12:52 -05:00

69 lines
1.8 KiB
Go

package openstack
import (
"code.google.com/p/go.crypto/ssh"
"errors"
"fmt"
"github.com/mitchellh/multistep"
"github.com/rackspace/gophercloud"
"time"
)
// SSHAddress returns a function that can be given to the SSH communicator
// for determining the SSH address based on the server AccessIPv4 setting..
func SSHAddress(csp gophercloud.CloudServersProvider, port int) func(multistep.StateBag) (string, error) {
return func(state multistep.StateBag) (string, error) {
s := state.Get("server").(*gophercloud.Server)
if ip := state.Get("access_ip").(gophercloud.FloatingIp); ip.Ip != "" {
return fmt.Sprintf("%s:%d", ip.Ip, port), nil
}
ip_pools, err := s.AllAddressPools()
if err != nil {
return "", errors.New("Error parsing SSH addresses")
}
for pool, addresses := range ip_pools {
if pool != "" {
for _, address := range addresses {
if address.Addr != "" && address.Version == 4 {
return fmt.Sprintf("%s:%d", address.Addr, port), nil
}
}
}
}
serverState, err := csp.ServerById(s.Id)
if err != nil {
return "", err
}
state.Put("server", serverState)
time.Sleep(1 * time.Second)
return "", errors.New("couldn't determine IP address for server")
}
}
// SSHConfig returns a function that can be used for the SSH communicator
// config for connecting to the instance created over SSH using the generated
// private key.
func SSHConfig(username string) func(multistep.StateBag) (*ssh.ClientConfig, error) {
return func(state multistep.StateBag) (*ssh.ClientConfig, error) {
privateKey := state.Get("privateKey").(string)
signer, err := ssh.ParsePrivateKey([]byte(privateKey))
if err != nil {
return nil, fmt.Errorf("Error setting up SSH config: %s", err)
}
return &ssh.ClientConfig{
User: username,
Auth: []ssh.AuthMethod{
ssh.PublicKeys(signer),
},
}, nil
}
}