115 lines
3.4 KiB
Go
115 lines
3.4 KiB
Go
|
package openstack
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/gophercloud/gophercloud"
|
||
|
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces"
|
||
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/external"
|
||
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
|
||
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/networks"
|
||
|
"github.com/gophercloud/gophercloud/pagination"
|
||
|
)
|
||
|
|
||
|
// ExternalNetwork is a network with external router.
|
||
|
type ExternalNetwork struct {
|
||
|
networks.Network
|
||
|
external.NetworkExternalExt
|
||
|
}
|
||
|
|
||
|
// FindExternalNetwork returns existing network with external router.
|
||
|
// It will return first network if there are many.
|
||
|
func FindExternalNetwork(client *gophercloud.ServiceClient) (*ExternalNetwork, error) {
|
||
|
var externalNetworks []ExternalNetwork
|
||
|
|
||
|
allPages, err := networks.List(client, networks.ListOpts{
|
||
|
Status: "ACTIVE",
|
||
|
}).AllPages()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
// Extract external networks from found networks.
|
||
|
err = networks.ExtractNetworksInto(allPages, &externalNetworks)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if len(externalNetworks) == 0 {
|
||
|
return nil, fmt.Errorf("no external networks found")
|
||
|
}
|
||
|
|
||
|
// Return the first external network.
|
||
|
return &externalNetworks[0], nil
|
||
|
}
|
||
|
|
||
|
// CheckFloatingIP gets a floating IP by its ID and checks if it is already
|
||
|
// associated with any internal interface.
|
||
|
// It returns floating IP if it can be used.
|
||
|
func CheckFloatingIP(client *gophercloud.ServiceClient, id string) (*floatingips.FloatingIP, error) {
|
||
|
floatingIP, err := floatingips.Get(client, id).Extract()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if floatingIP.PortID != "" {
|
||
|
return nil, fmt.Errorf("provided floating IP '%s' is already associated with port '%s'",
|
||
|
id, floatingIP.PortID)
|
||
|
}
|
||
|
|
||
|
return floatingIP, nil
|
||
|
}
|
||
|
|
||
|
// FindFreeFloatingIP returns free unassociated floating IP.
|
||
|
// It will return first floating IP if there are many.
|
||
|
func FindFreeFloatingIP(client *gophercloud.ServiceClient) (*floatingips.FloatingIP, error) {
|
||
|
var freeFloatingIP *floatingips.FloatingIP
|
||
|
|
||
|
pager := floatingips.List(client, floatingips.ListOpts{
|
||
|
Status: "DOWN",
|
||
|
})
|
||
|
err := pager.EachPage(func(page pagination.Page) (bool, error) {
|
||
|
candidates, err := floatingips.ExtractFloatingIPs(page)
|
||
|
if err != nil {
|
||
|
return false, err // stop and throw error out
|
||
|
}
|
||
|
|
||
|
for _, candidate := range candidates {
|
||
|
if candidate.PortID != "" {
|
||
|
continue // this floating IP is associated with port, move to next in list
|
||
|
}
|
||
|
|
||
|
// Floating IP is able to be allocated.
|
||
|
freeFloatingIP = &candidate
|
||
|
return false, nil // stop iterating over pages
|
||
|
}
|
||
|
return true, nil // try the next page
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if freeFloatingIP == nil {
|
||
|
return nil, fmt.Errorf("no free floating IPs found")
|
||
|
}
|
||
|
|
||
|
return freeFloatingIP, nil
|
||
|
}
|
||
|
|
||
|
// GetInstancePortID returns internal port of the instance that can be used for
|
||
|
// the association of a floating IP.
|
||
|
// It will return an ID of a first port if there are many.
|
||
|
func GetInstancePortID(client *gophercloud.ServiceClient, id string) (string, error) {
|
||
|
interfacesPage, err := attachinterfaces.List(client, id).AllPages()
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
interfaces, err := attachinterfaces.ExtractInterfaces(interfacesPage)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
if len(interfaces) == 0 {
|
||
|
return "", fmt.Errorf("instance '%s' has no interfaces", id)
|
||
|
}
|
||
|
|
||
|
return interfaces[0].PortID, nil
|
||
|
}
|