@ -5,7 +5,10 @@ import (
"log"
"strings"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
nfloatingips "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
"github.com/hashicorp/terraform/helper/schema"
)
@ -79,12 +82,67 @@ func resourceComputeFloatingIPAssociateV2Create(d *schema.ResourceData, meta int
}
func resourceComputeFloatingIPAssociateV2Read ( d * schema . ResourceData , meta interface { } ) error {
config := meta . ( * Config )
computeClient , err := config . computeV2Client ( GetRegion ( d ) )
if err != nil {
return fmt . Errorf ( "Error creating OpenStack compute client: %s" , err )
}
// Obtain relevant info from parsing the ID
floatingIP , instanceId , fixedIP , err := parseComputeFloatingIPAssociateId ( d . Id ( ) )
if err != nil {
return err
}
// Now check and see whether the floating IP still exists.
// First try to do this by querying the Network API.
networkEnabled := true
networkClient , err := config . networkingV2Client ( GetRegion ( d ) )
if err != nil {
networkEnabled = false
}
var exists bool
if networkEnabled {
log . Printf ( "[DEBUG] Checking for Floating IP existence via Network API" )
exists , err = resourceComputeFloatingIPAssociateV2NetworkExists ( networkClient , floatingIP )
} else {
log . Printf ( "[DEBUG] Checking for Floating IP existence via Compute API" )
exists , err = resourceComputeFloatingIPAssociateV2ComputeExists ( computeClient , floatingIP )
}
if err != nil {
return err
}
if ! exists {
d . SetId ( "" )
}
// Next, see if the instance still exists
instance , err := servers . Get ( computeClient , instanceId ) . Extract ( )
if err != nil {
if CheckDeleted ( d , err , "instance" ) == nil {
return nil
}
}
// Finally, check and see if the floating ip is still associated with the instance.
var associated bool
for _ , networkAddresses := range instance . Addresses {
for _ , element := range networkAddresses . ( [ ] interface { } ) {
address := element . ( map [ string ] interface { } )
if address [ "OS-EXT-IPS:type" ] == "floating" && address [ "addr" ] == floatingIP {
associated = true
}
}
}
if ! associated {
d . SetId ( "" )
}
// Set the attributes pulled from the composed resource ID
d . Set ( "floating_ip" , floatingIP )
d . Set ( "instance_id" , instanceId )
d . Set ( "fixed_ip" , fixedIP )
@ -128,3 +186,49 @@ func parseComputeFloatingIPAssociateId(id string) (string, string, string, error
return floatingIP , instanceId , fixedIP , nil
}
func resourceComputeFloatingIPAssociateV2NetworkExists ( networkClient * gophercloud . ServiceClient , floatingIP string ) ( bool , error ) {
listOpts := nfloatingips . ListOpts {
FloatingIP : floatingIP ,
}
allPages , err := nfloatingips . List ( networkClient , listOpts ) . AllPages ( )
if err != nil {
return false , err
}
allFips , err := nfloatingips . ExtractFloatingIPs ( allPages )
if err != nil {
return false , err
}
if len ( allFips ) > 1 {
return false , fmt . Errorf ( "There was a problem retrieving the floating IP" )
}
if len ( allFips ) == 0 {
return false , nil
}
return true , nil
}
func resourceComputeFloatingIPAssociateV2ComputeExists ( computeClient * gophercloud . ServiceClient , floatingIP string ) ( bool , error ) {
// If the Network API isn't available, fall back to the deprecated Compute API.
allPages , err := floatingips . List ( computeClient ) . AllPages ( )
if err != nil {
return false , err
}
allFips , err := floatingips . ExtractFloatingIPs ( allPages )
if err != nil {
return false , err
}
for _ , f := range allFips {
if f . IP == floatingIP {
return true , nil
}
}
return false , nil
}