Merge pull request #121 from echohead/floating-ips-rax

Add support for floating IPs using nova API.
diff --git a/floating_ips.go b/floating_ips.go
new file mode 100644
index 0000000..4c27347
--- /dev/null
+++ b/floating_ips.go
@@ -0,0 +1,83 @@
+package gophercloud
+
+import (
+	"fmt"
+	"github.com/racker/perigee"
+)
+
+func (gsp *genericServersProvider) ListFloatingIps() ([]FloatingIp, error) {
+	var fips []FloatingIp
+
+	err := gsp.context.WithReauth(gsp.access, func() error {
+		url := gsp.endpoint + "/os-floating-ips"
+		return perigee.Get(url, perigee.Options{
+			CustomClient: gsp.context.httpClient,
+			Results: &struct {
+				FloatingIps *[]FloatingIp `json:"floating_ips"`
+			}{&fips},
+			MoreHeaders: map[string]string{
+				"X-Auth-Token": gsp.access.AuthToken(),
+			},
+		})
+	})
+	return fips, err
+}
+
+func (gsp *genericServersProvider) CreateFloatingIp(pool string) (FloatingIp, error) {
+	var fip *FloatingIp
+
+	err := gsp.context.WithReauth(gsp.access, func() error {
+		url := gsp.endpoint + "/os-floating-ips"
+		return perigee.Post(url, perigee.Options{
+			CustomClient: gsp.context.httpClient,
+			ReqBody: map[string]string{
+				"pool": pool,
+			},
+			Results: &struct {
+				FloatingIp **FloatingIp `json:"floating_ip"`
+			}{&fip},
+			MoreHeaders: map[string]string{
+				"X-Auth-Token": gsp.access.AuthToken(),
+			},
+		})
+	})
+
+	return *fip, err
+}
+
+func (gsp *genericServersProvider) AssociateFloatingIp(serverId string, ip FloatingIp) error {
+	return gsp.context.WithReauth(gsp.access, func() error {
+		ep := fmt.Sprintf("%s/servers/%s/action", gsp.endpoint, serverId)
+		return perigee.Post(ep, perigee.Options{
+			CustomClient: gsp.context.httpClient,
+			ReqBody: map[string](map[string]string){
+				"addFloatingIp": map[string]string{"address": ip.Ip},
+			},
+			MoreHeaders: map[string]string{
+				"X-Auth-Token": gsp.access.AuthToken(),
+			},
+			OkCodes: []int{202},
+		})
+	})
+}
+
+func (gsp *genericServersProvider) DeleteFloatingIp(ip FloatingIp) error {
+	return gsp.context.WithReauth(gsp.access, func() error {
+		ep := fmt.Sprintf("%s/os-floating-ips/%s", gsp.endpoint, ip.Id)
+		return perigee.Delete(ep, perigee.Options{
+			CustomClient: gsp.context.httpClient,
+			MoreHeaders: map[string]string{
+				"X-Auth-Token": gsp.access.AuthToken(),
+			},
+			OkCodes: []int{202},
+		})
+	})
+}
+
+type FloatingIp struct {
+	Id         string `json:"id"`
+	Pool       string `json:"pool"`
+	Ip         string `json:"ip"`
+	FixedIp    string `json:"fixed_ip"`
+	InstanceId string `json:"instance_id"`
+}
diff --git a/interfaces.go b/interfaces.go
index 7a9c7eb..6340c1c 100644
--- a/interfaces.go
+++ b/interfaces.go
@@ -150,6 +150,18 @@
 	// Example: ListAddressesByNetwork("234-4353-4jfrj-43j2s", "private")
 	ListAddressesByNetwork(id, networkLabel string) (NetworkAddress, error)
 
+	// ListFloatingIps yields the list of all floating IP addresses allocated to the current project.
+	ListFloatingIps() ([]FloatingIp, error)
+
+	// CreateFloatingIp allocates a new IP from the named pool to the current project.
+	CreateFloatingIp(pool string) (FloatingIp, error)
+
+	// DeleteFloatingIp returns the specified IP from the current project to the pool.
+	DeleteFloatingIp(ip FloatingIp) error
+
+	// AssociateFloatingIp associates the given floating IP to the given server id.
+	AssociateFloatingIp(serverId string, ip FloatingIp) error
+
 	// Images
 
 	// ListImages yields the list of available operating system images.  This function