Added test case to check floating IP API operations

Added a test case by the name
'test_create_list_show_update_delete_floating_ip' to check
floating IP API operations. Also added supporting methods
in network_client.py

Implements blueprint: quantum-test-l2-abstraction

Change-Id: I13ca20a249e9eba0a52e6eb3c6e82baaa38fc5a0
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
new file mode 100644
index 0000000..017864f
--- /dev/null
+++ b/tempest/api/network/test_floating_ips.py
@@ -0,0 +1,135 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack Foundation
+# All Rights Reserved.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+
+from tempest.api.network import base
+from tempest.common.utils.data_utils import rand_name
+from tempest.test import attr
+
+
+class FloatingIPTest(base.BaseNetworkTest):
+    _interface = 'json'
+
+    """
+    Tests the following operations in the Quantum API using the REST client for
+    Quantum:
+
+        Create a Floating IP
+        Update a Floating IP
+        Delete a Floating IP
+        List all Floating IPs
+        Show Floating IP details
+
+    v2.0 of the Quantum API is assumed. It is also assumed that the following
+    options are defined in the [network] section of etc/tempest.conf:
+
+        public_network_id which is the id for the external network present
+    """
+
+    @classmethod
+    def setUpClass(cls):
+        super(FloatingIPTest, cls).setUpClass()
+        cls.ext_net_id = cls.config.network.public_network_id
+
+        # Create network, subnet, router and add interface
+        cls.network = cls.create_network()
+        cls.subnet = cls.create_subnet(cls.network)
+        resp, router = cls.client.create_router(
+            rand_name('router-'),
+            external_gateway_info={"network_id":
+                                   cls.network_cfg.public_network_id})
+        cls.router = router['router']
+        resp, _ = cls.client.add_router_interface_with_subnet_id(
+            cls.router['id'], cls.subnet['id'])
+        cls.port = list()
+        # Create two ports one each for Creation and Updating of floatingIP
+        for i in range(2):
+            resp, port = cls.client.create_port(cls.network['id'])
+            cls.port.append(port['port'])
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.client.remove_router_interface_with_subnet_id(cls.router['id'],
+                                                          cls.subnet['id'])
+        for i in range(2):
+            cls.client.delete_port(cls.port[i]['id'])
+        cls.client.delete_router(cls.router['id'])
+        super(FloatingIPTest, cls).tearDownClass()
+
+    def _delete_floating_ip(self, floating_ip_id):
+        # Deletes a floating IP and verifies if it is deleted or not
+        resp, _ = self.client.delete_floating_ip(floating_ip_id)
+        self.assertEqual(204, resp.status)
+        # Asserting that the floating_ip is not found in list after deletion
+        resp, floating_ips = self.client.list_floating_ips()
+        floatingip_id_list = list()
+        for f in floating_ips['floatingips']:
+            floatingip_id_list.append(f['id'])
+        self.assertNotIn(floating_ip_id, floatingip_id_list)
+
+    @attr(type='smoke')
+    def test_create_list_show_update_delete_floating_ip(self):
+        # Creates a floating IP
+        resp, floating_ip = self.client.create_floating_ip(
+            self.ext_net_id, port_id=self.port[0]['id'])
+        self.assertEqual('201', resp['status'])
+        create_floating_ip = floating_ip['floatingip']
+        self.assertIsNotNone(create_floating_ip['id'])
+        self.assertIsNotNone(create_floating_ip['tenant_id'])
+        self.assertIsNotNone(create_floating_ip['floating_ip_address'])
+        self.assertEqual(create_floating_ip['port_id'], self.port[0]['id'])
+        self.assertEqual(create_floating_ip['floating_network_id'],
+                         self.ext_net_id)
+        self.addCleanup(self._delete_floating_ip, create_floating_ip['id'])
+        # Verifies the details of a floating_ip
+        resp, floating_ip = self.client.show_floating_ip(
+            create_floating_ip['id'])
+        self.assertEqual('200', resp['status'])
+        show_floating_ip = floating_ip['floatingip']
+        self.assertEqual(show_floating_ip['id'], create_floating_ip['id'])
+        self.assertEqual(show_floating_ip['floating_network_id'],
+                         self.ext_net_id)
+        self.assertEqual(show_floating_ip['tenant_id'],
+                         create_floating_ip['tenant_id'])
+        self.assertEqual(show_floating_ip['floating_ip_address'],
+                         create_floating_ip['floating_ip_address'])
+        self.assertEqual(show_floating_ip['port_id'], self.port[0]['id'])
+
+        # Verify the floating ip exists in the list of all floating_ips
+        resp, floating_ips = self.client.list_floating_ips()
+        self.assertEqual('200', resp['status'])
+        floatingip_id_list = list()
+        for f in floating_ips['floatingips']:
+            floatingip_id_list.append(f['id'])
+        self.assertIn(create_floating_ip['id'], floatingip_id_list)
+
+        # Associate floating IP to the other port
+        resp, floating_ip = self.client.update_floating_ip(
+            create_floating_ip['id'], port_id=self.port[1]['id'])
+        self.assertEqual('200', resp['status'])
+        update_floating_ip = floating_ip['floatingip']
+        self.assertEqual(update_floating_ip['port_id'], self.port[1]['id'])
+        self.assertIsNotNone(update_floating_ip['fixed_ip_address'])
+        self.assertEqual(update_floating_ip['router_id'], self.router['id'])
+
+        # Disassociate floating IP from the port
+        resp, floating_ip = self.client.update_floating_ip(
+            create_floating_ip['id'], port_id=None)
+        self.assertEqual('200', resp['status'])
+        update_floating_ip = floating_ip['floatingip']
+        self.assertIsNone(update_floating_ip['port_id'])
+        self.assertIsNone(update_floating_ip['fixed_ip_address'])
+        self.assertIsNone(update_floating_ip['router_id'])
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index 588dc8f..ef12a00 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -24,7 +24,7 @@
     V1 API has been removed from the code base.
 
     Implements create, delete, update, list and show for the basic Neutron
-    abstractions (networks, sub-networks, routers and ports):
+    abstractions (networks, sub-networks, routers, ports and floating IP):
 
     Implements add/remove interface to router using subnet ID / port ID
 
@@ -285,3 +285,39 @@
         resp, body = self.put(uri, update_body, self.headers)
         body = json.loads(body)
         return resp, body
+
+    def create_floating_ip(self, ext_network_id, **kwargs):
+        post_body = {
+            'floatingip': kwargs}
+        post_body['floatingip']['floating_network_id'] = ext_network_id
+        body = json.dumps(post_body)
+        uri = '%s/floatingips' % (self.uri_prefix)
+        resp, body = self.post(uri, headers=self.headers, body=body)
+        body = json.loads(body)
+        return resp, body
+
+    def show_floating_ip(self, floating_ip_id):
+        uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def list_floating_ips(self):
+        uri = '%s/floatingips' % (self.uri_prefix)
+        resp, body = self.get(uri, self.headers)
+        body = json.loads(body)
+        return resp, body
+
+    def delete_floating_ip(self, floating_ip_id):
+        uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id)
+        resp, body = self.delete(uri, self.headers)
+        return resp, body
+
+    def update_floating_ip(self, floating_ip_id, **kwargs):
+        post_body = {
+            'floatingip': kwargs}
+        body = json.dumps(post_body)
+        uri = '%s/floatingips/%s' % (self.uri_prefix, floating_ip_id)
+        resp, body = self.put(uri, headers=self.headers, body=body)
+        body = json.loads(body)
+        return resp, body