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  }