github.com/raghuse92/packer@v1.3.2/builder/openstack/networks.go (about)

     1  package openstack
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/google/uuid"
     7  	"github.com/gophercloud/gophercloud"
     8  	"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
     9  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
    10  	"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
    11  	"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
    12  	"github.com/gophercloud/gophercloud/pagination"
    13  )
    14  
    15  // CheckFloatingIP gets a floating IP by its ID and checks if it is already
    16  // associated with any internal interface.
    17  // It returns floating IP if it can be used.
    18  func CheckFloatingIP(client *gophercloud.ServiceClient, id string) (*floatingips.FloatingIP, error) {
    19  	floatingIP, err := floatingips.Get(client, id).Extract()
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	if floatingIP.PortID != "" {
    24  		return nil, fmt.Errorf("provided floating IP '%s' is already associated with port '%s'",
    25  			id, floatingIP.PortID)
    26  	}
    27  
    28  	return floatingIP, nil
    29  }
    30  
    31  // FindFreeFloatingIP returns free unassociated floating IP.
    32  // It will return first floating IP if there are many.
    33  func FindFreeFloatingIP(client *gophercloud.ServiceClient) (*floatingips.FloatingIP, error) {
    34  	var freeFloatingIP *floatingips.FloatingIP
    35  
    36  	pager := floatingips.List(client, floatingips.ListOpts{
    37  		Status: "DOWN",
    38  	})
    39  	err := pager.EachPage(func(page pagination.Page) (bool, error) {
    40  		candidates, err := floatingips.ExtractFloatingIPs(page)
    41  		if err != nil {
    42  			return false, err // stop and throw error out
    43  		}
    44  
    45  		for _, candidate := range candidates {
    46  			if candidate.PortID != "" {
    47  				continue // this floating IP is associated with port, move to next in list
    48  			}
    49  
    50  			// Floating IP is able to be allocated.
    51  			freeFloatingIP = &candidate
    52  			return false, nil // stop iterating over pages
    53  		}
    54  		return true, nil // try the next page
    55  	})
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	if freeFloatingIP == nil {
    60  		return nil, fmt.Errorf("no free floating IPs found")
    61  	}
    62  
    63  	return freeFloatingIP, nil
    64  }
    65  
    66  // GetInstancePortID returns internal port of the instance that can be used for
    67  // the association of a floating IP.
    68  // It will return an ID of a first port if there are many.
    69  func GetInstancePortID(client *gophercloud.ServiceClient, id string) (string, error) {
    70  	interfacesPage, err := attachinterfaces.List(client, id).AllPages()
    71  	if err != nil {
    72  		return "", err
    73  	}
    74  	interfaces, err := attachinterfaces.ExtractInterfaces(interfacesPage)
    75  	if err != nil {
    76  		return "", err
    77  	}
    78  	if len(interfaces) == 0 {
    79  		return "", fmt.Errorf("instance '%s' has no interfaces", id)
    80  	}
    81  
    82  	return interfaces[0].PortID, nil
    83  }
    84  
    85  // CheckFloatingIPNetwork checks provided network reference and returns a valid
    86  // Networking service ID.
    87  func CheckFloatingIPNetwork(client *gophercloud.ServiceClient, networkRef string) (string, error) {
    88  	if _, err := uuid.Parse(networkRef); err != nil {
    89  		return GetFloatingIPNetworkIDByName(client, networkRef)
    90  	}
    91  
    92  	return networkRef, nil
    93  }
    94  
    95  // ExternalNetwork is a network with external router.
    96  type ExternalNetwork struct {
    97  	networks.Network
    98  	external.NetworkExternalExt
    99  }
   100  
   101  // GetFloatingIPNetworkIDByName searches for the external network ID by the provided name.
   102  func GetFloatingIPNetworkIDByName(client *gophercloud.ServiceClient, networkName string) (string, error) {
   103  	var externalNetworks []ExternalNetwork
   104  
   105  	allPages, err := networks.List(client, networks.ListOpts{
   106  		Name: networkName,
   107  	}).AllPages()
   108  	if err != nil {
   109  		return "", err
   110  	}
   111  
   112  	if err := networks.ExtractNetworksInto(allPages, &externalNetworks); err != nil {
   113  		return "", err
   114  	}
   115  
   116  	if len(externalNetworks) == 0 {
   117  		return "", fmt.Errorf("can't find external network %s", networkName)
   118  	}
   119  	// Check and return the first external network.
   120  	if !externalNetworks[0].External {
   121  		return "", fmt.Errorf("network %s is not external", networkName)
   122  	}
   123  
   124  	return externalNetworks[0].ID, nil
   125  }