Merge "Split out Neutron ports client"
diff --git a/requirements.txt b/requirements.txt
index c0a9254..59d6856 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,11 +13,11 @@
testrepository>=0.0.18
pyOpenSSL>=0.14
oslo.concurrency>=2.3.0 # Apache-2.0
-oslo.config>=2.3.0 # Apache-2.0
+oslo.config>=2.6.0 # Apache-2.0
oslo.i18n>=1.5.0 # Apache-2.0
oslo.log>=1.8.0 # Apache-2.0
-oslo.serialization>=1.4.0 # Apache-2.0
-oslo.utils>=2.0.0 # Apache-2.0
+oslo.serialization>=1.10.0 # Apache-2.0
+oslo.utils!=2.6.0,>=2.4.0 # Apache-2.0
six>=1.9.0
iso8601>=0.1.9
fixtures>=1.3.1
diff --git a/setup.cfg b/setup.cfg
index 46e21f1..ee61788 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -34,6 +34,7 @@
tempest = tempest.cmd.main:main
tempest.cm =
init = tempest.cmd.init:TempestInit
+ cleanup = tempest.cmd.cleanup:TempestCleanup
oslo.config.opts =
tempest.config = tempest.config:list_opts
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 12c471e..f186a7d 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -34,10 +34,6 @@
cls.admin_servers_client = cls.os_adm.servers_client
cls.admin_migration_client = cls.os_adm.migrations_client
- @classmethod
- def resource_setup(cls):
- super(LiveBlockMigrationTestJSON, cls).resource_setup()
-
def _get_compute_hostnames(self):
body = self.admin_hosts_client.list_hosts()['hosts']
return [
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index 742d737..15bea28 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -28,6 +28,11 @@
# or else it would result in unauthorized error
self.client.update_domain(domain_id, enabled=False)
self.client.delete_domain(domain_id)
+ # Asserting that the domain is not found in the list
+ # after deletion
+ body = self.client.list_domains()['domains']
+ domains_list = [d['id'] for d in body]
+ self.assertNotIn(domain_id, domains_list)
@test.idempotent_id('8cf516ef-2114-48f1-907b-d32726c734d4')
def test_list_domains(self):
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 156179c..33819a8 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -37,3 +37,10 @@
# domain need to be disabled before deleting
self.assertRaises(lib_exc.Forbidden, self.client.delete_domain,
domain_id)
+
+ @test.attr(type=['negative'])
+ @test.idempotent_id('9018461d-7d24-408d-b3fe-ae37e8cd5c9e')
+ def test_create_domain_with_empty_name(self):
+ # Domain name should not be empty
+ self.assertRaises(lib_exc.BadRequest, self.client.create_domain,
+ name='')
diff --git a/tempest/cmd/cleanup.py b/tempest/cmd/cleanup.py
old mode 100755
new mode 100644
index 7898035..4fa4302
--- a/tempest/cmd/cleanup.py
+++ b/tempest/cmd/cleanup.py
@@ -50,9 +50,9 @@
Please run with **--help** to see full list of options.
"""
-import argparse
import sys
+from cliff import command
from oslo_log import log as logging
from oslo_serialization import jsonutils as json
@@ -67,13 +67,17 @@
CONF = config.CONF
-class Cleanup(object):
+class TempestCleanup(command.Command):
- def __init__(self):
+ def __init__(self, app, cmd):
+ super(TempestCleanup, self).__init__(app, cmd)
+
+ def take_action(self, parsed_args):
+ cleanup_service.init_conf()
+ self.options = parsed_args
self.admin_mgr = clients.AdminManager()
self.dry_run_data = {}
self.json_data = {}
- self._init_options()
self.admin_id = ""
self.admin_role_id = ""
@@ -86,9 +90,7 @@
self.tenant_services = cleanup_service.get_tenant_cleanup_services()
self.global_services = cleanup_service.get_global_cleanup_services()
- def run(self):
- opts = self.options
- if opts.init_saved_state:
+ if parsed_args.init_saved_state:
self._init_state()
return
@@ -157,8 +159,8 @@
tenant_data = dry_run_data["_tenants_to_clean"][tenant_id] = {}
tenant_data['name'] = tenant_name
- kwargs = {"username": CONF.identity.admin_username,
- "password": CONF.identity.admin_password,
+ kwargs = {"username": CONF.auth.admin_username,
+ "password": CONF.auth.admin_password,
"tenant_name": tenant['name']}
mgr = clients.Manager(credentials=cred_provider.get_credentials(
**kwargs))
@@ -175,22 +177,21 @@
def _init_admin_ids(self):
id_cl = self.admin_mgr.identity_client
- tenant = id_cl.get_tenant_by_name(CONF.identity.admin_tenant_name)
+ tenant = id_cl.get_tenant_by_name(CONF.auth.admin_tenant_name)
self.admin_tenant_id = tenant['id']
user = id_cl.get_user_by_username(self.admin_tenant_id,
- CONF.identity.admin_username)
+ CONF.auth.admin_username)
self.admin_id = user['id']
- roles = id_cl.list_roles()
+ roles = id_cl.list_roles()['roles']
for role in roles:
if role['name'] == CONF.identity.admin_role:
self.admin_role_id = role['id']
break
- def _init_options(self):
- parser = argparse.ArgumentParser(
- description='Cleanup after tempest run')
+ def get_parser(self, prog_name):
+ parser = super(TempestCleanup, self).get_parser(prog_name)
parser.add_argument('--init-saved-state', action="store_true",
dest='init_saved_state', default=False,
help="Creates JSON file: " + SAVED_STATE_JSON +
@@ -211,13 +212,15 @@
help="Generate JSON file:" + DRY_RUN_JSON +
", that reports the objects that would have "
"been deleted had a full cleanup been run.")
+ return parser
- self.options = parser.parse_args()
+ def get_description(self):
+ return 'Cleanup after tempest run'
def _add_admin(self, tenant_id):
id_cl = self.admin_mgr.identity_client
needs_role = True
- roles = id_cl.list_user_roles(tenant_id, self.admin_id)
+ roles = id_cl.list_user_roles(tenant_id, self.admin_id)['roles']
for role in roles:
if role['id'] == self.admin_role_id:
needs_role = False
@@ -282,14 +285,3 @@
except Exception as ex:
LOG.exception("Exception parsing saved state json : %s" % ex)
sys.exit(ex)
-
-
-def main():
- cleanup_service.init_conf()
- cleanup = Cleanup()
- cleanup.run()
- LOG.info('Cleanup finished!')
- return 0
-
-if __name__ == "__main__":
- sys.exit(main())
diff --git a/tempest/cmd/cleanup_service.py b/tempest/cmd/cleanup_service.py
index 1ef6f81..76eb051 100644
--- a/tempest/cmd/cleanup_service.py
+++ b/tempest/cmd/cleanup_service.py
@@ -69,10 +69,10 @@
CONF_PRIV_NETWORK_NAME = CONF.compute.fixed_network_name
CONF_PUB_NETWORK = CONF.network.public_network_id
CONF_PUB_ROUTER = CONF.network.public_router_id
- CONF_TENANTS = [CONF.identity.admin_tenant_name,
+ CONF_TENANTS = [CONF.auth.admin_tenant_name,
CONF.identity.tenant_name,
CONF.identity.alt_tenant_name]
- CONF_USERS = [CONF.identity.admin_username, CONF.identity.username,
+ CONF_USERS = [CONF.auth.admin_username, CONF.identity.username,
CONF.identity.alt_username]
if IS_NEUTRON:
@@ -147,7 +147,7 @@
def list(self):
client = self.client
- snaps = client.list_snapshots()
+ snaps = client.list_snapshots()['snapshots']
LOG.debug("List count, %s Snapshots" % len(snaps))
return snaps
@@ -169,6 +169,7 @@
def __init__(self, manager, **kwargs):
super(ServerService, self).__init__(kwargs)
self.client = manager.servers_client
+ self.server_groups_client = manager.server_groups_client
def list(self):
client = self.client
@@ -194,7 +195,7 @@
class ServerGroupService(ServerService):
def list(self):
- client = self.client
+ client = self.server_groups_client
sgs = client.list_server_groups()['server_groups']
LOG.debug("List count, %s Server Groups" % len(sgs))
return sgs
@@ -813,7 +814,7 @@
def list(self):
client = self.client
- users = client.get_users()
+ users = client.get_users()['users']
if not self.is_save_state:
users = [user for user in users if user['id']
@@ -825,7 +826,7 @@
elif not self.is_save_state: # Never delete admin user
users = [user for user in users if user['name'] !=
- CONF.identity.admin_username]
+ CONF.auth.admin_username]
LOG.debug("List count, %s Users after reconcile" % len(users))
return users
@@ -855,7 +856,7 @@
def list(self):
client = self.client
try:
- roles = client.list_roles()
+ roles = client.list_roles()['roles']
# reconcile roles with saved state and never list admin role
if not self.is_save_state:
roles = [role for role in roles if
@@ -896,7 +897,7 @@
if not self.is_save_state:
tenants = [tenant for tenant in tenants if (tenant['id']
not in self.saved_state_json['tenants'].keys()
- and tenant['name'] != CONF.identity.admin_tenant_name)]
+ and tenant['name'] != CONF.auth.admin_tenant_name)]
if self.is_preserve:
tenants = [tenant for tenant in tenants if tenant['name']
diff --git a/tempest/cmd/init.py b/tempest/cmd/init.py
index af8f270..a4ed064 100644
--- a/tempest/cmd/init.py
+++ b/tempest/cmd/init.py
@@ -116,9 +116,9 @@
if not os.path.isdir(local_dir):
LOG.debug('Creating local working dir: %s' % local_dir)
os.mkdir(local_dir)
- else:
+ elif not os.listdir(local_dir) == []:
raise OSError("Directory you are trying to initialize already "
- "exists: %s" % local_dir)
+ "exists and is not empty: %s" % local_dir)
lock_dir = os.path.join(local_dir, 'tempest_lock')
etc_dir = os.path.join(local_dir, 'etc')
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 859e3a7..6548d28 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -758,6 +758,8 @@
for fxip in p["fixed_ips"]
if netaddr.valid_ipv4(fxip["ip_address"])]
+ self.assertNotEqual(0, len(port_map),
+ "No IPv4 addresses found in: %s" % ports)
self.assertEqual(len(port_map), 1,
"Found multiple IPv4 addresses: %s. "
"Unable to determine which port to target."
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 3df92cf..f82e7e4 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -188,21 +188,15 @@
self._check_connectivity(sshv4_1, ips_from_api_2['4'])
self._check_connectivity(sshv4_2, ips_from_api_1['4'])
- # Some VM (like cirros) may not have ping6 utility
- result = sshv4_1.exec_command('whereis ping6')
- is_ping6 = False if result == 'ping6:\n' else True
- if is_ping6:
- for i in range(n_subnets6):
- self._check_connectivity(sshv4_1,
- ips_from_api_2['6'][i])
- self._check_connectivity(sshv4_1,
- self.subnets_v6[i].gateway_ip)
- self._check_connectivity(sshv4_2,
- ips_from_api_1['6'][i])
- self._check_connectivity(sshv4_2,
- self.subnets_v6[i].gateway_ip)
- else:
- LOG.warning('Ping6 is not available, skipping')
+ for i in range(n_subnets6):
+ self._check_connectivity(sshv4_1,
+ ips_from_api_2['6'][i])
+ self._check_connectivity(sshv4_1,
+ self.subnets_v6[i].gateway_ip)
+ self._check_connectivity(sshv4_2,
+ ips_from_api_1['6'][i])
+ self._check_connectivity(sshv4_2,
+ self.subnets_v6[i].gateway_ip)
def _check_connectivity(self, source, dest):
self.assertTrue(
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index d4bddc0..414305d 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -11,7 +11,6 @@
# under the License.
from oslo_log import log
-from tempest_lib import decorators
from tempest.common.utils import data_utils
from tempest.common import waiters
@@ -96,32 +95,17 @@
vol_name = data_utils.rand_name('volume')
return self.create_volume(name=vol_name, snapshot_id=snap_id)
- def _ssh_to_server(self, server, keypair):
+ def _get_server_ip(self, server):
if CONF.compute.use_floatingip_for_ssh:
ip = self.create_floating_ip(server)['ip']
else:
ip = server
-
- return self.get_remote_client(ip, private_key=keypair['private_key'],
- log_console_of_servers=[server])
-
- def _get_content(self, ssh_client):
- return ssh_client.exec_command('cat /tmp/text')
-
- def _write_text(self, ssh_client):
- text = data_utils.rand_name('text')
- ssh_client.exec_command('echo "%s" > /tmp/text; sync' % (text))
-
- return self._get_content(ssh_client)
+ return ip
def _delete_server(self, server):
self.servers_client.delete_server(server['id'])
waiters.wait_for_server_termination(self.servers_client, server['id'])
- def _check_content_of_written_file(self, ssh_client, expected):
- actual = self._get_content(ssh_client)
- self.assertEqual(expected, actual)
-
@test.idempotent_id('557cd2c2-4eb8-4dce-98be-f86765ff311b')
@test.attr(type='smoke')
@test.services('compute', 'volume', 'image')
@@ -135,9 +119,9 @@
keypair, security_group)
# write content to volume on instance
- ssh_client_for_instance_1st = self._ssh_to_server(instance_1st,
- keypair)
- text = self._write_text(ssh_client_for_instance_1st)
+ ip_instance_1st = self._get_server_ip(instance_1st)
+ timestamp = self.create_timestamp(ip_instance_1st,
+ private_key=keypair['private_key'])
# delete instance
self._delete_server(instance_1st)
@@ -147,9 +131,10 @@
keypair, security_group)
# check the content of written file
- ssh_client_for_instance_2nd = self._ssh_to_server(instance_2nd,
- keypair)
- self._check_content_of_written_file(ssh_client_for_instance_2nd, text)
+ ip_instance_2nd = self._get_server_ip(instance_2nd)
+ timestamp2 = self.get_timestamp(ip_instance_2nd,
+ private_key=keypair['private_key'])
+ self.assertEqual(timestamp, timestamp2)
# snapshot a volume
snapshot = self._create_snapshot_from_volume(volume_origin['id'])
@@ -161,10 +146,11 @@
keypair, security_group))
# check the content of written file
- ssh_client = self._ssh_to_server(instance_from_snapshot, keypair)
- self._check_content_of_written_file(ssh_client, text)
+ ip_instance_from_snapshot = self._get_server_ip(instance_from_snapshot)
+ timestamp3 = self.get_timestamp(ip_instance_from_snapshot,
+ private_key=keypair['private_key'])
+ self.assertEqual(timestamp, timestamp3)
- @decorators.skip_because(bug='1489581')
@test.idempotent_id('36c34c67-7b54-4b59-b188-02a2f458a63b')
@test.services('compute', 'volume', 'image')
def test_create_ebs_image_and_check_boot(self):
diff --git a/tempest/services/identity/v2/json/identity_client.py b/tempest/services/identity/v2/json/identity_client.py
index f37bc08..2d71359 100644
--- a/tempest/services/identity/v2/json/identity_client.py
+++ b/tempest/services/identity/v2/json/identity_client.py
@@ -27,21 +27,6 @@
body = json.loads(body)
return service_client.ResponseBody(resp, body)
- def has_admin_extensions(self):
- """
- Returns True if the KSADM Admin Extensions are supported
- False otherwise
- """
- if hasattr(self, '_has_admin_extensions'):
- return self._has_admin_extensions
- # Try something that requires admin
- try:
- self.list_roles()
- self._has_admin_extensions = True
- except Exception:
- self._has_admin_extensions = False
- return self._has_admin_extensions
-
def create_role(self, name):
"""Create a role."""
post_body = {
diff --git a/tempest/tests/cmd/test_tempest_init.py b/tempest/tests/cmd/test_tempest_init.py
index 1d60c67..1048a52 100644
--- a/tempest/tests/cmd/test_tempest_init.py
+++ b/tempest/tests/cmd/test_tempest_init.py
@@ -58,9 +58,11 @@
self.assertTrue(os.path.isfile(local_sample_conf_file))
self.assertGreater(os.path.getsize(local_sample_conf_file), 0)
- def test_create_working_dir_with_existing_local_dir(self):
+ def test_create_working_dir_with_existing_local_dir_non_empty(self):
fake_local_dir = self.useFixture(fixtures.TempDir())
fake_local_conf_dir = self.useFixture(fixtures.TempDir())
+ open("%s/foo" % fake_local_dir.path, 'w').close()
+
_init = init.TempestInit(None, None)
self.assertRaises(OSError,
_init.create_working_dir,