From af8c4e64cca3c9d4688ba3c4ec12297a6c3f4ec0 Mon Sep 17 00:00:00 2001 From: ivan-zhu Date: Wed, 22 Jan 2014 17:09:42 +0800 Subject: [PATCH] port flavors and server_password tests into nova v3 part2 this ports the flavors, server_password tests and corresponding client into v3 version. Partially implements blueprint nova-v3-api-tests Change-Id: Iaf2056d56429898d524536e54296bac5e479fd3e --- .../compute/flavors/flavor_details_v3.json | 6 +++ .../compute/flavors/flavors_list_v3.json | 24 +++++++++++ tempest/api/compute/v3/admin/test_flavors.py | 43 ++++++++----------- .../compute/v3/admin/test_flavors_negative.py | 23 ++++------ .../api/compute/v3/flavors/test_flavors.py | 40 ++++++++--------- .../v3/flavors/test_flavors_negative.py | 18 ++++---- .../v3/servers/test_server_password.py | 14 +++--- .../compute/v3/json/servers_client.py | 15 +++++++ 8 files changed, 104 insertions(+), 79 deletions(-) create mode 100644 etc/schemas/compute/flavors/flavor_details_v3.json create mode 100644 etc/schemas/compute/flavors/flavors_list_v3.json diff --git a/etc/schemas/compute/flavors/flavor_details_v3.json b/etc/schemas/compute/flavors/flavor_details_v3.json new file mode 100644 index 0000000000..d1c1077235 --- /dev/null +++ b/etc/schemas/compute/flavors/flavor_details_v3.json @@ -0,0 +1,6 @@ +{ + "name": "get-flavor-details", + "http-method": "GET", + "url": "flavors/%s", + "resources": ["flavor"] +} diff --git a/etc/schemas/compute/flavors/flavors_list_v3.json b/etc/schemas/compute/flavors/flavors_list_v3.json new file mode 100644 index 0000000000..d5388b388e --- /dev/null +++ b/etc/schemas/compute/flavors/flavors_list_v3.json @@ -0,0 +1,24 @@ +{ + "name": "list-flavors-with-detail", + "http-method": "GET", + "url": "flavors/detail", + "json-schema": { + "type": "object", + "properties": { + "min_ram": { + "type": "integer", + "results": { + "gen_none": 400, + "gen_string": 400 + } + }, + "min_disk": { + "type": "integer", + "results": { + "gen_none": 400, + "gen_string": 400 + } + } + } + } +} diff --git a/tempest/api/compute/v3/admin/test_flavors.py b/tempest/api/compute/v3/admin/test_flavors.py index 252f4be416..597c99b217 100644 --- a/tempest/api/compute/v3/admin/test_flavors.py +++ b/tempest/api/compute/v3/admin/test_flavors.py @@ -21,7 +21,7 @@ from tempest import exceptions from tempest import test -class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): +class FlavorsAdminV3Test(base.BaseV3ComputeAdminTest): """ Tests Flavors API Create and Delete that require admin privileges @@ -31,13 +31,10 @@ class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): @classmethod def setUpClass(cls): - super(FlavorsAdminTestJSON, cls).setUpClass() - if not test.is_extension_enabled('FlavorExtraData', 'compute'): - msg = "FlavorExtraData extension not enabled." - raise cls.skipException(msg) + super(FlavorsAdminV3Test, cls).setUpClass() - cls.client = cls.os_adm.flavors_client - cls.user_client = cls.os.flavors_client + cls.client = cls.flavors_admin_client + cls.user_client = cls.flavors_client cls.flavor_name_prefix = 'test_flavor_' cls.ram = 512 cls.vcpus = 1 @@ -48,7 +45,7 @@ class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): def flavor_clean_up(self, flavor_id): resp, body = self.client.delete_flavor(flavor_id) - self.assertEqual(resp.status, 202) + self.assertEqual(resp.status, 204) self.client.wait_for_resource_deletion(flavor_id) def _create_flavor(self, flavor_id): @@ -65,16 +62,17 @@ class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): swap=self.swap, rxtx=self.rxtx) self.addCleanup(self.flavor_clean_up, flavor['id']) - self.assertEqual(200, resp.status) + self.assertEqual(201, resp.status) self.assertEqual(flavor['name'], flavor_name) self.assertEqual(flavor['vcpus'], self.vcpus) self.assertEqual(flavor['disk'], self.disk) self.assertEqual(flavor['ram'], self.ram) self.assertEqual(flavor['swap'], self.swap) - self.assertEqual(flavor['rxtx_factor'], self.rxtx) - self.assertEqual(flavor['OS-FLV-EXT-DATA:ephemeral'], + if test.is_extension_enabled("os-flavor-rxtx", "compute_v3"): + self.assertEqual(flavor['os-flavor-rxtx:rxtx_factor'], self.rxtx) + self.assertEqual(flavor['ephemeral'], self.ephemeral) - self.assertEqual(flavor['os-flavor-access:is_public'], True) + self.assertEqual(flavor['flavor-access:is_public'], True) # Verify flavor is retrieved resp, flavor = self.client.get_flavor_details(flavor['id']) @@ -135,10 +133,11 @@ class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): def verify_flavor_response_extension(flavor): # check some extensions for the flavor create/show/detail response - self.assertEqual(flavor['swap'], '') - self.assertEqual(int(flavor['rxtx_factor']), 1) - self.assertEqual(int(flavor['OS-FLV-EXT-DATA:ephemeral']), 0) - self.assertEqual(flavor['os-flavor-access:is_public'], True) + self.assertEqual(flavor['swap'], 0) + if test.is_extension_enabled("os-flavor-rxtx", "compute_v3"): + self.assertEqual(int(flavor['os-flavor-rxtx:rxtx_factor']), 1) + self.assertEqual(int(flavor['ephemeral']), 0) + self.assertEqual(flavor['flavor-access:is_public'], True) flavor_name = data_utils.rand_name(self.flavor_name_prefix) new_flavor_id = data_utils.rand_int_id(start=1000) @@ -149,7 +148,7 @@ class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): self.disk, new_flavor_id) self.addCleanup(self.flavor_clean_up, flavor['id']) - self.assertEqual(200, resp.status) + self.assertEqual(201, resp.status) self.assertEqual(flavor['name'], flavor_name) self.assertEqual(flavor['ram'], self.ram) self.assertEqual(flavor['vcpus'], self.vcpus) @@ -219,11 +218,11 @@ class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): new_flavor_id, is_public="False") self.addCleanup(self.flavor_clean_up, flavor['id']) - self.assertEqual(200, resp.status) + self.assertEqual(201, resp.status) # Verify flavor is not used by other user self.assertRaises(exceptions.BadRequest, - self.os.servers_client.create_server, + self.servers_client.create_server, 'test', self.image_ref, flavor['id']) @test.attr(type='gate') @@ -304,13 +303,9 @@ class FlavorsAdminTestJSON(base.BaseV2ComputeAdminTest): self.disk, new_flavor_id) self.addCleanup(self.flavor_clean_up, flavor['id']) - self.assertEqual(200, resp.status) + self.assertEqual(201, resp.status) self.assertEqual(flavor['name'], flavor_name) self.assertEqual(flavor['vcpus'], self.vcpus) self.assertEqual(flavor['disk'], self.disk) self.assertEqual(flavor['ram'], int(ram)) self.assertEqual(int(flavor['id']), new_flavor_id) - - -class FlavorsAdminTestXML(FlavorsAdminTestJSON): - _interface = 'xml' diff --git a/tempest/api/compute/v3/admin/test_flavors_negative.py b/tempest/api/compute/v3/admin/test_flavors_negative.py index ad4ceebe27..f54de79449 100644 --- a/tempest/api/compute/v3/admin/test_flavors_negative.py +++ b/tempest/api/compute/v3/admin/test_flavors_negative.py @@ -21,7 +21,7 @@ from tempest import exceptions from tempest import test -class FlavorsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest): +class FlavorsAdminNegativeV3Test(base.BaseV3ComputeAdminTest): """ Tests Flavors API Create and Delete that require admin privileges @@ -31,13 +31,10 @@ class FlavorsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest): @classmethod def setUpClass(cls): - super(FlavorsAdminNegativeTestJSON, cls).setUpClass() - if not test.is_extension_enabled('FlavorExtraData', 'compute'): - msg = "FlavorExtraData extension not enabled." - raise cls.skipException(msg) + super(FlavorsAdminNegativeV3Test, cls).setUpClass() - cls.client = cls.os_adm.flavors_client - cls.user_client = cls.os.flavors_client + cls.client = cls.flavors_admin_client + cls.user_client = cls.flavors_client cls.flavor_name_prefix = 'test_flavor_' cls.ram = 512 cls.vcpus = 1 @@ -48,7 +45,7 @@ class FlavorsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest): def flavor_clean_up(self, flavor_id): resp, body = self.client.delete_flavor(flavor_id) - self.assertEqual(resp.status, 202) + self.assertEqual(resp.status, 204) self.client.wait_for_resource_deletion(flavor_id) @test.attr(type=['negative', 'gate']) @@ -69,8 +66,8 @@ class FlavorsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest): # Delete the flavor new_flavor_id = flavor['id'] resp_delete, body = self.client.delete_flavor(new_flavor_id) - self.assertEqual(200, resp.status) - self.assertEqual(202, resp_delete.status) + self.assertEqual(201, resp.status) + self.assertEqual(204, resp_delete.status) # Deleted flavors can be seen via detailed GET resp, flavor = self.client.get_flavor_details(new_flavor_id) @@ -316,7 +313,7 @@ class FlavorsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest): ephemeral=self.ephemeral, swap=self.swap, rxtx=self.rxtx) - self.assertEqual(200, resp.status) + self.assertEqual(201, resp.status) self.addCleanup(self.flavor_clean_up, flavor['id']) self.assertRaises(exceptions.Conflict, @@ -336,7 +333,3 @@ class FlavorsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest): self.assertRaises(exceptions.NotFound, self.client.delete_flavor, nonexistent_flavor_id) - - -class FlavorsAdminNegativeTestXML(FlavorsAdminNegativeTestJSON): - _interface = 'xml' diff --git a/tempest/api/compute/v3/flavors/test_flavors.py b/tempest/api/compute/v3/flavors/test_flavors.py index b0a7fed615..812358fc1e 100644 --- a/tempest/api/compute/v3/flavors/test_flavors.py +++ b/tempest/api/compute/v3/flavors/test_flavors.py @@ -14,18 +14,18 @@ # under the License. from tempest.api.compute import base -from tempest.test import attr +from tempest import test -class FlavorsTestJSON(base.BaseV2ComputeTest): +class FlavorsV3Test(base.BaseV3ComputeTest): _interface = 'json' @classmethod def setUpClass(cls): - super(FlavorsTestJSON, cls).setUpClass() + super(FlavorsV3Test, cls).setUpClass() cls.client = cls.flavors_client - @attr(type='smoke') + @test.attr(type='smoke') def test_list_flavors(self): # List of all flavors should contain the expected flavor resp, flavors = self.client.list_flavors() @@ -34,34 +34,34 @@ class FlavorsTestJSON(base.BaseV2ComputeTest): 'name': flavor['name']} self.assertIn(flavor_min_detail, flavors) - @attr(type='smoke') + @test.attr(type='smoke') def test_list_flavors_with_detail(self): # Detailed list of all flavors should contain the expected flavor resp, flavors = self.client.list_flavors_with_detail() resp, flavor = self.client.get_flavor_details(self.flavor_ref) self.assertIn(flavor, flavors) - @attr(type='smoke') + @test.attr(type='smoke') def test_get_flavor(self): # The expected flavor details should be returned resp, flavor = self.client.get_flavor_details(self.flavor_ref) self.assertEqual(self.flavor_ref, flavor['id']) - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_limit_results(self): # Only the expected number of flavors should be returned params = {'limit': 1} resp, flavors = self.client.list_flavors(params) self.assertEqual(1, len(flavors)) - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_detailed_limit_results(self): # Only the expected number of flavors (detailed) should be returned params = {'limit': 1} resp, flavors = self.client.list_flavors_with_detail(params) self.assertEqual(1, len(flavors)) - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_using_marker(self): # The list of flavors should start from the provided marker resp, flavors = self.client.list_flavors() @@ -72,7 +72,7 @@ class FlavorsTestJSON(base.BaseV2ComputeTest): self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]), 'The list of flavors did not start after the marker.') - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_detailed_using_marker(self): # The list of flavors should start from the provided marker resp, flavors = self.client.list_flavors_with_detail() @@ -83,50 +83,46 @@ class FlavorsTestJSON(base.BaseV2ComputeTest): self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]), 'The list of flavors did not start after the marker.') - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_detailed_filter_by_min_disk(self): # The detailed list of flavors should be filtered by disk space resp, flavors = self.client.list_flavors_with_detail() flavors = sorted(flavors, key=lambda k: k['disk']) flavor_id = flavors[0]['id'] - params = {'minDisk': flavors[0]['disk'] + 1} + params = {'min_disk': flavors[0]['disk'] + 1} resp, flavors = self.client.list_flavors_with_detail(params) self.assertFalse(any([i for i in flavors if i['id'] == flavor_id])) - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_detailed_filter_by_min_ram(self): # The detailed list of flavors should be filtered by RAM resp, flavors = self.client.list_flavors_with_detail() flavors = sorted(flavors, key=lambda k: k['ram']) flavor_id = flavors[0]['id'] - params = {'minRam': flavors[0]['ram'] + 1} + params = {'min_ram': flavors[0]['ram'] + 1} resp, flavors = self.client.list_flavors_with_detail(params) self.assertFalse(any([i for i in flavors if i['id'] == flavor_id])) - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_filter_by_min_disk(self): # The list of flavors should be filtered by disk space resp, flavors = self.client.list_flavors_with_detail() flavors = sorted(flavors, key=lambda k: k['disk']) flavor_id = flavors[0]['id'] - params = {'minDisk': flavors[0]['disk'] + 1} + params = {'min_disk': flavors[0]['disk'] + 1} resp, flavors = self.client.list_flavors(params) self.assertFalse(any([i for i in flavors if i['id'] == flavor_id])) - @attr(type='gate') + @test.attr(type='gate') def test_list_flavors_filter_by_min_ram(self): # The list of flavors should be filtered by RAM resp, flavors = self.client.list_flavors_with_detail() flavors = sorted(flavors, key=lambda k: k['ram']) flavor_id = flavors[0]['id'] - params = {'minRam': flavors[0]['ram'] + 1} + params = {'min_ram': flavors[0]['ram'] + 1} resp, flavors = self.client.list_flavors(params) self.assertFalse(any([i for i in flavors if i['id'] == flavor_id])) - - -class FlavorsTestXML(FlavorsTestJSON): - _interface = 'xml' diff --git a/tempest/api/compute/v3/flavors/test_flavors_negative.py b/tempest/api/compute/v3/flavors/test_flavors_negative.py index 8ac61827a1..3d4100ac25 100644 --- a/tempest/api/compute/v3/flavors/test_flavors_negative.py +++ b/tempest/api/compute/v3/flavors/test_flavors_negative.py @@ -22,11 +22,11 @@ from tempest import test load_tests = testscenarios.load_tests_apply_scenarios -class FlavorsListNegativeTestJSON(base.BaseV2ComputeTest, - test.NegativeAutoTest): +class FlavorsListNegativeV3Test(base.BaseV3ComputeTest, + test.NegativeAutoTest): _interface = 'json' - _service = 'compute' - _schema_file = 'compute/flavors/flavors_list.json' + _service = 'computev3' + _schema_file = 'compute/flavors/flavors_list_v3.json' scenarios = test.NegativeAutoTest.generate_scenario(_schema_file) @@ -35,17 +35,17 @@ class FlavorsListNegativeTestJSON(base.BaseV2ComputeTest, self.execute(self._schema_file) -class FlavorDetailsNegativeTestJSON(base.BaseV2ComputeTest, - test.NegativeAutoTest): +class FlavorDetailsNegativeV3Test(base.BaseV3ComputeTest, + test.NegativeAutoTest): _interface = 'json' - _service = 'compute' - _schema_file = 'compute/flavors/flavor_details.json' + _service = 'computev3' + _schema_file = 'compute/flavors/flavor_details_v3.json' scenarios = test.NegativeAutoTest.generate_scenario(_schema_file) @classmethod def setUpClass(cls): - super(FlavorDetailsNegativeTestJSON, cls).setUpClass() + super(FlavorDetailsNegativeV3Test, cls).setUpClass() cls.set_resource("flavor", cls.flavor_ref) @test.attr(type=['negative', 'gate']) diff --git a/tempest/api/compute/v3/servers/test_server_password.py b/tempest/api/compute/v3/servers/test_server_password.py index 06697a5e29..579a8a5cc1 100644 --- a/tempest/api/compute/v3/servers/test_server_password.py +++ b/tempest/api/compute/v3/servers/test_server_password.py @@ -15,28 +15,24 @@ from tempest.api.compute import base -from tempest.test import attr +from tempest import test -class ServerPasswordTestJSON(base.BaseV2ComputeTest): +class ServerPasswordV3Test(base.BaseV3ComputeTest): _interface = 'json' @classmethod def setUpClass(cls): - super(ServerPasswordTestJSON, cls).setUpClass() + super(ServerPasswordV3Test, cls).setUpClass() cls.client = cls.servers_client resp, cls.server = cls.create_test_server(wait_until="ACTIVE") - @attr(type='gate') + @test.attr(type='gate') def test_get_server_password(self): resp, body = self.client.get_password(self.server['id']) self.assertEqual(200, resp.status) - @attr(type='gate') + @test.attr(type='gate') def test_delete_server_password(self): resp, body = self.client.delete_password(self.server['id']) self.assertEqual(204, resp.status) - - -class ServerPasswordTestXML(ServerPasswordTestJSON): - _interface = 'xml' diff --git a/tempest/services/compute/v3/json/servers_client.py b/tempest/services/compute/v3/json/servers_client.py index 11538f5239..56459d4c42 100644 --- a/tempest/services/compute/v3/json/servers_client.py +++ b/tempest/services/compute/v3/json/servers_client.py @@ -216,6 +216,21 @@ class ServersV3ClientJSON(RestClient): return self.action(server_id, 'change_password', None, admin_password=admin_password) + def get_password(self, server_id): + resp, body = self.get("servers/%s/os-server-password" % + str(server_id)) + body = json.loads(body) + return resp, body + + def delete_password(self, server_id): + """ + Removes the encrypted server password from the metadata server + Note that this does not actually change the instance server + password. + """ + return self.delete("servers/%s/os-server-password" % + str(server_id)) + def reboot(self, server_id, reboot_type): """Reboots a server.""" return self.action(server_id, 'reboot', None, type=reboot_type)