Merge "Fix three accidentally formatted paragraphs"
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
new file mode 100644
index 0000000..5ed4823
--- /dev/null
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -0,0 +1,96 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 NTT Data
+# 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.
+
+import testtools
+
+from tempest.api.compute import base
+from tempest.common.utils import data_utils
+from tempest import config
+from tempest.test import attr
+
+
+class SecurityGroupsTestAdminJSON(base.BaseV2ComputeAdminTest):
+ _interface = 'json'
+
+ @classmethod
+ def setUpClass(cls):
+ super(SecurityGroupsTestAdminJSON, cls).setUpClass()
+ cls.adm_client = cls.os_adm.security_groups_client
+ cls.client = cls.security_groups_client
+
+ def _delete_security_group(self, securitygroup_id, admin=True):
+ if admin:
+ resp, _ = self.adm_client.delete_security_group(securitygroup_id)
+ else:
+ resp, _ = self.client.delete_security_group(securitygroup_id)
+
+ self.assertEqual(202, resp.status)
+
+ @testtools.skipIf(config.TempestConfig().service_available.neutron,
+ "Skipped because neutron do not support all_tenants"
+ "search filter.")
+ @attr(type='smoke')
+ def test_list_security_groups_list_all_tenants_filter(self):
+ # Admin can list security groups of all tenants
+ # List of all security groups created
+ security_group_list = []
+ # Create two security groups for a non-admin tenant
+ for i in range(2):
+ name = data_utils.rand_name('securitygroup-')
+ description = data_utils.rand_name('description-')
+ resp, securitygroup = (self.client
+ .create_security_group(name, description))
+ self.assertEqual(200, resp.status)
+ self.addCleanup(self._delete_security_group,
+ securitygroup['id'], admin=False)
+ security_group_list.append(securitygroup)
+
+ client_tenant_id = securitygroup['tenant_id']
+ # Create two security groups for admin tenant
+ for i in range(2):
+ name = data_utils.rand_name('securitygroup-')
+ description = data_utils.rand_name('description-')
+ resp, adm_securitygroup = (self.adm_client
+ .create_security_group(name,
+ description))
+ self.assertEqual(200, resp.status)
+ self.addCleanup(self._delete_security_group,
+ adm_securitygroup['id'])
+ security_group_list.append(adm_securitygroup)
+
+ # Fetch all security groups based on 'all_tenants' search filter
+ param = {'all_tenants': 'true'}
+ resp, fetched_list = self.adm_client.list_security_groups(params=param)
+ self.assertEqual(200, resp.status)
+ sec_group_id_list = map(lambda sg: sg['id'], fetched_list)
+ # Now check if all created Security Groups are present in fetched list
+ for sec_group in security_group_list:
+ self.assertIn(sec_group['id'], sec_group_id_list)
+
+ # Fetch all security groups for non-admin user with 'all_tenants'
+ # search filter
+ resp, fetched_list = self.client.list_security_groups(params=param)
+ self.assertEqual(200, resp.status)
+ # Now check if all created Security Groups are present in fetched list
+ for sec_group in fetched_list:
+ self.assertEqual(sec_group['tenant_id'], client_tenant_id,
+ "Failed to get all security groups for "
+ "non admin user.")
+
+
+class SecurityGroupsTestAdminXML(SecurityGroupsTestAdminJSON):
+ _interface = 'xml'
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index b0ff7ab..6e4c8cb 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -117,6 +117,20 @@
self.assertEqual('204', resp['status'])
self.client.wait_for_resource_deletion(image_id)
+ @attr(type=['gate'])
+ def test_create_image_specify_multibyte_character_image_name(self):
+ if self.__class__._interface == "xml":
+ # NOTE(sdague): not entirely accurage, but we'd need a ton of work
+ # in our XML client to make this good
+ raise self.skipException("Not testable in XML")
+ # prefix character is:
+ # http://www.fileformat.info/info/unicode/char/1F4A9/index.htm
+ utf8_name = data_utils.rand_name(u'\xF0\x9F\x92\xA9')
+ resp, body = self.client.create_image(self.server_id, utf8_name)
+ image_id = data_utils.parse_image_id(resp['location'])
+ self.addCleanup(self.client.delete_image, image_id)
+ self.assertEqual('202', resp['status'])
+
class ImagesOneServerTestXML(ImagesOneServerTestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 2d27b81..b8a4304 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -86,11 +86,15 @@
@skip_because(bug="1006725")
@attr(type=['negative', 'gate'])
def test_create_image_specify_multibyte_character_image_name(self):
- # Return an error if the image name has multi-byte characters
- snapshot_name = data_utils.rand_name('\xef\xbb\xbf')
+ if self.__class__._interface == "xml":
+ raise self.skipException("Not testable in XML")
+ # invalid multibyte sequence from:
+ # http://stackoverflow.com/questions/1301402/
+ # example-invalid-utf8-string
+ invalid_name = data_utils.rand_name(u'\xc3\x28')
self.assertRaises(exceptions.BadRequest,
self.client.create_image, self.server_id,
- snapshot_name)
+ invalid_name)
@attr(type=['negative', 'gate'])
def test_create_image_specify_invalid_metadata(self):
diff --git a/tempest/api/compute/keypairs/test_keypairs.py b/tempest/api/compute/keypairs/test_keypairs.py
index 50b6c77..b36595c 100644
--- a/tempest/api/compute/keypairs/test_keypairs.py
+++ b/tempest/api/compute/keypairs/test_keypairs.py
@@ -17,7 +17,7 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
-from tempest.test import attr
+from tempest import test
class KeyPairsTestJSON(base.BaseV2ComputeTest):
@@ -28,14 +28,23 @@
super(KeyPairsTestJSON, cls).setUpClass()
cls.client = cls.keypairs_client
- @attr(type='gate')
+ def _delete_keypair(self, keypair_name):
+ resp, _ = self.client.delete_keypair(keypair_name)
+ self.assertEqual(202, resp.status)
+
+ def _create_keypair(self, keypair_name, pub_key=None):
+ resp, body = self.client.create_keypair(keypair_name, pub_key)
+ self.addCleanup(self._delete_keypair, keypair_name)
+ return resp, body
+
+ @test.attr(type='gate')
def test_keypairs_create_list_delete(self):
# Keypairs created should be available in the response list
# Create 3 keypairs
key_list = list()
for i in range(3):
k_name = data_utils.rand_name('keypair-')
- resp, keypair = self.client.create_keypair(k_name)
+ resp, keypair = self._create_keypair(k_name)
# Need to pop these keys so that our compare doesn't fail later,
# as the keypair dicts from list API doesn't have them.
keypair.pop('private_key')
@@ -57,16 +66,12 @@
self.assertFalse(missing_kps,
"Failed to find keypairs %s in fetched list"
% ', '.join(m_key['name'] for m_key in missing_kps))
- # Delete all the keypairs created
- for keypair in key_list:
- resp, _ = self.client.delete_keypair(keypair['name'])
- self.assertEqual(202, resp.status)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_keypair_create_delete(self):
# Keypair should be created, verified and deleted
k_name = data_utils.rand_name('keypair-')
- resp, keypair = self.client.create_keypair(k_name)
+ resp, keypair = self._create_keypair(k_name)
self.assertEqual(200, resp.status)
private_key = keypair['private_key']
key_name = keypair['name']
@@ -75,15 +80,12 @@
"to the requested name")
self.assertTrue(private_key is not None,
"Field private_key is empty or not found.")
- resp, _ = self.client.delete_keypair(k_name)
- self.assertEqual(202, resp.status)
- @attr(type='gate')
+ @test.attr(type='gate')
def test_get_keypair_detail(self):
# Keypair should be created, Got details by name and deleted
k_name = data_utils.rand_name('keypair-')
- resp, keypair = self.client.create_keypair(k_name)
- self.addCleanup(self.client.delete_keypair, k_name)
+ resp, keypair = self._create_keypair(k_name)
resp, keypair_detail = self.client.get_keypair(k_name)
self.assertEqual(200, resp.status)
self.assertIn('name', keypair_detail)
@@ -95,7 +97,7 @@
self.assertTrue(public_key is not None,
"Field public_key is empty or not found.")
- @attr(type='gate')
+ @test.attr(type='gate')
def test_keypair_create_with_pub_key(self):
# Keypair should be created with a given public key
k_name = data_utils.rand_name('keypair-')
@@ -108,7 +110,7 @@
"LOeB1kYMOBaiUPLQTWXR3JpckqFIQwhIH0zoHlJvZE8hh90"
"XcPojYN56tI0OlrGqojbediJYD0rUsJu4weZpbn8vilb3JuDY+jws"
"snSA8wzBx3A/8y9Pp1B nova@ubuntu")
- resp, keypair = self.client.create_keypair(k_name, pub_key)
+ resp, keypair = self._create_keypair(k_name, pub_key)
self.assertEqual(200, resp.status)
self.assertFalse('private_key' in keypair,
"Field private_key is not empty!")
@@ -116,8 +118,6 @@
self.assertEqual(key_name, k_name,
"The created keypair name is not equal "
"to the requested name!")
- resp, _ = self.client.delete_keypair(k_name)
- self.assertEqual(202, resp.status)
class KeyPairsTestXML(KeyPairsTestJSON):
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
index fad985e..621487c 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -19,7 +19,7 @@
from tempest.api.compute import base
from tempest.common.utils import data_utils
from tempest import exceptions
-from tempest.test import attr
+from tempest import test
class KeyPairsNegativeTestJSON(base.BaseV2ComputeTest):
@@ -30,67 +30,71 @@
super(KeyPairsNegativeTestJSON, cls).setUpClass()
cls.client = cls.keypairs_client
- @attr(type=['negative', 'gate'])
+ def _create_keypair(self, keypair_name, pub_key=None):
+ self.client.create_keypair(keypair_name, pub_key)
+ self.addCleanup(self.client.delete_keypair, keypair_name)
+
+ @test.attr(type=['negative', 'gate'])
def test_keypair_create_with_invalid_pub_key(self):
# Keypair should not be created with a non RSA public key
k_name = data_utils.rand_name('keypair-')
pub_key = "ssh-rsa JUNK nova@ubuntu"
self.assertRaises(exceptions.BadRequest,
- self.client.create_keypair, k_name, pub_key)
+ self._create_keypair, k_name, pub_key)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_keypair_delete_nonexistant_key(self):
# Non-existant key deletion should throw a proper error
k_name = data_utils.rand_name("keypair-non-existant-")
self.assertRaises(exceptions.NotFound, self.client.delete_keypair,
k_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_keypair_with_empty_public_key(self):
# Keypair should not be created with an empty public key
k_name = data_utils.rand_name("keypair-")
pub_key = ' '
- self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+ self.assertRaises(exceptions.BadRequest, self._create_keypair,
k_name, pub_key)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
# Keypair should not be created when public key bits are too long
k_name = data_utils.rand_name("keypair-")
pub_key = 'ssh-rsa ' + 'A' * 2048 + ' openstack@ubuntu'
- self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+ self.assertRaises(exceptions.BadRequest, self._create_keypair,
k_name, pub_key)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_keypair_with_duplicate_name(self):
# Keypairs with duplicate names should not be created
k_name = data_utils.rand_name('keypair-')
resp, _ = self.client.create_keypair(k_name)
self.assertEqual(200, resp.status)
# Now try the same keyname to create another key
- self.assertRaises(exceptions.Conflict, self.client.create_keypair,
+ self.assertRaises(exceptions.Conflict, self._create_keypair,
k_name)
resp, _ = self.client.delete_keypair(k_name)
self.assertEqual(202, resp.status)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_keypair_with_empty_name_string(self):
# Keypairs with name being an empty string should not be created
- self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+ self.assertRaises(exceptions.BadRequest, self._create_keypair,
'')
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_keypair_with_long_keynames(self):
# Keypairs with name longer than 255 chars should not be created
k_name = 'keypair-'.ljust(260, '0')
- self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+ self.assertRaises(exceptions.BadRequest, self._create_keypair,
k_name)
- @attr(type=['negative', 'gate'])
+ @test.attr(type=['negative', 'gate'])
def test_create_keypair_invalid_name(self):
# Keypairs with name being an invalid name should not be created
k_name = 'key_/.\@:'
- self.assertRaises(exceptions.BadRequest, self.client.create_keypair,
+ self.assertRaises(exceptions.BadRequest, self._create_keypair,
k_name)
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 0d0e794..e64a257 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -89,3 +89,7 @@
# usually to /dev/ttyS0
cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message
return self.ssh_client.exec_command(cmd)
+
+ def ping_host(self, host):
+ cmd = 'ping -c1 -w1 %s' % host
+ return self.ssh_client.exec_command(cmd)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index e839d20..b24d2b9 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -853,6 +853,12 @@
return rules
+ def _ssh_to_server(self, server, private_key):
+ ssh_login = self.config.compute.image_ssh_user
+ return self.get_remote_client(server,
+ username=ssh_login,
+ private_key=private_key)
+
def _show_quota_network(self, tenant_id):
quota = self.network_client.show_quota(tenant_id)
return quota['quota']['network']