github.com/raghuse92/packer@v1.3.2/builder/openstack/ssh.go (about) 1 package openstack 2 3 import ( 4 "errors" 5 "fmt" 6 "log" 7 "time" 8 9 "github.com/gophercloud/gophercloud" 10 "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" 11 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips" 12 "github.com/hashicorp/packer/helper/multistep" 13 ) 14 15 // CommHost looks up the host for the communicator. 16 func CommHost( 17 client *gophercloud.ServiceClient, 18 sshinterface string, 19 sshipversion string) func(multistep.StateBag) (string, error) { 20 return func(state multistep.StateBag) (string, error) { 21 s := state.Get("server").(*servers.Server) 22 23 // If we have a specific interface, try that 24 if sshinterface != "" { 25 if addr := sshAddrFromPool(s, sshinterface, sshipversion); addr != "" { 26 log.Printf("[DEBUG] Using IP address %s from specified interface %s to connect", addr, sshinterface) 27 return addr, nil 28 } 29 } 30 31 // If we have a floating IP, use that 32 ip := state.Get("access_ip").(*floatingips.FloatingIP) 33 if ip != nil && ip.FloatingIP != "" { 34 log.Printf("[DEBUG] Using floating IP %s to connect", ip.FloatingIP) 35 return ip.FloatingIP, nil 36 } 37 38 if s.AccessIPv4 != "" { 39 log.Printf("[DEBUG] Using AccessIPv4 %s to connect", s.AccessIPv4) 40 return s.AccessIPv4, nil 41 } 42 43 // Try to get it from the requested interface 44 if addr := sshAddrFromPool(s, sshinterface, sshipversion); addr != "" { 45 log.Printf("[DEBUG] Using IP address %s to connect", addr) 46 return addr, nil 47 } 48 49 s, err := servers.Get(client, s.ID).Extract() 50 if err != nil { 51 return "", err 52 } 53 54 state.Put("server", s) 55 time.Sleep(1 * time.Second) 56 57 return "", errors.New("couldn't determine IP address for server") 58 } 59 } 60 61 func sshAddrFromPool(s *servers.Server, desired string, sshIPVersion string) string { 62 // Get all the addresses associated with this server. This 63 // was taken directly from Terraform. 64 for pool, networkAddresses := range s.Addresses { 65 // If we have an SSH interface specified, skip it if no match 66 if desired != "" && pool != desired { 67 log.Printf( 68 "[INFO] Skipping pool %s, doesn't match requested %s", 69 pool, desired) 70 continue 71 } 72 73 elements, ok := networkAddresses.([]interface{}) 74 if !ok { 75 log.Printf( 76 "[ERROR] Unknown return type for address field: %#v", 77 networkAddresses) 78 continue 79 } 80 81 for _, element := range elements { 82 var addr string 83 address := element.(map[string]interface{}) 84 if address["OS-EXT-IPS:type"] == "floating" { 85 addr = address["addr"].(string) 86 } else if sshIPVersion == "4" { 87 if address["version"].(float64) == 4 { 88 addr = address["addr"].(string) 89 } 90 } else if sshIPVersion == "6" { 91 if address["version"].(float64) == 6 { 92 addr = fmt.Sprintf("[%s]", address["addr"].(string)) 93 } 94 } else { 95 if address["version"].(float64) == 6 { 96 addr = fmt.Sprintf("[%s]", address["addr"].(string)) 97 } else { 98 addr = address["addr"].(string) 99 } 100 } 101 102 if addr != "" { 103 log.Printf("[DEBUG] Detected address: %s", addr) 104 return addr 105 } 106 } 107 } 108 109 return "" 110 }