packer-cn/builder/openstack/ssh.go

117 lines
3.1 KiB
Go
Raw Normal View History

package openstack
import (
"errors"
"fmt"
2015-06-12 00:16:43 -04:00
"log"
"time"
2016-11-27 19:59:26 -05:00
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
2020-12-17 16:29:25 -05:00
"github.com/hashicorp/packer-plugin-sdk/multistep"
)
// CommHost looks up the host for the communicator.
func CommHost(
2019-07-02 17:00:51 -04:00
host string,
2015-06-12 00:16:43 -04:00
client *gophercloud.ServiceClient,
sshinterface string,
sshipversion string) func(multistep.StateBag) (string, error) {
2013-08-31 15:37:07 -04:00
return func(state multistep.StateBag) (string, error) {
2019-07-02 17:00:51 -04:00
if host != "" {
log.Printf("Using host value: %s", host)
2019-07-02 17:00:51 -04:00
return host, nil
}
2015-06-12 00:16:43 -04:00
s := state.Get("server").(*servers.Server)
// If we have a specific interface, try that
if sshinterface != "" {
if addr := sshAddrFromPool(s, sshinterface, sshipversion); addr != "" {
log.Printf("[DEBUG] Using IP address %s from specified interface %s to connect", addr, sshinterface)
return addr, nil
}
}
2015-06-12 00:16:43 -04:00
// If we have a floating IP, use that
2016-11-27 19:59:26 -05:00
ip := state.Get("access_ip").(*floatingips.FloatingIP)
if ip != nil && ip.FloatingIP != "" {
log.Printf("[DEBUG] Using floating IP %s to connect", ip.FloatingIP)
return ip.FloatingIP, nil
2014-02-27 03:34:24 -05:00
}
2015-06-12 00:16:43 -04:00
if s.AccessIPv4 != "" {
log.Printf("[DEBUG] Using AccessIPv4 %s to connect", s.AccessIPv4)
return s.AccessIPv4, nil
2014-02-27 03:34:24 -05:00
}
2015-06-12 00:16:43 -04:00
// Try to get it from the requested interface
if addr := sshAddrFromPool(s, sshinterface, sshipversion); addr != "" {
log.Printf("[DEBUG] Using IP address %s to connect", addr)
return addr, nil
2014-02-27 03:34:24 -05:00
}
2015-06-12 00:16:43 -04:00
s, err := servers.Get(client, s.ID).Extract()
2014-02-27 03:34:24 -05:00
if err != nil {
return "", err
}
2015-06-12 00:16:43 -04:00
state.Put("server", s)
2014-02-27 03:34:24 -05:00
time.Sleep(1 * time.Second)
return "", errors.New("couldn't determine IP address for server")
}
}
func sshAddrFromPool(s *servers.Server, desired string, sshIPVersion string) string {
// Get all the addresses associated with this server. This
// was taken directly from Terraform.
for pool, networkAddresses := range s.Addresses {
// If we have an SSH interface specified, skip it if no match
if desired != "" && pool != desired {
log.Printf(
"[INFO] Skipping pool %s, doesn't match requested %s",
pool, desired)
continue
}
elements, ok := networkAddresses.([]interface{})
if !ok {
log.Printf(
"[ERROR] Unknown return type for address field: %#v",
networkAddresses)
continue
}
for _, element := range elements {
var addr string
address := element.(map[string]interface{})
if address["OS-EXT-IPS:type"] == "floating" {
addr = address["addr"].(string)
} else if sshIPVersion == "4" {
if address["version"].(float64) == 4 {
addr = address["addr"].(string)
}
} else if sshIPVersion == "6" {
if address["version"].(float64) == 6 {
addr = fmt.Sprintf("[%s]", address["addr"].(string))
}
} else {
if address["version"].(float64) == 6 {
addr = fmt.Sprintf("[%s]", address["addr"].(string))
} else {
addr = address["addr"].(string)
}
}
if addr != "" {
log.Printf("[DEBUG] Detected address: %s", addr)
2015-06-15 12:34:35 -04:00
return addr
}
}
}
return ""
}