From be299d8424074f411118b74044a5e040bda4956d Mon Sep 17 00:00:00 2001
From: Phil Day <philip.day@hp.com>
Date: Fri, 17 May 2013 12:39:46 +0100
Subject: [PATCH] Adds support for ExtendedFloatingIps APi extension

Allow a floating IP to be associated to a specific fixed IP

This is the client side of:
https://review.openstack.org/#/c/26113/15

Change-Id: I05f8a0dc60268535231b95a6664719015f67a318
---
 novaclient/tests/v1_1/fakes.py        |  4 +++-
 novaclient/tests/v1_1/test_servers.py | 13 +++++++++++++
 novaclient/v1_1/servers.py            | 18 ++++++++++++++----
 novaclient/v1_1/shell.py              |  6 +++++-
 4 files changed, 35 insertions(+), 6 deletions(-)

diff --git a/novaclient/tests/v1_1/fakes.py b/novaclient/tests/v1_1/fakes.py
index 552a0847a..528c26d22 100644
--- a/novaclient/tests/v1_1/fakes.py
+++ b/novaclient/tests/v1_1/fakes.py
@@ -517,7 +517,9 @@ class FakeHTTPClient(base_client.HTTPClient):
         elif action == 'removeFixedIp':
             assert body[action].keys() == ['address']
         elif action == 'addFloatingIp':
-            assert body[action].keys() == ['address']
+            assert (body[action].keys() == ['address'] or
+                    body[action].keys() == ['fixed_address',
+                                                'address'])
         elif action == 'removeFloatingIp':
             assert body[action].keys() == ['address']
         elif action == 'createImage':
diff --git a/novaclient/tests/v1_1/test_servers.py b/novaclient/tests/v1_1/test_servers.py
index f9b48a278..5874a006c 100644
--- a/novaclient/tests/v1_1/test_servers.py
+++ b/novaclient/tests/v1_1/test_servers.py
@@ -251,6 +251,19 @@ class ServersTest(utils.TestCase):
         s.add_floating_ip(f)
         cs.assert_called('POST', '/servers/1234/action')
 
+    def test_add_floating_ip_to_fixed(self):
+        s = cs.servers.get(1234)
+        s.add_floating_ip('11.0.0.1', fixed_address='12.0.0.1')
+        cs.assert_called('POST', '/servers/1234/action')
+        cs.servers.add_floating_ip(s, '11.0.0.1',
+                                   fixed_address='12.0.0.1')
+        cs.assert_called('POST', '/servers/1234/action')
+        f = cs.floating_ips.list()[0]
+        cs.servers.add_floating_ip(s, f)
+        cs.assert_called('POST', '/servers/1234/action')
+        s.add_floating_ip(f)
+        cs.assert_called('POST', '/servers/1234/action')
+
     def test_remove_floating_ip(self):
         s = cs.servers.get(1234)
         s.remove_floating_ip('11.0.0.1')
diff --git a/novaclient/v1_1/servers.py b/novaclient/v1_1/servers.py
index 440c63192..260d81806 100644
--- a/novaclient/v1_1/servers.py
+++ b/novaclient/v1_1/servers.py
@@ -97,13 +97,15 @@ class Server(base.Resource):
         """
         self.manager.add_fixed_ip(self, network_id)
 
-    def add_floating_ip(self, address):
+    def add_floating_ip(self, address, fixed_address=None):
         """
         Add floating IP to an instance
 
         :param address: The ip address or FloatingIP to add to the instance
+        :param fixed_address: The fixedIP address the FloatingIP is to be
+               associated with (optional)
         """
-        self.manager.add_floating_ip(self, address)
+        self.manager.add_floating_ip(self, address, fixed_address)
 
     def remove_floating_ip(self, address):
         """
@@ -392,16 +394,24 @@ class ServerManager(local_base.BootingManagerWithFind):
         """
         self._action('removeFixedIp', server, {'address': address})
 
-    def add_floating_ip(self, server, address):
+    def add_floating_ip(self, server, address, fixed_address=None):
         """
         Add a floating ip to an instance
 
         :param server: The :class:`Server` (or its ID) to add an IP to.
         :param address: The FloatingIP or string floating address to add.
+        :param fixed_address: The FixedIP the floatingIP should be
+                              associated with (optional)
         """
 
         address = address.ip if hasattr(address, 'ip') else address
-        self._action('addFloatingIp', server, {'address': address})
+        if fixed_address:
+            if hasattr(fixed_address, 'ip'):
+                fixed_address = fixed_address.ip
+            self._action('addFloatingIp', server,
+                         {'address': address, 'fixed_address': fixed_address})
+        else:
+            self._action('addFloatingIp', server, {'address': address})
 
     def remove_floating_ip(self, server, address):
         """
diff --git a/novaclient/v1_1/shell.py b/novaclient/v1_1/shell.py
index 0bdabe4f1..f1d5d6779 100644
--- a/novaclient/v1_1/shell.py
+++ b/novaclient/v1_1/shell.py
@@ -1707,10 +1707,14 @@ def do_console_log(cs, args):
 
 @utils.arg('server', metavar='<server>', help='Name or ID of server.')
 @utils.arg('address', metavar='<address>', help='IP Address.')
+@utils.arg('--fixed-address',
+           metavar='<fixed_address>',
+           default=None,
+           help='Fixed IP Address to associate with.')
 def do_add_floating_ip(cs, args):
     """Add a floating IP address to a server."""
     server = _find_server(cs, args.server)
-    server.add_floating_ip(args.address)
+    server.add_floating_ip(args.address, args.fixed_address)
 
 
 @utils.arg('server', metavar='<server>', help='Name or ID of server.')