Merge "Fixes LP#902358 - Test case for Floating IPs"
diff --git a/tempest/openstack.py b/tempest/openstack.py
index a3fe71d..3504589 100644
--- a/tempest/openstack.py
+++ b/tempest/openstack.py
@@ -7,6 +7,7 @@
from tempest.services.nova.json.extensions_client import ExtensionsClient
from tempest.services.nova.json.security_groups_client \
import SecurityGroupsClient
+from tempest.services.nova.json.floating_ips_client import FloatingIPsClient
from tempest.services.nova.json.keypairs_client import KeyPairsClient
@@ -55,6 +56,11 @@
self.config.nova.api_key,
self.config.nova.auth_url,
self.config.nova.tenant_name)
+ self.floating_ips_client = FloatingIPsClient(self.config,
+ self.config.nova.username,
+ self.config.nova.api_key,
+ self.config.nova.auth_url,
+ self.config.nova.tenant_name)
else:
#Assuming basic/native authentication
self.servers_client = ServersClient(self.config,
@@ -85,6 +91,10 @@
self.config.nova.username,
self.config.nova.api_key,
self.config.nova.auth_url)
+ self.floating_ips_client = FloatingIPsClient(self.config,
+ self.config.nova.username,
+ self.config.nova.api_key,
+ self.config.nova.auth_url)
class ServiceManager(object):
diff --git a/tempest/services/nova/json/floating_ips_client.py b/tempest/services/nova/json/floating_ips_client.py
new file mode 100644
index 0000000..8bd276f
--- /dev/null
+++ b/tempest/services/nova/json/floating_ips_client.py
@@ -0,0 +1,63 @@
+from tempest.common import rest_client
+from tempest import exceptions
+import json
+
+
+class FloatingIPsClient(object):
+ def __init__(self, config, username, key, auth_url, tenant_name=None):
+ self.config = config
+ self.client = rest_client.RestClient(config, username, key,
+ auth_url, tenant_name)
+
+ def list_floating_ips(self, params=None):
+ """Returns a list of all floating IPs filtered by any parameters"""
+ url = 'os-floating-ips'
+ if params != None:
+ param_list = []
+ for param, value in params.iteritems():
+ param_list.append("%s=%s&" % (param, value))
+ url += '?' + ' '.join(param_list)
+ resp, body = self.client.get(url)
+ body = json.loads(body)
+ return resp, body['floating_ips']
+
+ def get_floating_ip_details(self, floating_ip_id):
+ """Get the details of a floating IP"""
+ url = "os-floating-ips/%s" % str(floating_ip_id)
+ resp, body = self.client.get(url)
+ body = json.loads(body)
+ if resp.status == 404:
+ raise exceptions.NotFound(body)
+ return resp, body['floating_ip']
+
+ def create_floating_ip(self):
+ """Allocate a floating IP to the project"""
+ url = 'os-floating-ips'
+ resp, body = self.client.post(url, None, None)
+ body = json.loads(body)
+ return resp, body['floating_ip']
+
+ def delete_floating_ip(self, floating_ip_id):
+ """Deletes the provided floating IP from the project"""
+ url = "os-floating-ips/%s" % str(floating_ip_id)
+ resp, body = self.client.delete(url)
+ return resp, body
+
+ def associate_floating_ip_to_server(self, floating_ip_id, fixed_ip_addr):
+ """Associate the provided floating IP to a specific server"""
+ url = "os-floating-ips/%s/associate" % str(floating_ip_id)
+ post_body = {
+ 'associate_address': {
+ 'fixed_ip': fixed_ip_addr,
+ }
+ }
+
+ post_body = json.dumps(post_body)
+ resp, body = self.client.post(url, post_body, None)
+ return resp, body
+
+ def disassociate_floating_ip_from_server(self, floating_ip_id):
+ """Disassociate the provided floating IP from a specific server"""
+ url = "os-floating-ips/%s/disassociate" % str(floating_ip_id)
+ resp, body = self.client.post(url, None, None)
+ return resp, body
diff --git a/tempest/tests/test_floating_ips_actions.py b/tempest/tests/test_floating_ips_actions.py
new file mode 100644
index 0000000..ab9e22d
--- /dev/null
+++ b/tempest/tests/test_floating_ips_actions.py
@@ -0,0 +1,160 @@
+from nose.plugins.attrib import attr
+from tempest import openstack
+import unittest2 as unittest
+from tempest import exceptions
+from tempest.common.utils.data_utils import rand_name
+
+
+class FloatingIPsTest(unittest.TestCase):
+ server_id = None
+ floating_ip_id = None
+
+ @classmethod
+ def setUpClass(cls):
+ cls.os = openstack.Manager()
+ cls.client = cls.os.floating_ips_client
+ cls.servers_client = cls.os.servers_client
+ cls.config = cls.os.config
+ cls.image_ref = cls.config.env.image_ref
+ cls.flavor_ref = cls.config.env.flavor_ref
+ #Server creation
+ resp, server = cls.servers_client.create_server('floating-server',
+ cls.image_ref,
+ cls.flavor_ref)
+ cls.servers_client.wait_for_server_status(server['id'], 'ACTIVE')
+ cls.server_id = server['id']
+ resp, body = cls.servers_client.get_server(server['id'])
+ cls.fixed_ip_addr = body['addresses']['private'][0]['addr']
+ #Floating IP creation
+ resp, body = cls.client.create_floating_ip()
+ cls.floating_ip_id = body['id']
+ #Generating a nonexistant floatingIP id
+ cls.floating_ip_ids = []
+ resp, body = cls.client.list_floating_ips()
+ for i in range(len(body)):
+ cls.floating_ip_ids.append(body[i]['id'])
+ while True:
+ cls.non_exist_id = rand_name('999')
+ if cls.non_exist_id not in cls.floating_ip_ids:
+ break
+
+ @classmethod
+ def tearDownClass(cls):
+ #Deleting the server which is created in this method
+ resp, body = cls.servers_client.delete_server(cls.server_id)
+ #Deleting the floating IP which is created in this method
+ resp, body = cls.client.delete_floating_ip(cls.floating_ip_id)
+
+ @attr(type='positive')
+ def test_allocate_floating_ip(self):
+ """
+ Positive test:Allocation of a new floating IP to a project
+ should be succesfull
+ """
+ resp, body = self.client.create_floating_ip()
+ self.assertEqual(200, resp.status)
+ floating_ip_id_allocated = body['id']
+ resp, floating_ip_details = \
+ self.client.get_floating_ip_details(floating_ip_id_allocated)
+ #Checking if the details of allocated IP is in list of floating IP
+ resp, body = self.client.list_floating_ips()
+ self.assertTrue(floating_ip_details in body)
+ #Deleting the floating IP which is created in this method
+ self.client.delete_floating_ip(floating_ip_id_allocated)
+
+ @attr(type='positive')
+ def test_delete_floating_ip(self):
+ """
+ Positive test:Deletion of valid floating IP from project
+ should be succesfull
+ """
+ #Creating the floating IP that is to be deleted in this method
+ resp, floating_ip_body = self.client.create_floating_ip()
+ #Storing the details of floating IP before deleting it
+ resp, floating_ip_details = \
+ self.client.get_floating_ip_details(floating_ip_body['id'])
+ #Deleting the floating IP from the project
+ resp, body = self.client.delete_floating_ip(floating_ip_body['id'])
+ self.assertEqual(202, resp.status)
+ #Listing the floating IPs and checking the existence
+ #of deleted floating IP
+ resp, body = self.client.list_floating_ips()
+ self.assertTrue(floating_ip_details not in body)
+
+ @attr(type='positive')
+ def test_associate_floating_ip(self):
+ """
+ Positive test:Associate the provided floating IP to a specific server
+ should be successfull
+ l"""
+ #Association of floating IP to fixed IP address
+ resp, body =\
+ self.client.associate_floating_ip_to_server(self.floating_ip_id,
+ self.fixed_ip_addr)
+ self.assertEqual(202, resp.status)
+ #Disassociation of floating IP that was associated in this method
+ resp, body = \
+ self.client.disassociate_floating_ip_from_server(floating_ip_id)
+
+ @attr(type='positive')
+ def test_dissociate_floating_ip(self):
+ """
+ Positive test:Dissociate the provided floating IP
+ from a specific server should be successfull
+ """
+ #Association of floating IP to a specific server
+ #so as to check dissociation
+ resp, body = \
+ self.client.associate_floating_ip_to_server(self.floating_ip_id,
+ self.fixed_ip_addr)
+ #Disassociation of floating IP
+ resp, body = \
+ self.client.disassociate_floating_ip_from_server(self.floating_ip_id)
+ self.assertEqual(202, resp.status)
+
+ @attr(type='negative')
+ def test_delete_nonexistant_floating_ip(self):
+ """
+
+ Negative test:Deletion of a nonexistant floating IP
+ from project should fail
+ """
+ #Deleting the non existant floating IP
+ try:
+ resp, body = self.client.delete_floating_ip(self.non_exist_id)
+ except exceptions.NotFound:
+ pass
+ else:
+ self.fail('Should not be able to delete a nonexistant floating IP')
+
+ @attr(type='negative')
+ def test_associate_nonexistant_floating_ip(self):
+ """
+ Negative test:Association of a non existant floating IP
+ to specific server should fail
+ """
+ #Associating non existant floating IP
+ try:
+ resp, body = \
+ self.client.associate_floating_ip_to_server(self.non_exist_id,
+ self.fixed_ip_addr)
+ except exceptions.NotFound:
+ pass
+ else:
+ self.fail('Should not be able to associate'
+ ' a nonexistant floating IP')
+
+ @attr(type='negative')
+ def test_dissociate_nonexistant_floating_ip(self):
+ """
+ Negative test:Dissociation of a non existant floating IP should fail
+ """
+ #Dissociating non existant floating IP
+ try:
+ resp, body = \
+ self.client.disassociate_floating_ip_from_server(self.non_exist_id)
+ except exceptions.NotFound:
+ pass
+ else:
+ self.fail('Should not be able to dissociate'
+ ' a nonexistant floating IP')
diff --git a/tempest/tests/test_list_floating_ips.py b/tempest/tests/test_list_floating_ips.py
new file mode 100644
index 0000000..2de6d6b
--- /dev/null
+++ b/tempest/tests/test_list_floating_ips.py
@@ -0,0 +1,82 @@
+from nose.plugins.attrib import attr
+from tempest import openstack
+import unittest2 as unittest
+from tempest import exceptions
+from tempest.common.utils.data_utils import rand_name
+
+
+class FloatingIPDetailsTest(unittest.TestCase):
+
+ @classmethod
+ def setUpClass(cls):
+ cls.os = openstack.Manager()
+ cls.client = cls.os.floating_ips_client
+ cls.floating_ip = []
+ cls.floating_ip_id = []
+ cls.random_number = 0
+ for i in range(3):
+ resp, body = cls.client.create_floating_ip()
+ cls.floating_ip.append(body)
+ cls.floating_ip_id.append(body['id'])
+
+ @classmethod
+ def tearDownClass(cls):
+ for i in range(3):
+ cls.client.delete_floating_ip(cls.floating_ip_id[i])
+
+ @attr(type='positive')
+ def test_list_floating_ips(self):
+ """Positive test:Should return the list of floating IPs"""
+ resp, body = self.client.list_floating_ips()
+ self.assertEqual(200, resp.status)
+ floating_ips = body
+ self.assertNotEqual(0, len(floating_ips),
+ "Expected floating IPs. Got zero.")
+ for i in range(3):
+ self.assertTrue(self.floating_ip[i] in floating_ips)
+
+ @attr(type='positive')
+ def test_get_floating_ip_details(self):
+ """Positive test:Should be able to GET the details of floatingIP"""
+ #Creating a floating IP for which details are to be checked
+ resp, body = self.client.create_floating_ip()
+ floating_ip_instance_id = body['instance_id']
+ floating_ip_ip = body['ip']
+ floating_ip_fixed_ip = body['fixed_ip']
+ floating_ip_id = body['id']
+ resp, body = \
+ self.client.get_floating_ip_details(floating_ip_id)
+ self.assertEqual(200, resp.status)
+ #Comparing the details of floating IP
+ self.assertEqual(floating_ip_instance_id,
+ body['instance_id'])
+ self.assertEqual(floating_ip_ip, body['ip'])
+ self.assertEqual(floating_ip_fixed_ip,
+ body['fixed_ip'])
+ self.assertEqual(floating_ip_id, body['id'])
+ #Deleting the floating IP created in this method
+ self.client.delete_floating_ip(floating_ip_id)
+
+ @attr(type='negative')
+ def test_get_nonexistant_floating_ip_details(self):
+ """
+ Negative test:Should not be able to GET the details
+ of nonexistant floating IP
+ """
+ floating_ip_id = []
+ resp, body = self.client.list_floating_ips()
+ for i in range(len(body)):
+ floating_ip_id.append(body[i]['id'])
+ #Creating a nonexistant floatingIP id
+ while True:
+ non_exist_id = rand_name('999')
+ if non_exist_id not in floating_ip_id:
+ break
+ try:
+ resp, body = \
+ self.client.get_floating_ip_details(non_exist_id)
+ except exceptions.NotFound:
+ pass
+ else:
+ self.fail('Should not be able to GET the details from a'
+ 'nonexistant floating IP')