Merge "Inherit V2 keypair API's tests from V3 tests"
diff --git a/requirements.txt b/requirements.txt
index 5e396c6..75a61e7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -15,7 +15,7 @@
python-heatclient>=0.2.3
python-ironicclient
python-saharaclient>=0.6.0
-python-swiftclient>=1.6
+python-swiftclient>=2.0.2
testresources>=0.2.4
keyring>=2.1
testrepository>=0.0.18
diff --git a/tempest/api/compute/admin/test_availability_zone.py b/tempest/api/compute/admin/test_availability_zone.py
index 3c06624..9555367 100644
--- a/tempest/api/compute/admin/test_availability_zone.py
+++ b/tempest/api/compute/admin/test_availability_zone.py
@@ -17,15 +17,15 @@
from tempest import test
-class AZAdminTestJSON(base.BaseV2ComputeAdminTest):
-
+class AZAdminV3Test(base.BaseComputeAdminTest):
"""
Tests Availability Zone API List
"""
+ _api_version = 3
@classmethod
def setUpClass(cls):
- super(AZAdminTestJSON, cls).setUpClass()
+ super(AZAdminV3Test, cls).setUpClass()
cls.client = cls.os_adm.availability_zone_client
@test.attr(type='gate')
@@ -44,5 +44,9 @@
self.assertTrue(len(availability_zone) > 0)
-class AZAdminTestXML(AZAdminTestJSON):
+class AZAdminV2TestJSON(AZAdminV3Test):
+ _api_version = 2
+
+
+class AZAdminV2TestXML(AZAdminV2TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/admin/test_quotas.py b/tempest/api/compute/admin/test_quotas.py
index 32e0478..d6d5592 100644
--- a/tempest/api/compute/admin/test_quotas.py
+++ b/tempest/api/compute/admin/test_quotas.py
@@ -28,8 +28,7 @@
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
- cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
- 'tenantId')
+ cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
cls.default_quota_set = set(('injected_file_content_bytes',
'metadata_items', 'injected_files',
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index 5b2b5fd..10c3243 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -33,8 +33,7 @@
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
- cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
- 'tenantId')
+ cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
@test.attr(type=['negative', 'gate'])
def test_update_quota_normal_user(self):
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index edeb2fc..44340c3 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -38,6 +38,8 @@
cls.set_network_resources()
super(BaseComputeTest, cls).setUpClass()
+ # TODO(andreaf) WE should care also for the alt_manager here
+ # but only once client lazy load in the manager is done
os = cls.get_client_manager()
cls.os = os
@@ -173,7 +175,6 @@
pass
except Exception:
LOG.exception('Exception raised deleting image %s' % image_id)
- pass
@classmethod
def clear_security_groups(cls):
@@ -188,7 +189,6 @@
LOG.info('Exception raised deleting security group %s',
sg['id'])
LOG.exception(exc)
- pass
@classmethod
def tearDownClass(cls):
@@ -320,7 +320,6 @@
cls.servers_client.wait_for_server_termination(server_id)
except Exception:
LOG.exception('Failed to delete server %s' % server_id)
- pass
resp, server = cls.create_test_server(wait_until='ACTIVE', **kwargs)
if cls._api_version == 2:
cls.password = server['adminPass']
@@ -342,68 +341,51 @@
_interface = "json"
-class BaseV2ComputeAdminTest(BaseV2ComputeTest):
- """Base test case class for Compute Admin V2 API tests."""
-
- @classmethod
- def setUpClass(cls):
- super(BaseV2ComputeAdminTest, cls).setUpClass()
- admin_username = CONF.compute_admin.username
- admin_password = CONF.compute_admin.password
- admin_tenant = CONF.compute_admin.tenant_name
- if not (admin_username and admin_password and admin_tenant):
- msg = ("Missing Compute Admin API credentials "
- "in configuration.")
- raise cls.skipException(msg)
- if (CONF.compute.allow_tenant_isolation or
- cls.force_tenant_isolation is True):
- creds = cls.isolated_creds.get_admin_creds()
- admin_username, admin_tenant_name, admin_password = creds
- cls.os_adm = clients.Manager(username=admin_username,
- password=admin_password,
- tenant_name=admin_tenant_name,
- interface=cls._interface)
- else:
- cls.os_adm = clients.ComputeAdminManager(interface=cls._interface)
-
-
class BaseV3ComputeTest(BaseComputeTest):
_api_version = 3
_interface = "json"
-class BaseV3ComputeAdminTest(BaseV3ComputeTest):
- """Base test case class for all Compute Admin API V3 tests."""
+class BaseComputeAdminTest(BaseComputeTest):
+ """Base test case class for Compute Admin API tests."""
+ _interface = "json"
@classmethod
def setUpClass(cls):
- super(BaseV3ComputeAdminTest, cls).setUpClass()
- admin_username = CONF.compute_admin.username
- admin_password = CONF.compute_admin.password
- admin_tenant = CONF.compute_admin.tenant_name
- if not (admin_username and admin_password and admin_tenant):
- msg = ("Missing Compute Admin API credentials "
- "in configuration.")
- raise cls.skipException(msg)
- if CONF.compute.allow_tenant_isolation:
+ super(BaseComputeAdminTest, cls).setUpClass()
+ if (CONF.compute.allow_tenant_isolation or
+ cls.force_tenant_isolation is True):
creds = cls.isolated_creds.get_admin_creds()
- admin_username, admin_tenant_name, admin_password = creds
- os_adm = clients.Manager(username=admin_username,
- password=admin_password,
- tenant_name=admin_tenant_name,
- interface=cls._interface)
+ cls.os_adm = clients.Manager(credentials=creds,
+ interface=cls._interface)
else:
- os_adm = clients.ComputeAdminManager(interface=cls._interface)
+ try:
+ cls.os_adm = clients.ComputeAdminManager(
+ interface=cls._interface)
+ except exceptions.InvalidCredentials:
+ msg = ("Missing Compute Admin API credentials "
+ "in configuration.")
+ raise cls.skipException(msg)
- cls.os_adm = os_adm
- cls.servers_admin_client = cls.os_adm.servers_v3_client
- cls.services_admin_client = cls.os_adm.services_v3_client
- cls.availability_zone_admin_client = \
- cls.os_adm.availability_zone_v3_client
- cls.hypervisor_admin_client = cls.os_adm.hypervisor_v3_client
- cls.flavors_admin_client = cls.os_adm.flavors_v3_client
- cls.aggregates_admin_client = cls.os_adm.aggregates_v3_client
- cls.hosts_admin_client = cls.os_adm.hosts_v3_client
- cls.quotas_admin_client = cls.os_adm.quotas_v3_client
- cls.agents_admin_client = cls.os_adm.agents_v3_client
- cls.migrations_admin_client = cls.os_adm.migrations_v3_client
+ if cls._api_version == 3:
+ cls.servers_admin_client = cls.os_adm.servers_v3_client
+ cls.services_admin_client = cls.os_adm.services_v3_client
+ cls.availability_zone_admin_client = \
+ cls.os_adm.availability_zone_v3_client
+ cls.hypervisor_admin_client = cls.os_adm.hypervisor_v3_client
+ cls.flavors_admin_client = cls.os_adm.flavors_v3_client
+ cls.aggregates_admin_client = cls.os_adm.aggregates_v3_client
+ cls.hosts_admin_client = cls.os_adm.hosts_v3_client
+ cls.quotas_admin_client = cls.os_adm.quotas_v3_client
+ cls.agents_admin_client = cls.os_adm.agents_v3_client
+ cls.migrations_admin_client = cls.os_adm.migrations_v3_client
+
+
+class BaseV2ComputeAdminTest(BaseComputeAdminTest):
+ """Base test case class for Compute Admin V2 API tests."""
+ _api_version = 2
+
+
+class BaseV3ComputeAdminTest(BaseComputeAdminTest):
+ """Base test case class for Compute Admin V3 API tests."""
+ _api_version = 3
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index 6e202f6..bfebb5e 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -17,11 +17,15 @@
from tempest import test
-class FlavorsTestJSON(base.BaseV2ComputeTest):
+class FlavorsV3Test(base.BaseComputeTest):
+
+ _api_version = 3
+ _min_disk = 'min_disk'
+ _min_ram = 'min_ram'
@classmethod
def setUpClass(cls):
- super(FlavorsTestJSON, cls).setUpClass()
+ super(FlavorsV3Test, cls).setUpClass()
cls.client = cls.flavors_client
@test.attr(type='smoke')
@@ -89,7 +93,7 @@
flavors = sorted(flavors, key=lambda k: k['disk'])
flavor_id = flavors[0]['id']
- params = {'minDisk': flavors[0]['disk'] + 1}
+ params = {self._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]))
@@ -100,7 +104,7 @@
flavors = sorted(flavors, key=lambda k: k['ram'])
flavor_id = flavors[0]['id']
- params = {'minRam': flavors[0]['ram'] + 1}
+ params = {self._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]))
@@ -111,7 +115,7 @@
flavors = sorted(flavors, key=lambda k: k['disk'])
flavor_id = flavors[0]['id']
- params = {'minDisk': flavors[0]['disk'] + 1}
+ params = {self._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]))
@@ -122,10 +126,17 @@
flavors = sorted(flavors, key=lambda k: k['ram'])
flavor_id = flavors[0]['id']
- params = {'minRam': flavors[0]['ram'] + 1}
+ params = {self._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):
+class FlavorsV2TestJSON(FlavorsV3Test):
+
+ _api_version = 2
+ _min_disk = 'minDisk'
+ _min_ram = 'minRam'
+
+
+class FlavorsV2TestXML(FlavorsV2TestJSON):
_interface = 'xml'
diff --git a/tempest/api/compute/test_authorization.py b/tempest/api/compute/test_authorization.py
index c87f24e..375ddf8 100644
--- a/tempest/api/compute/test_authorization.py
+++ b/tempest/api/compute/test_authorization.py
@@ -43,10 +43,7 @@
if CONF.compute.allow_tenant_isolation:
creds = cls.isolated_creds.get_alt_creds()
- username, tenant_name, password = creds
- cls.alt_manager = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name)
+ cls.alt_manager = clients.Manager(credentials=creds)
else:
# Use the alt_XXX credentials in the config file
cls.alt_manager = clients.AltManager()
diff --git a/tempest/api/compute/v3/admin/test_availability_zone.py b/tempest/api/compute/v3/admin/test_availability_zone.py
deleted file mode 100644
index 9ca8953..0000000
--- a/tempest/api/compute/v3/admin/test_availability_zone.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2013 NEC Corporation
-# 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.compute import base
-from tempest.test import attr
-
-
-class AZAdminV3Test(base.BaseV3ComputeAdminTest):
-
- """
- Tests Availability Zone API List
- """
-
- @classmethod
- def setUpClass(cls):
- super(AZAdminV3Test, cls).setUpClass()
- cls.client = cls.availability_zone_admin_client
-
- @attr(type='gate')
- def test_get_availability_zone_list(self):
- # List of availability zone
- resp, availability_zone = self.client.get_availability_zone_list()
- self.assertEqual(200, resp.status)
- self.assertTrue(len(availability_zone) > 0)
-
- @attr(type='gate')
- def test_get_availability_zone_list_detail(self):
- # List of availability zones and available services
- resp, availability_zone = \
- self.client.get_availability_zone_list_detail()
- self.assertEqual(200, resp.status)
- self.assertTrue(len(availability_zone) > 0)
diff --git a/tempest/api/compute/v3/admin/test_quotas.py b/tempest/api/compute/v3/admin/test_quotas.py
index b70e254..27836fb 100644
--- a/tempest/api/compute/v3/admin/test_quotas.py
+++ b/tempest/api/compute/v3/admin/test_quotas.py
@@ -32,8 +32,7 @@
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
- cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
- 'tenantId')
+ cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
cls.default_quota_set = set(('metadata_items',
'ram', 'floating_ips',
diff --git a/tempest/api/compute/v3/admin/test_quotas_negative.py b/tempest/api/compute/v3/admin/test_quotas_negative.py
index d138e80..307462f 100644
--- a/tempest/api/compute/v3/admin/test_quotas_negative.py
+++ b/tempest/api/compute/v3/admin/test_quotas_negative.py
@@ -30,8 +30,7 @@
# NOTE(afazekas): these test cases should always create and use a new
# tenant most of them should be skipped if we can't do that
- cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
- 'tenantId')
+ cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
# TODO(afazekas): Add dedicated tenant to the skiped quota tests
# it can be moved into the setUpClass as well
diff --git a/tempest/api/compute/v3/flavors/test_flavors.py b/tempest/api/compute/v3/flavors/test_flavors.py
deleted file mode 100644
index a0bbba6..0000000
--- a/tempest/api/compute/v3/flavors/test_flavors.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright 2012 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.compute import base
-from tempest import test
-
-
-class FlavorsV3Test(base.BaseV3ComputeTest):
-
- @classmethod
- def setUpClass(cls):
- super(FlavorsV3Test, cls).setUpClass()
- cls.client = cls.flavors_client
-
- @test.attr(type='smoke')
- def test_list_flavors(self):
- # List of all flavors should contain the expected flavor
- resp, flavors = self.client.list_flavors()
- resp, flavor = self.client.get_flavor_details(self.flavor_ref)
- flavor_min_detail = {'id': flavor['id'], 'links': flavor['links'],
- 'name': flavor['name']}
- self.assertIn(flavor_min_detail, flavors)
-
- @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)
-
- @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'])
-
- @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))
-
- @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))
-
- @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()
- flavor_id = flavors[0]['id']
-
- params = {'marker': flavor_id}
- resp, flavors = self.client.list_flavors(params)
- self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
- 'The list of flavors did not start after the marker.')
-
- @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()
- flavor_id = flavors[0]['id']
-
- params = {'marker': flavor_id}
- resp, flavors = self.client.list_flavors_with_detail(params)
- self.assertFalse(any([i for i in flavors if i['id'] == flavor_id]),
- 'The list of flavors did not start after the marker.')
-
- @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 = {'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]))
-
- @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 = {'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]))
-
- @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 = {'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]))
-
- @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 = {'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]))
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index fc313f2..74444d7 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -38,6 +38,7 @@
# add lists for watched resources
cls._node_group_templates = []
cls._cluster_templates = []
+ cls._data_sources = []
@classmethod
def tearDownClass(cls):
@@ -45,6 +46,8 @@
cls.client.delete_cluster_template)
cls.cleanup_resources(getattr(cls, '_node_group_templates', []),
cls.client.delete_node_group_template)
+ cls.cleanup_resources(getattr(cls, '_data_sources', []),
+ cls.client.delete_data_source)
cls.clear_isolated_creds()
super(BaseDataProcessingTest, cls).tearDownClass()
@@ -96,3 +99,17 @@
cls._cluster_templates.append(body['id'])
return resp, body
+
+ @classmethod
+ def create_data_source(cls, name, type, url, **kwargs):
+ """Creates watched data source with specified params.
+
+ It supports passing additional params using kwargs and returns created
+ object. All resources created in this method will be automatically
+ removed in tearDownClass method.
+ """
+ resp, body = cls.client.create_data_source(name, type, url, **kwargs)
+ # store id of created data source
+ cls._data_sources.append(body['id'])
+
+ return resp, body
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index cae20ad..8e3a7d1 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -13,6 +13,7 @@
import datetime
import re
from tempest.api.identity import base
+from tempest import auth
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
@@ -88,10 +89,13 @@
self.assertIsNotNone(self.trustee_user_id)
# Initialize a new client with the trustor credentials
- os = clients.Manager(username=self.trustor_username,
- password=self.trustor_password,
- tenant_name=self.trustor_project_name,
- interface=self._interface)
+ creds = auth.get_credentials(
+ username=self.trustor_username,
+ password=self.trustor_password,
+ tenant_name=self.trustor_project_name)
+ os = clients.Manager(
+ credentials=creds,
+ interface=self._interface)
self.trustor_client = os.identity_v3_client
def cleanup_user_and_roles(self):
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index a5bf248..e4e74c1 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -14,6 +14,7 @@
# under the License.
+from tempest import auth
from tempest import clients
from tempest.common.utils import data_utils
from tempest import config
@@ -120,6 +121,14 @@
self.projects = []
self.v3_roles = []
+ @property
+ def test_credentials(self):
+ return auth.get_credentials(username=self.test_user,
+ user_id=self.user['id'],
+ password=self.test_password,
+ tenant_name=self.test_tenant,
+ tenant_id=self.tenant['id'])
+
def setup_test_user(self):
"""Set up a test user."""
self.setup_test_tenant()
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index e439238..31ffd14 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -42,11 +42,7 @@
skip_msg = ("%s skipped as glance is not available" % cls.__name__)
raise cls.skipException(skip_msg)
if CONF.compute.allow_tenant_isolation:
- creds = cls.isolated_creds.get_primary_creds()
- username, tenant_name, password = creds
- cls.os = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name)
+ cls.os = clients.Manager(cls.isolated_creds.get_primary_creds())
else:
cls.os = clients.Manager()
@@ -96,11 +92,7 @@
def setUpClass(cls):
super(BaseV1ImageMembersTest, cls).setUpClass()
if CONF.compute.allow_tenant_isolation:
- creds = cls.isolated_creds.get_alt_creds()
- username, tenant_name, password = creds
- cls.os_alt = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name)
+ cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
else:
cls.os_alt = clients.AltManager()
@@ -139,12 +131,8 @@
super(BaseV2MemberImageTest, cls).setUpClass()
if CONF.compute.allow_tenant_isolation:
creds = cls.isolated_creds.get_alt_creds()
- username, tenant_name, password = creds
- cls.os_alt = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name,
- interface=cls._interface)
- cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
+ cls.os_alt = clients.Manager(creds)
+ cls.alt_tenant_id = cls.isolated_creds.get_alt_creds().tenant_id
else:
cls.os_alt = clients.AltManager()
alt_tenant_name = cls.os_alt.credentials['tenant_name']
diff --git a/tempest/api/network/admin/test_load_balancer_admin_actions.py b/tempest/api/network/admin/test_load_balancer_admin_actions.py
index bc7f1d6..fe4fc60 100644
--- a/tempest/api/network/admin/test_load_balancer_admin_actions.py
+++ b/tempest/api/network/admin/test_load_balancer_admin_actions.py
@@ -38,9 +38,7 @@
cls.force_tenant_isolation = True
manager = cls.get_client_manager()
cls.client = manager.network_client
- username, tenant_name, passwd = cls.isolated_creds.get_primary_creds()
- cls.tenant_id = cls.os_adm.identity_client.get_tenant_by_name(
- tenant_name)['id']
+ cls.tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
cls.network = cls.create_network()
cls.subnet = cls.create_subnet(cls.network)
cls.pool = cls.create_pool(data_utils.rand_name('pool-'),
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index 425d3f2..dcd9bff 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -145,7 +145,7 @@
return network
@classmethod
- def create_subnet(cls, network):
+ def create_subnet(cls, network, gateway=None):
"""Wrapper utility that returns a test subnet."""
# The cidr and mask_bits depend on the ip version.
if cls._ip_version == 4:
@@ -156,14 +156,19 @@
mask_bits = CONF.network.tenant_network_v6_mask_bits
# Find a cidr that is not in use yet and create a subnet with it
for subnet_cidr in cidr.subnet(mask_bits):
+ if not gateway:
+ gateway = str(netaddr.IPAddress(subnet_cidr) + 1)
try:
resp, body = cls.client.create_subnet(
network_id=network['id'],
cidr=str(subnet_cidr),
- ip_version=cls._ip_version)
+ ip_version=cls._ip_version,
+ gateway_ip=gateway)
break
except exceptions.BadRequest as e:
is_overlapping_cidr = 'overlaps with another subnet' in str(e)
+ # Unset gateway value if there is an overlapping subnet
+ gateway = None
if not is_overlapping_cidr:
raise
else:
@@ -294,7 +299,7 @@
def create_vpnservice(cls, subnet_id, router_id):
"""Wrapper utility that returns a test vpn service."""
resp, body = cls.client.create_vpnservice(
- subnet_id, router_id, admin_state_up=True,
+ subnet_id=subnet_id, router_id=router_id, admin_state_up=True,
name=data_utils.rand_name("vpnservice-"))
vpnservice = body['vpnservice']
cls.vpnservices.append(vpnservice)
@@ -303,7 +308,7 @@
@classmethod
def create_ikepolicy(cls, name):
"""Wrapper utility that returns a test ike policy."""
- resp, body = cls.client.create_ikepolicy(name)
+ resp, body = cls.client.create_ikepolicy(name=name)
ikepolicy = body['ikepolicy']
cls.ikepolicies.append(ikepolicy)
return ikepolicy
@@ -352,11 +357,7 @@
raise cls.skipException(msg)
if (CONF.compute.allow_tenant_isolation or
cls.force_tenant_isolation is True):
- creds = cls.isolated_creds.get_admin_creds()
- admin_username, admin_tenant_name, admin_password = creds
- cls.os_adm = clients.Manager(username=admin_username,
- password=admin_password,
- tenant_name=admin_tenant_name,
+ cls.os_adm = clients.Manager(cls.isolated_creds.get_admin_creds(),
interface=cls._interface)
else:
cls.os_adm = clients.ComputeAdminManager(interface=cls._interface)
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 00754e4..660b376 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -216,6 +216,37 @@
# it from the list.
self.subnets.pop()
+ @test.attr(type='smoke')
+ def test_create_delete_subnet_with_gw(self):
+ gateway = '10.100.0.13'
+ name = data_utils.rand_name('network-')
+ resp, body = self.client.create_network(name=name)
+ self.assertEqual('201', resp['status'])
+ network = body['network']
+ net_id = network['id']
+ subnet = self.create_subnet(network, gateway)
+ # Verifies Subnet GW in IPv4
+ self.assertEqual(subnet['gateway_ip'], gateway)
+ # Delete network and subnet
+ resp, body = self.client.delete_network(net_id)
+ self.assertEqual('204', resp['status'])
+ self.subnets.pop()
+
+ @test.attr(type='smoke')
+ def test_create_delete_subnet_without_gw(self):
+ name = data_utils.rand_name('network-')
+ resp, body = self.client.create_network(name=name)
+ self.assertEqual('201', resp['status'])
+ network = body['network']
+ net_id = network['id']
+ subnet = self.create_subnet(network)
+ # Verifies Subnet GW in IPv4
+ self.assertEqual(subnet['gateway_ip'], '10.100.0.1')
+ # Delete network and subnet
+ resp, body = self.client.delete_network(net_id)
+ self.assertEqual('204', resp['status'])
+ self.subnets.pop()
+
class NetworksTestXML(NetworksTestJSON):
_interface = 'xml'
@@ -369,6 +400,37 @@
raise cls.skipException(skip_msg)
super(NetworksIpV6TestJSON, cls).setUpClass()
+ @test.attr(type='smoke')
+ def test_create_delete_subnet_with_gw(self):
+ gateway = '2003::2'
+ name = data_utils.rand_name('network-')
+ resp, body = self.client.create_network(name=name)
+ self.assertEqual('201', resp['status'])
+ network = body['network']
+ net_id = network['id']
+ subnet = self.create_subnet(network, gateway)
+ # Verifies Subnet GW in IPv6
+ self.assertEqual(subnet['gateway_ip'], gateway)
+ # Delete network and subnet
+ resp, body = self.client.delete_network(net_id)
+ self.assertEqual('204', resp['status'])
+ self.subnets.pop()
+
+ @test.attr(type='smoke')
+ def test_create_delete_subnet_without_gw(self):
+ name = data_utils.rand_name('network-')
+ resp, body = self.client.create_network(name=name)
+ self.assertEqual('201', resp['status'])
+ network = body['network']
+ net_id = network['id']
+ subnet = self.create_subnet(network)
+ # Verifies Subnet GW in IPv6
+ self.assertEqual(subnet['gateway_ip'], '2003::1')
+ # Delete network and subnet
+ resp, body = self.client.delete_network(net_id)
+ self.assertEqual('204', resp['status'])
+ self.subnets.pop()
+
class NetworksIpV6TestXML(NetworksIpV6TestJSON):
_interface = 'xml'
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 4cc0338..7605b8a 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -262,10 +262,25 @@
self.addCleanup(
self._delete_extra_routes,
self.router['id'])
- # Update router extra route
+ # Update router extra route, second ip of the range is
+ # used as next hop
cidr = netaddr.IPNetwork(self.subnet['cidr'])
+ next_hop = str(cidr[2])
+ destination = str(self.subnet['cidr'])
resp, extra_route = self.client.update_extra_routes(
- self.router['id'], str(cidr[0]), str(self.subnet['cidr']))
+ self.router['id'], next_hop, destination)
+ self.assertEqual('200', resp['status'])
+ self.assertEqual(1, len(extra_route['router']['routes']))
+ self.assertEqual(destination,
+ extra_route['router']['routes'][0]['destination'])
+ self.assertEqual(next_hop,
+ extra_route['router']['routes'][0]['nexthop'])
+ resp, show_body = self.client.show_router(self.router['id'])
+ self.assertEqual('200', resp['status'])
+ self.assertEqual(destination,
+ show_body['router']['routes'][0]['destination'])
+ self.assertEqual(next_hop,
+ show_body['router']['routes'][0]['nexthop'])
def _delete_extra_routes(self, router_id):
resp, _ = self.client.delete_extra_routes(router_id)
diff --git a/tempest/api/network/test_vpnaas_extensions.py b/tempest/api/network/test_vpnaas_extensions.py
index 7edaaf8..a49e944 100644
--- a/tempest/api/network/test_vpnaas_extensions.py
+++ b/tempest/api/network/test_vpnaas_extensions.py
@@ -82,8 +82,8 @@
def test_create_update_delete_vpn_service(self):
# Creates a VPN service
name = data_utils.rand_name('vpn-service-')
- resp, body = self.client.create_vpnservice(self.subnet['id'],
- self.router['id'],
+ resp, body = self.client.create_vpnservice(subnet_id=self.subnet['id'],
+ router_id=self.router['id'],
name=name,
admin_state_up=True)
self.assertEqual('201', resp['status'])
@@ -134,7 +134,7 @@
# Creates a IKE policy
name = data_utils.rand_name('ike-policy-')
resp, body = (self.client.create_ikepolicy(
- name,
+ name=name,
ike_version="v1",
encryption_algorithm="aes-128",
auth_algorithm="sha1"))
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index 45c895b..6b18182 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -38,23 +38,12 @@
cls.__name__, network_resources=cls.network_resources)
if CONF.compute.allow_tenant_isolation:
# Get isolated creds for normal user
- creds = cls.isolated_creds.get_primary_creds()
- username, tenant_name, password = creds
- cls.os = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name)
+ cls.os = clients.Manager(cls.isolated_creds.get_primary_creds())
# Get isolated creds for admin user
- admin_creds = cls.isolated_creds.get_admin_creds()
- admin_username, admin_tenant_name, admin_password = admin_creds
- cls.os_admin = clients.Manager(username=admin_username,
- password=admin_password,
- tenant_name=admin_tenant_name)
+ cls.os_admin = clients.Manager(
+ cls.isolated_creds.get_admin_creds())
# Get isolated creds for alt user
- alt_creds = cls.isolated_creds.get_alt_creds()
- alt_username, alt_tenant, alt_password = alt_creds
- cls.os_alt = clients.Manager(username=alt_username,
- password=alt_password,
- tenant_name=alt_tenant)
+ cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds())
# Add isolated users to operator role so that they can create a
# container in swift.
cls._assign_member_role()
@@ -92,8 +81,8 @@
@classmethod
def _assign_member_role(cls):
- primary_user = cls.isolated_creds.get_primary_user()
- alt_user = cls.isolated_creds.get_alt_user()
+ primary_creds = cls.isolated_creds.get_primary_creds()
+ alt_creds = cls.isolated_creds.get_alt_creds()
swift_role = CONF.object_storage.operator_role
try:
resp, roles = cls.os_admin.identity_client.list_roles()
@@ -101,9 +90,9 @@
except StopIteration:
msg = "No role named %s found" % swift_role
raise exceptions.NotFound(msg)
- for user in [primary_user, alt_user]:
- cls.os_admin.identity_client.assign_user_role(user['tenantId'],
- user['id'],
+ for creds in [primary_creds, alt_creds]:
+ cls.os_admin.identity_client.assign_user_role(creds.tenant_id,
+ creds.user_id,
role['id'])
@classmethod
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index c1f468b..021555c 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -35,10 +35,7 @@
cls.data.setup_test_user()
- cls.os_reselleradmin = clients.Manager(
- cls.data.test_user,
- cls.data.test_password,
- cls.data.test_tenant)
+ cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
# Retrieve the ResellerAdmin role id
reseller_role_id = None
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 4677f97..f1355db 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -35,10 +35,7 @@
cls.data.setup_test_user()
- cls.os_reselleradmin = clients.Manager(
- cls.data.test_user,
- cls.data.test_password,
- cls.data.test_tenant)
+ cls.os_reselleradmin = clients.Manager(cls.data.test_credentials)
# Retrieve the ResellerAdmin role id
reseller_role_id = None
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index 7fb0604..d615374 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -67,9 +67,7 @@
self.data.setup_test_user()
os_test_user = clients.Manager(
- self.data.test_user,
- self.data.test_password,
- self.data.test_tenant)
+ self.data.test_credentials)
# Retrieve the id of an operator role of object storage
test_role_id = None
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index 71eaab5..d5f8649 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -28,9 +28,7 @@
# create user
self.data.setup_test_user()
- test_os = clients.Manager(self.data.test_user,
- self.data.test_password,
- self.data.test_tenant)
+ test_os = clients.Manager(self.data.test_credentials)
test_auth_provider = test_os.auth_provider
# Get auth for the test user
test_auth_provider.auth_data
diff --git a/tempest/api/object_storage/test_container_acl.py b/tempest/api/object_storage/test_container_acl.py
index c865ee1..fc51504 100644
--- a/tempest/api/object_storage/test_container_acl.py
+++ b/tempest/api/object_storage/test_container_acl.py
@@ -24,9 +24,7 @@
def setUpClass(cls):
super(ObjectTestACLs, cls).setUpClass()
cls.data.setup_test_user()
- test_os = clients.Manager(cls.data.test_user,
- cls.data.test_password,
- cls.data.test_tenant)
+ test_os = clients.Manager(cls.data.test_credentials)
cls.test_auth_data = test_os.auth_provider.auth_data
@classmethod
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index 547bf87..ca53876 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -26,9 +26,7 @@
def setUpClass(cls):
super(ObjectACLsNegativeTest, cls).setUpClass()
cls.data.setup_test_user()
- test_os = clients.Manager(cls.data.test_user,
- cls.data.test_password,
- cls.data.test_tenant)
+ test_os = clients.Manager(cls.data.test_credentials)
cls.test_auth_data = test_os.auth_provider.auth_data
@classmethod
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index 4f399b4..d1541b9 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -29,10 +29,7 @@
# endpoint and test the healthcheck feature.
cls.data.setup_test_user()
- cls.os_test_user = clients.Manager(
- cls.data.test_user,
- cls.data.test_password,
- cls.data.test_tenant)
+ cls.os_test_user = clients.Manager(cls.data.test_credentials)
cls.xml_start = '<?xml version="1.0"?>\n' \
'<!DOCTYPE cross-domain-policy SYSTEM ' \
diff --git a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
index 60b8dc1..7f088de 100644
--- a/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
+++ b/tempest/api/orchestration/stacks/test_nova_keypair_resources.py
@@ -70,13 +70,13 @@
output_map[outputs['output_key']] = outputs['output_value']
#Test that first key generated public and private keys
self.assertTrue('KeyPair_PublicKey' in output_map)
- self.assertTrue("Generated by" in output_map['KeyPair_PublicKey'])
+ self.assertTrue("Generated" in output_map['KeyPair_PublicKey'])
self.assertTrue('KeyPair_PrivateKey' in output_map)
self.assertTrue('-----BEGIN' in output_map['KeyPair_PrivateKey'])
#Test that second key generated public key, and private key is not
#in the output due to save_private_key = false
self.assertTrue('KeyPairDontSavePrivate_PublicKey' in output_map)
- self.assertTrue('Generated by' in
+ self.assertTrue('Generated' in
output_map['KeyPairDontSavePrivate_PublicKey'])
self.assertTrue(u'KeyPairDontSavePrivate_PrivateKey' in output_map)
private_key = output_map['KeyPairDontSavePrivate_PrivateKey']
diff --git a/tempest/api/volume/admin/test_volume_quotas.py b/tempest/api/volume/admin/test_volume_quotas.py
index 2949d56..531e145 100644
--- a/tempest/api/volume/admin/test_volume_quotas.py
+++ b/tempest/api/volume/admin/test_volume_quotas.py
@@ -29,8 +29,7 @@
def setUpClass(cls):
super(VolumeQuotasAdminTestJSON, cls).setUpClass()
cls.admin_volume_client = cls.os_adm.volumes_client
- cls.demo_tenant_id = cls.isolated_creds.get_primary_user().get(
- 'tenantId')
+ cls.demo_tenant_id = cls.isolated_creds.get_primary_creds().tenant_id
@test.attr(type='gate')
def test_list_quotas(self):
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index ff616fc..4d11d24 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -136,11 +136,7 @@
"in configuration.")
raise cls.skipException(msg)
if CONF.compute.allow_tenant_isolation:
- creds = cls.isolated_creds.get_admin_creds()
- admin_username, admin_tenant_name, admin_password = creds
- cls.os_adm = clients.Manager(username=admin_username,
- password=admin_password,
- tenant_name=admin_tenant_name,
+ cls.os_adm = clients.Manager(cls.isolated_creds.get_admin_creds(),
interface=cls._interface)
else:
cls.os_adm = clients.AdminManager(interface=cls._interface)
diff --git a/tempest/api/volume/test_volume_transfers.py b/tempest/api/volume/test_volume_transfers.py
index 55a72c1..1ef93b9 100644
--- a/tempest/api/volume/test_volume_transfers.py
+++ b/tempest/api/volume/test_volume_transfers.py
@@ -32,21 +32,13 @@
# Add another tenant to test volume-transfer
if CONF.compute.allow_tenant_isolation:
- creds = cls.isolated_creds.get_alt_creds()
- username, tenant_name, password = creds
- cls.os_alt = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name,
+ cls.os_alt = clients.Manager(cls.isolated_creds.get_alt_creds(),
interface=cls._interface)
cls.alt_tenant_id = cls.isolated_creds.get_alt_tenant()['id']
-
# Add admin tenant to cleanup resources
- adm_creds = cls.isolated_creds.get_admin_creds()
- admin_username, admin_tenant_name, admin_password = adm_creds
- cls.os_adm = clients.Manager(username=admin_username,
- password=admin_password,
- tenant_name=admin_tenant_name,
+ cls.os_adm = clients.Manager(cls.isolated_creds.get_admin_creds(),
interface=cls._interface)
+
else:
cls.os_alt = clients.AltManager()
alt_tenant_name = cls.os_alt.credentials['tenant_name']
diff --git a/tempest/api_schema/compute/aggregates.py b/tempest/api_schema/compute/aggregates.py
index a3ab3c8..9393a16 100644
--- a/tempest/api_schema/compute/aggregates.py
+++ b/tempest/api_schema/compute/aggregates.py
@@ -64,3 +64,23 @@
'updated_at'] = {
'type': 'string'
}
+
+common_create_aggregate = {
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'aggregate': aggregate
+ },
+ 'required': ['aggregate']
+ }
+}
+# create-aggregate api doesn't have 'hosts' and 'metadata' attributes.
+del common_create_aggregate['response_body']['properties']['aggregate'][
+ 'properties']['hosts']
+del common_create_aggregate['response_body']['properties']['aggregate'][
+ 'properties']['metadata']
+common_create_aggregate['response_body']['properties']['aggregate'][
+ 'required'] = ['availability_zone', 'created_at', 'deleted', 'deleted_at',
+ 'id', 'name', 'updated_at']
+
+aggregate_add_remove_host = get_aggregate
diff --git a/tempest/api_schema/compute/hosts.py b/tempest/api_schema/compute/hosts.py
index a9d6567..2596c27 100644
--- a/tempest/api_schema/compute/hosts.py
+++ b/tempest/api_schema/compute/hosts.py
@@ -73,3 +73,13 @@
'required': ['host']
}
}
+
+update_host_common = {
+ 'type': 'object',
+ 'properties': {
+ 'host': {'type': 'string'},
+ 'maintenance_mode': {'enum': ['on_maintenance', 'off_maintenance']},
+ 'status': {'enum': ['enabled', 'disabled']}
+ },
+ 'required': ['host', 'maintenance_mode', 'status']
+}
diff --git a/tempest/api_schema/compute/v2/aggregates.py b/tempest/api_schema/compute/v2/aggregates.py
index de3e12b..bc36044 100644
--- a/tempest/api_schema/compute/v2/aggregates.py
+++ b/tempest/api_schema/compute/v2/aggregates.py
@@ -12,6 +12,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+from tempest.api_schema.compute import aggregates
+
delete_aggregate = {
'status_code': [200]
}
+
+create_aggregate = copy.deepcopy(aggregates.common_create_aggregate)
+# V2 API's response status_code is 200
+create_aggregate['status_code'] = [200]
diff --git a/tempest/api_schema/compute/v2/hosts.py b/tempest/api_schema/compute/v2/hosts.py
index 9ec8848..86efadf 100644
--- a/tempest/api_schema/compute/v2/hosts.py
+++ b/tempest/api_schema/compute/v2/hosts.py
@@ -35,3 +35,8 @@
reboot_host['response_body']['properties']['power_action'] = {
'enum': ['reboot']
}
+
+update_host = {
+ 'status_code': [200],
+ 'response_body': hosts.update_host_common
+}
diff --git a/tempest/api_schema/compute/v3/aggregates.py b/tempest/api_schema/compute/v3/aggregates.py
index 358e455..0272641 100644
--- a/tempest/api_schema/compute/v3/aggregates.py
+++ b/tempest/api_schema/compute/v3/aggregates.py
@@ -12,6 +12,18 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
+from tempest.api_schema.compute import aggregates
+
delete_aggregate = {
'status_code': [204]
}
+
+create_aggregate = copy.deepcopy(aggregates.common_create_aggregate)
+# V3 API's response status_code is 201
+create_aggregate['status_code'] = [201]
+
+aggregate_add_remove_host = copy.deepcopy(aggregates.aggregate_add_remove_host)
+# V3 API's response status_code is 202
+aggregate_add_remove_host['status_code'] = [202]
diff --git a/tempest/api_schema/compute/v3/hosts.py b/tempest/api_schema/compute/v3/hosts.py
index 575a6e2..eb689d1 100644
--- a/tempest/api_schema/compute/v3/hosts.py
+++ b/tempest/api_schema/compute/v3/hosts.py
@@ -16,7 +16,6 @@
from tempest.api_schema.compute import hosts
-
startup_host = {
'status_code': [200],
'response_body': {
@@ -41,3 +40,14 @@
reboot_host['response_body']['properties']['power_action'] = {
'enum': ['reboot']
}
+
+update_host = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'host': hosts.update_host_common
+ },
+ 'required': ['host']
+ }
+}
diff --git a/tempest/clients.py b/tempest/clients.py
index 646a2d9..b9550fd 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -16,6 +16,7 @@
import keystoneclient.exceptions
import keystoneclient.v2_0.client
+from tempest import auth
from tempest.common.rest_client import NegativeRestClient
from tempest import config
from tempest import exceptions
@@ -196,22 +197,12 @@
Top level manager for OpenStack tempest clients
"""
- def __init__(self, username=None, password=None, tenant_name=None,
- interface='json', service=None):
- """
- We allow overriding of the credentials used within the various
- client classes managed by the Manager object. Left as None, the
- standard username/password/tenant_name is used.
-
- :param username: Override of the username
- :param password: Override of the password
- :param tenant_name: Override of the tenant name
- """
+ def __init__(self, credentials=None, interface='json', service=None):
+ # Set interface and client type first
self.interface = interface
self.client_type = 'tempest'
# super cares for credentials validation
- super(Manager, self).__init__(
- username=username, password=password, tenant_name=tenant_name)
+ super(Manager, self).__init__(credentials=credentials)
if self.interface == 'xml':
self.certificates_client = CertificatesClientXML(
@@ -368,10 +359,10 @@
raise exceptions.InvalidConfiguration(msg)
# TODO(andreaf) EC2 client still do their auth, v2 only
- ec2_client_args = (self.credentials.get('username'),
- self.credentials.get('password'),
+ ec2_client_args = (self.credentials.username,
+ self.credentials.password,
CONF.identity.uri,
- self.credentials.get('tenant_name'))
+ self.credentials.tenant_name)
# common clients
self.account_client = AccountClient(self.auth_provider)
@@ -402,11 +393,10 @@
"""
def __init__(self, interface='json', service=None):
- super(AltManager, self).__init__(CONF.identity.alt_username,
- CONF.identity.alt_password,
- CONF.identity.alt_tenant_name,
- interface=interface,
- service=service)
+ super(AltManager, self).__init__(
+ credentials=auth.get_default_credentials('alt_user'),
+ interface=interface,
+ service=service)
class AdminManager(Manager):
@@ -417,11 +407,10 @@
"""
def __init__(self, interface='json', service=None):
- super(AdminManager, self).__init__(CONF.identity.admin_username,
- CONF.identity.admin_password,
- CONF.identity.admin_tenant_name,
- interface=interface,
- service=service)
+ super(AdminManager, self).__init__(
+ credentials=auth.get_default_credentials('identity_admin'),
+ interface=interface,
+ service=service)
class ComputeAdminManager(Manager):
@@ -433,11 +422,10 @@
def __init__(self, interface='json', service=None):
base = super(ComputeAdminManager, self)
- base.__init__(CONF.compute_admin.username,
- CONF.compute_admin.password,
- CONF.compute_admin.tenant_name,
- interface=interface,
- service=service)
+ base.__init__(
+ credentials=auth.get_default_credentials('compute_admin'),
+ interface=interface,
+ service=service)
class OfficialClientManager(manager.Manager):
@@ -452,47 +440,32 @@
IRONICCLIENT_VERSION = '1'
SAHARACLIENT_VERSION = '1.1'
- def __init__(self, username, password, tenant_name):
+ def __init__(self, credentials):
# FIXME(andreaf) Auth provider for client_type 'official' is
# not implemented yet, setting to 'tempest' for now.
self.client_type = 'tempest'
self.interface = None
# super cares for credentials validation
- super(OfficialClientManager, self).__init__(
- username=username, password=password, tenant_name=tenant_name)
+ super(OfficialClientManager, self).__init__(credentials=credentials)
self.baremetal_client = self._get_baremetal_client()
- self.compute_client = self._get_compute_client(username,
- password,
- tenant_name)
- self.identity_client = self._get_identity_client(username,
- password,
- tenant_name)
+ self.compute_client = self._get_compute_client(credentials)
+ self.identity_client = self._get_identity_client(credentials)
self.image_client = self._get_image_client()
self.network_client = self._get_network_client()
- self.volume_client = self._get_volume_client(username,
- password,
- tenant_name)
+ self.volume_client = self._get_volume_client(credentials)
self.object_storage_client = self._get_object_storage_client(
- username,
- password,
- tenant_name)
+ credentials)
self.orchestration_client = self._get_orchestration_client(
- username,
- password,
- tenant_name)
+ credentials)
self.data_processing_client = self._get_data_processing_client(
- username,
- password,
- tenant_name)
+ credentials)
def _get_roles(self):
- keystone_admin = self._get_identity_client(
- CONF.identity.admin_username,
- CONF.identity.admin_password,
- CONF.identity.admin_tenant_name)
+ admin_credentials = auth.get_default_credentials('identity_admin')
+ keystone_admin = self._get_identity_client(admin_credentials)
- username = self.credentials['username']
- tenant_name = self.credentials['tenant_name']
+ username = self.credentials.username
+ tenant_name = self.credentials.tenant_name
user_id = keystone_admin.users.find(name=username).id
tenant_id = keystone_admin.tenants.find(name=tenant_name).id
@@ -501,20 +474,20 @@
return [r.name for r in roles]
- def _get_compute_client(self, username, password, tenant_name):
+ def _get_compute_client(self, credentials):
# Novaclient will not execute operations for anyone but the
# identified user, so a new client needs to be created for
# each user that operations need to be performed for.
if not CONF.service_available.nova:
return None
import novaclient.client
- self._validate_credentials(username, password, tenant_name)
auth_url = CONF.identity.uri
dscv = CONF.identity.disable_ssl_certificate_validation
region = CONF.identity.region
- client_args = (username, password, tenant_name, auth_url)
+ client_args = (credentials.username, credentials.password,
+ credentials.tenant_name, auth_url)
# Create our default Nova client to use in testing
service_type = CONF.compute.catalog_type
@@ -542,7 +515,7 @@
return glanceclient.Client('1', endpoint=endpoint, token=token,
insecure=dscv)
- def _get_volume_client(self, username, password, tenant_name):
+ def _get_volume_client(self, credentials):
if not CONF.service_available.cinder:
return None
import cinderclient.client
@@ -551,25 +524,23 @@
endpoint_type = CONF.volume.endpoint_type
dscv = CONF.identity.disable_ssl_certificate_validation
return cinderclient.client.Client(self.CINDERCLIENT_VERSION,
- username,
- password,
- tenant_name,
+ credentials.username,
+ credentials.password,
+ credentials.tenant_name,
auth_url,
region_name=region,
endpoint_type=endpoint_type,
insecure=dscv,
http_log_debug=True)
- def _get_object_storage_client(self, username, password, tenant_name):
+ def _get_object_storage_client(self, credentials):
if not CONF.service_available.swift:
return None
import swiftclient
auth_url = CONF.identity.uri
# add current tenant to swift operator role group.
- keystone_admin = self._get_identity_client(
- CONF.identity.admin_username,
- CONF.identity.admin_password,
- CONF.identity.admin_tenant_name)
+ admin_credentials = auth.get_default_credentials('identity_admin')
+ keystone_admin = self._get_identity_client(admin_credentials)
# enable test user to operate swift by adding operator role to him.
roles = keystone_admin.roles.list()
@@ -586,26 +557,18 @@
endpoint_type = CONF.object_storage.endpoint_type
os_options = {'endpoint_type': endpoint_type}
- return swiftclient.Connection(auth_url, username, password,
- tenant_name=tenant_name,
+ return swiftclient.Connection(auth_url, credentials.username,
+ credentials.password,
+ tenant_name=credentials.tenant_name,
auth_version='2',
os_options=os_options)
- def _get_orchestration_client(self, username=None, password=None,
- tenant_name=None):
+ def _get_orchestration_client(self, credentials):
if not CONF.service_available.heat:
return None
import heatclient.client
- if not username:
- username = CONF.identity.admin_username
- if not password:
- password = CONF.identity.admin_password
- if not tenant_name:
- tenant_name = CONF.identity.tenant_name
- self._validate_credentials(username, password, tenant_name)
-
- keystone = self._get_identity_client(username, password, tenant_name)
+ keystone = self._get_identity_client(credentials)
region = CONF.identity.region
endpoint_type = CONF.orchestration.endpoint_type
token = keystone.auth_token
@@ -622,22 +585,22 @@
return heatclient.client.Client(self.HEATCLIENT_VERSION,
endpoint,
token=token,
- username=username,
- password=password)
+ username=credentials.username,
+ password=credentials.password)
- def _get_identity_client(self, username, password, tenant_name):
+ def _get_identity_client(self, credentials):
# This identity client is not intended to check the security
# of the identity service, so use admin credentials by default.
- self._validate_credentials(username, password, tenant_name)
auth_url = CONF.identity.uri
dscv = CONF.identity.disable_ssl_certificate_validation
- return keystoneclient.v2_0.client.Client(username=username,
- password=password,
- tenant_name=tenant_name,
- auth_url=auth_url,
- insecure=dscv)
+ return keystoneclient.v2_0.client.Client(
+ username=credentials.username,
+ password=credentials.password,
+ tenant_name=credentials.tenant_name,
+ auth_url=auth_url,
+ insecure=dscv)
def _get_baremetal_client(self):
# ironic client is currently intended to by used by admin users
@@ -654,9 +617,9 @@
service_type = CONF.baremetal.catalog_type
endpoint_type = CONF.baremetal.endpoint_type
creds = {
- 'os_username': self.credentials['username'],
- 'os_password': self.credentials['password'],
- 'os_tenant_name': self.credentials['tenant_name']
+ 'os_username': self.credentials.username,
+ 'os_password': self.credentials.password,
+ 'os_tenant_name': self.credentials.tenant_name
}
try:
@@ -680,41 +643,39 @@
if not CONF.service_available.neutron:
return None
import neutronclient.v2_0.client
- username = CONF.identity.admin_username
- password = CONF.identity.admin_password
- tenant_name = CONF.identity.admin_tenant_name
- self._validate_credentials(username, password, tenant_name)
+ credentials = auth.get_default_credentials('identity_admin')
auth_url = CONF.identity.uri
dscv = CONF.identity.disable_ssl_certificate_validation
endpoint_type = CONF.network.endpoint_type
- return neutronclient.v2_0.client.Client(username=username,
- password=password,
- tenant_name=tenant_name,
- endpoint_type=endpoint_type,
- auth_url=auth_url,
- insecure=dscv)
+ return neutronclient.v2_0.client.Client(
+ username=credentials.username,
+ password=credentials.password,
+ tenant_name=credentials.tenant_name,
+ endpoint_type=endpoint_type,
+ auth_url=auth_url,
+ insecure=dscv)
- def _get_data_processing_client(self, username, password, tenant_name):
+ def _get_data_processing_client(self, credentials):
if not CONF.service_available.sahara:
# Sahara isn't available
return None
import saharaclient.client
- self._validate_credentials(username, password, tenant_name)
-
endpoint_type = CONF.data_processing.endpoint_type
catalog_type = CONF.data_processing.catalog_type
auth_url = CONF.identity.uri
- client = saharaclient.client.Client(self.SAHARACLIENT_VERSION,
- username, password,
- project_name=tenant_name,
- endpoint_type=endpoint_type,
- service_type=catalog_type,
- auth_url=auth_url)
+ client = saharaclient.client.Client(
+ self.SAHARACLIENT_VERSION,
+ credentials.username,
+ credentials.password,
+ project_name=credentials.tenant_name,
+ endpoint_type=endpoint_type,
+ service_type=catalog_type,
+ auth_url=auth_url)
return client
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 9a50c0b..5059a5b 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -14,9 +14,6 @@
import netaddr
-import keystoneclient.v2_0.client as keystoneclient
-import neutronclient.v2_0.client as neutronclient
-
from tempest import auth
from tempest import clients
from tempest.common.utils import data_utils
@@ -44,24 +41,6 @@
self.identity_admin_client, self.network_admin_client = (
self._get_admin_clients())
- def _get_official_admin_clients(self):
- username = CONF.identity.admin_username
- password = CONF.identity.admin_password
- tenant_name = CONF.identity.admin_tenant_name
- auth_url = CONF.identity.uri
- dscv = CONF.identity.disable_ssl_certificate_validation
- identity_client = keystoneclient.Client(username=username,
- password=password,
- tenant_name=tenant_name,
- auth_url=auth_url,
- insecure=dscv)
- network_client = neutronclient.Client(username=username,
- password=password,
- tenant_name=tenant_name,
- auth_url=auth_url,
- insecure=dscv)
- return identity_client, network_client
-
def _get_admin_clients(self):
"""
Returns a tuple with instances of the following admin clients (in this
@@ -71,11 +50,11 @@
"""
if self.tempest_client:
os = clients.AdminManager(interface=self.interface)
- admin_clients = (os.identity_client,
- os.network_client,)
else:
- admin_clients = self._get_official_admin_clients()
- return admin_clients
+ os = clients.OfficialClientManager(
+ auth.get_default_credentials('identity_admin')
+ )
+ return os.identity_client, os.network_client
def _create_tenant(self, name, description):
if self.tempest_client:
@@ -388,13 +367,13 @@
else:
return credentials
- def get_primary_creds(self, old_style=True):
+ def get_primary_creds(self, old_style=False):
return self.get_credentials('primary', old_style)
- def get_admin_creds(self, old_style=True):
+ def get_admin_creds(self, old_style=False):
return self.get_credentials('admin', old_style)
- def get_alt_creds(self, old_style=True):
+ def get_alt_creds(self, old_style=False):
return self.get_credentials('alt', old_style)
def _clear_isolated_router(self, router_id, router_name):
@@ -404,7 +383,6 @@
except exceptions.NotFound:
LOG.warn('router with name: %s not found for delete' %
router_name)
- pass
def _clear_isolated_subnet(self, subnet_id, subnet_name):
net_client = self.network_admin_client
@@ -413,7 +391,6 @@
except exceptions.NotFound:
LOG.warn('subnet with name: %s not found for delete' %
subnet_name)
- pass
def _clear_isolated_network(self, network_id, network_name):
net_client = self.network_admin_client
@@ -422,7 +399,6 @@
except exceptions.NotFound:
LOG.warn('network with name: %s not found for delete' %
network_name)
- pass
def _cleanup_ports(self, network_id):
# TODO(mlavalle) This method will be removed once patch
@@ -468,7 +444,6 @@
except exceptions.NotFound:
LOG.warn('router with name: %s not found for delete' %
router['name'])
- pass
self._clear_isolated_router(router['id'], router['name'])
if (not self.network_resources or
self.network_resources.get('network')):
@@ -492,10 +467,8 @@
except exceptions.NotFound:
LOG.warn("user with name: %s not found for delete" %
creds.username)
- pass
try:
self._delete_tenant(creds.tenant_id)
except exceptions.NotFound:
LOG.warn("tenant with name: %s not found for delete" %
creds.tenant_name)
- pass
diff --git a/tempest/common/rest_client.py b/tempest/common/rest_client.py
index 4f1e709..02a8c65 100644
--- a/tempest/common/rest_client.py
+++ b/tempest/common/rest_client.py
@@ -140,15 +140,19 @@
@property
def user(self):
- return self.auth_provider.credentials.get('username', None)
+ return self.auth_provider.credentials.username
@property
def tenant_name(self):
- return self.auth_provider.credentials.get('tenant_name', None)
+ return self.auth_provider.credentials.tenant_name
+
+ @property
+ def tenant_id(self):
+ return self.auth_provider.credentials.tenant_id
@property
def password(self):
- return self.auth_provider.credentials.get('password', None)
+ return self.auth_provider.credentials.password
@property
def base_url(self):
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 8e6b9fb..d52ed7c 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -13,6 +13,7 @@
import time
+from tempest.common.utils import misc as misc_utils
from tempest import config
from tempest import exceptions
from tempest.openstack.common import log as logging
@@ -86,6 +87,9 @@
'timeout': timeout})
message += ' Current status: %s.' % server_status
message += ' Current task state: %s.' % task_state
+ caller = misc_utils.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
raise exceptions.TimeoutException(message)
old_status = server_status
old_task_state = task_state
@@ -119,4 +123,7 @@
'status': status,
'timeout': client.build_timeout})
message += ' Current status: %s.' % image['status']
+ caller = misc_utils.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
raise exceptions.TimeoutException(message)
diff --git a/tempest/manager.py b/tempest/manager.py
index 63235db..fb2842f 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -29,7 +29,7 @@
and a client object for a test case to use in performing actions.
"""
- def __init__(self, username=None, password=None, tenant_name=None):
+ def __init__(self, credentials=None):
"""
We allow overriding of the credentials used within the various
client classes managed by the Manager object. Left as None, the
@@ -38,29 +38,18 @@
:param credentials: Override of the credentials
"""
self.auth_version = CONF.identity.auth_version
- # FIXME(andreaf) Change Manager __init__ to accept a credentials dict
- if username is None or password is None:
- # Tenant None is a valid use case
- self.credentials = self.get_default_credentials()
+ if credentials is None:
+ self.credentials = auth.get_default_credentials('user')
else:
- self.credentials = dict(username=username, password=password,
- tenant_name=tenant_name)
- if self.auth_version == 'v3':
- self.credentials['domain_name'] = 'Default'
+ self.credentials = credentials
+ # Check if passed or default credentials are valid
+ if not self.credentials.is_valid():
+ raise exceptions.InvalidCredentials()
# Creates an auth provider for the credentials
self.auth_provider = self.get_auth_provider(self.credentials)
# FIXME(andreaf) unused
self.client_attr_names = []
- # we do this everywhere, have it be part of the super class
- def _validate_credentials(self, username, password, tenant_name):
- if None in (username, password, tenant_name):
- msg = ("Missing required credentials. "
- "username: %(u)s, password: %(p)s, "
- "tenant_name: %(t)s" %
- {'u': username, 'p': password, 't': tenant_name})
- raise exceptions.InvalidConfiguration(msg)
-
@classmethod
def get_auth_provider_class(cls, auth_version):
if auth_version == 'v2':
@@ -68,13 +57,6 @@
else:
return auth.KeystoneV3AuthProvider
- def get_default_credentials(self):
- return dict(
- username=CONF.identity.username,
- password=CONF.identity.password,
- tenant_name=CONF.identity.tenant_name
- )
-
def get_auth_provider(self, credentials):
if credentials is None:
raise exceptions.InvalidCredentials(
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 1e7ddb1..c745f4e 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -24,6 +24,7 @@
from novaclient import exceptions as nova_exceptions
from tempest.api.network import common as net_common
+from tempest import auth
from tempest import clients
from tempest.common import isolated_creds
from tempest.common.utils import data_utils
@@ -65,10 +66,8 @@
cls.__name__, tempest_client=False,
network_resources=cls.network_resources)
- username, password, tenant_name = cls.credentials()
-
cls.manager = clients.OfficialClientManager(
- username, password, tenant_name)
+ credentials=cls.credentials())
cls.compute_client = cls.manager.compute_client
cls.image_client = cls.manager.image_client
cls.baremetal_client = cls.manager.baremetal_client
@@ -82,27 +81,27 @@
cls.os_resources = []
@classmethod
- def _get_credentials(cls, get_creds, prefix):
+ def _get_credentials(cls, get_creds, ctype):
if CONF.compute.allow_tenant_isolation:
- username, tenant_name, password = get_creds()
+ creds = get_creds()
else:
- username = getattr(CONF.identity, prefix + 'username')
- password = getattr(CONF.identity, prefix + 'password')
- tenant_name = getattr(CONF.identity, prefix + 'tenant_name')
- return username, password, tenant_name
+ creds = auth.get_default_credentials(ctype)
+ return creds
@classmethod
def credentials(cls):
- return cls._get_credentials(cls.isolated_creds.get_primary_creds, '')
+ return cls._get_credentials(cls.isolated_creds.get_primary_creds,
+ 'user')
@classmethod
def alt_credentials(cls):
- return cls._get_credentials(cls.isolated_creds.get_alt_creds, 'alt_')
+ return cls._get_credentials(cls.isolated_creds.get_alt_creds,
+ 'alt_user')
@classmethod
def admin_credentials(cls):
return cls._get_credentials(cls.isolated_creds.get_admin_creds,
- 'admin_')
+ 'identity_admin')
@staticmethod
def cleanup_resource(resource, test_name):
@@ -541,13 +540,7 @@
@classmethod
def setUpClass(cls):
super(NetworkScenarioTest, cls).setUpClass()
- if CONF.compute.allow_tenant_isolation:
- cls.tenant_id = cls.isolated_creds.get_primary_tenant().id
- else:
- cls.tenant_id = cls.manager._get_identity_client(
- CONF.identity.username,
- CONF.identity.password,
- CONF.identity.tenant_name).tenant_id
+ cls.tenant_id = cls.manager.identity_client.tenant_id
def _create_network(self, tenant_id, namestart='network-smoke-'):
name = data_utils.rand_name(namestart)
@@ -1053,10 +1046,10 @@
@classmethod
def credentials(cls):
- username = CONF.identity.admin_username
- password = CONF.identity.admin_password
- tenant_name = CONF.identity.tenant_name
- return username, password, tenant_name
+ admin_creds = auth.get_default_credentials('identity_admin')
+ creds = auth.get_default_credentials('user')
+ admin_creds.tenant_name = creds.tenant_name
+ return admin_creds
def _load_template(self, base_file, file_name):
filepath = os.path.join(os.path.dirname(os.path.realpath(base_file)),
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index c76a117..4616b82 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -98,17 +98,10 @@
access point
"""
- def __init__(self, tenant_id, tenant_user, tenant_pass, tenant_name):
- self.manager = clients.OfficialClientManager(
- tenant_user,
- tenant_pass,
- tenant_name
- )
- self.keypair = None
- self.tenant_id = tenant_id
- self.tenant_name = tenant_name
- self.tenant_user = tenant_user
- self.tenant_pass = tenant_pass
+ def __init__(self, credentials):
+ self.manager = clients.OfficialClientManager(credentials)
+ # Credentials from manager are filled with both names and IDs
+ self.creds = self.manager.credentials
self.network = None
self.subnet = None
self.router = None
@@ -121,12 +114,14 @@
self.router = router
def _get_tenant_credentials(self):
- return self.tenant_user, self.tenant_pass, self.tenant_name
+ # FIXME(andreaf) Unused method
+ return self.creds
@classmethod
def check_preconditions(cls):
super(TestSecurityGroupsBasicOps, cls).check_preconditions()
- if (cls.alt_tenant_id is None) or (cls.tenant_id is cls.alt_tenant_id):
+ if (cls.alt_creds is None) or \
+ (cls.tenant_id is cls.alt_creds.tenant_id):
msg = 'No alt_tenant defined'
cls.enabled = False
raise cls.skipException(msg)
@@ -140,21 +135,20 @@
@classmethod
def setUpClass(cls):
super(TestSecurityGroupsBasicOps, cls).setUpClass()
- alt_creds = cls.alt_credentials()
- cls.alt_tenant_id = cls.manager._get_identity_client(
- *alt_creds
- ).tenant_id
+ cls.alt_creds = cls.alt_credentials()
+ cls.alt_manager = clients.OfficialClientManager(cls.alt_creds)
+ # Credentials from the manager are filled with both IDs and Names
+ cls.alt_creds = cls.alt_manager.credentials
cls.check_preconditions()
# TODO(mnewby) Consider looking up entities as needed instead
# of storing them as collections on the class.
cls.floating_ips = {}
cls.tenants = {}
- cls.primary_tenant = cls.TenantProperties(cls.tenant_id,
- *cls.credentials())
- cls.alt_tenant = cls.TenantProperties(cls.alt_tenant_id,
- *alt_creds)
+ creds = cls.credentials()
+ cls.primary_tenant = cls.TenantProperties(creds)
+ cls.alt_tenant = cls.TenantProperties(cls.alt_creds)
for tenant in [cls.primary_tenant, cls.alt_tenant]:
- cls.tenants[tenant.tenant_id] = tenant
+ cls.tenants[tenant.creds.tenant_id] = tenant
cls.floating_ip_access = not CONF.network.public_router_id
def cleanup_wrapper(self, resource):
@@ -175,14 +169,14 @@
def _create_tenant_security_groups(self, tenant):
access_sg = self._create_empty_security_group(
namestart='secgroup_access-',
- tenant_id=tenant.tenant_id
+ tenant_id=tenant.creds.tenant_id
)
self.addCleanup(self.cleanup_wrapper, access_sg)
# don't use default secgroup since it allows in-tenant traffic
def_sg = self._create_empty_security_group(
namestart='secgroup_general-',
- tenant_id=tenant.tenant_id
+ tenant_id=tenant.creds.tenant_id
)
self.addCleanup(self.cleanup_wrapper, def_sg)
tenant.security_groups.update(access=access_sg, default=def_sg)
@@ -239,7 +233,7 @@
],
'key_name': tenant.keypair.name,
'security_groups': security_groups,
- 'tenant_id': tenant.tenant_id
+ 'tenant_id': tenant.creds.tenant_id
}
server = self.create_server(name=name, create_kwargs=create_kwargs)
self.addCleanup(self.cleanup_wrapper, server)
@@ -248,7 +242,7 @@
def _create_tenant_servers(self, tenant, num=1):
for i in range(num):
name = 'server-{tenant}-gen-{num}-'.format(
- tenant=tenant.tenant_name,
+ tenant=tenant.creds.tenant_name,
num=i
)
name = data_utils.rand_name(name)
@@ -262,8 +256,8 @@
workaround ip namespace
"""
secgroups = [sg.name for sg in tenant.security_groups.values()]
- name = 'server-{tenant}-access_point-'.format(tenant=tenant.tenant_name
- )
+ name = 'server-{tenant}-access_point-'.format(
+ tenant=tenant.creds.tenant_name)
name = data_utils.rand_name(name)
server = self._create_server(name, tenant,
security_groups=secgroups)
@@ -277,7 +271,7 @@
self.floating_ips.setdefault(server, floating_ip)
def _create_tenant_network(self, tenant):
- network, subnet, router = self._create_networks(tenant.tenant_id)
+ network, subnet, router = self._create_networks(tenant.creds.tenant_id)
for r in [network, router, subnet]:
self.addCleanup(self.cleanup_wrapper, r)
tenant.set_network(network, subnet, router)
@@ -300,7 +294,7 @@
tenant_id = tenant_or_id
else:
tenant = tenant_or_id
- tenant_id = tenant.tenant_id
+ tenant_id = tenant.creds.tenant_id
self._set_compute_context(tenant)
self._create_tenant_keypairs(tenant_id)
self._create_tenant_network(tenant)
diff --git a/tempest/scenario/utils.py b/tempest/scenario/utils.py
index 4c7b6d7..e2adb34 100644
--- a/tempest/scenario/utils.py
+++ b/tempest/scenario/utils.py
@@ -21,6 +21,7 @@
import testscenarios
import testtools
+from tempest import auth
from tempest import clients
from tempest.common.utils import misc
from tempest import config
@@ -39,9 +40,8 @@
self.non_ssh_image_pattern = \
CONF.input_scenario.non_ssh_image_regex
# Setup clients
- ocm = clients.OfficialClientManager(CONF.identity.username,
- CONF.identity.password,
- CONF.identity.tenant_name)
+ ocm = clients.OfficialClientManager(
+ auth.get_default_credentials('user'))
self.client = ocm.compute_client
def ssh_user(self, image_id):
@@ -99,9 +99,8 @@
digit=string.digits)
def __init__(self):
- ocm = clients.OfficialClientManager(CONF.identity.username,
- CONF.identity.password,
- CONF.identity.tenant_name)
+ ocm = clients.OfficialClientManager(
+ auth.get_default_credentials('user', fill_in=False))
self.client = ocm.compute_client
self.image_pattern = CONF.input_scenario.image_regex
self.flavor_pattern = CONF.input_scenario.flavor_regex
diff --git a/tempest/services/compute/json/aggregates_client.py b/tempest/services/compute/json/aggregates_client.py
index 5c0b5d3..71d6f63 100644
--- a/tempest/services/compute/json/aggregates_client.py
+++ b/tempest/services/compute/json/aggregates_client.py
@@ -50,6 +50,7 @@
resp, body = self.post('os-aggregates', post_body)
body = json.loads(body)
+ self.validate_response(v2_schema.create_aggregate, resp, body)
return resp, body['aggregate']
def update_aggregate(self, aggregate_id, name, availability_zone=None):
@@ -87,6 +88,7 @@
resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
post_body)
body = json.loads(body)
+ self.validate_response(schema.aggregate_add_remove_host, resp, body)
return resp, body['aggregate']
def remove_host(self, aggregate_id, host):
@@ -98,6 +100,7 @@
resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
post_body)
body = json.loads(body)
+ self.validate_response(schema.aggregate_add_remove_host, resp, body)
return resp, body['aggregate']
def set_metadata(self, aggregate_id, meta):
diff --git a/tempest/services/compute/json/hosts_client.py b/tempest/services/compute/json/hosts_client.py
index e148572..342f946 100644
--- a/tempest/services/compute/json/hosts_client.py
+++ b/tempest/services/compute/json/hosts_client.py
@@ -61,6 +61,7 @@
resp, body = self.put("os-hosts/%s" % str(hostname), request_body)
body = json.loads(body)
+ self.validate_response(v2_schema.update_host, resp, body)
return resp, body
def startup_host(self, hostname):
diff --git a/tempest/services/compute/v3/json/aggregates_client.py b/tempest/services/compute/v3/json/aggregates_client.py
index 2487ee7..d9b7930 100644
--- a/tempest/services/compute/v3/json/aggregates_client.py
+++ b/tempest/services/compute/v3/json/aggregates_client.py
@@ -50,6 +50,7 @@
resp, body = self.post('os-aggregates', post_body)
body = json.loads(body)
+ self.validate_response(v3_schema.create_aggregate, resp, body)
return resp, body['aggregate']
def update_aggregate(self, aggregate_id, name, availability_zone=None):
@@ -87,6 +88,7 @@
resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
post_body)
body = json.loads(body)
+ self.validate_response(v3_schema.aggregate_add_remove_host, resp, body)
return resp, body['aggregate']
def remove_host(self, aggregate_id, host):
@@ -98,6 +100,7 @@
resp, body = self.post('os-aggregates/%s/action' % aggregate_id,
post_body)
body = json.loads(body)
+ self.validate_response(v3_schema.aggregate_add_remove_host, resp, body)
return resp, body['aggregate']
def set_metadata(self, aggregate_id, meta):
diff --git a/tempest/services/compute/v3/json/hosts_client.py b/tempest/services/compute/v3/json/hosts_client.py
index 24d43d0..d2eb43d 100644
--- a/tempest/services/compute/v3/json/hosts_client.py
+++ b/tempest/services/compute/v3/json/hosts_client.py
@@ -61,6 +61,7 @@
resp, body = self.put("os-hosts/%s" % str(hostname), request_body)
body = json.loads(body)
+ self.validate_response(v3_schema.update_host, resp, body)
return resp, body
def startup_host(self, hostname):
diff --git a/tempest/services/data_processing/v1_1/client.py b/tempest/services/data_processing/v1_1/client.py
index c7b5f93..194e300 100644
--- a/tempest/services/data_processing/v1_1/client.py
+++ b/tempest/services/data_processing/v1_1/client.py
@@ -128,3 +128,37 @@
uri = 'cluster-templates/%s' % tmpl_id
return self.delete(uri)
+
+ def list_data_sources(self):
+ """List all data sources for a user."""
+
+ uri = 'data-sources'
+ return self._request_and_parse(self.get, uri, 'data_sources')
+
+ def get_data_source(self, source_id):
+ """Returns the details of a single data source."""
+
+ uri = 'data-sources/%s' % source_id
+ return self._request_and_parse(self.get, uri, 'data_source')
+
+ def create_data_source(self, name, data_source_type, url, **kwargs):
+ """Creates data source with specified params.
+
+ It supports passing additional params using kwargs and returns created
+ object.
+ """
+ uri = 'data-sources'
+ body = kwargs.copy()
+ body.update({
+ 'name': name,
+ 'type': data_source_type,
+ 'url': url
+ })
+ return self._request_and_parse(self.post, uri, 'data_source',
+ body=json.dumps(body))
+
+ def delete_data_source(self, source_id):
+ """Deletes the specified data source by id."""
+
+ uri = 'data-sources/%s' % source_id
+ return self.delete(uri)
diff --git a/tempest/services/network/json/network_client.py b/tempest/services/network/json/network_client.py
index f9dd8ef..8e53b8d 100644
--- a/tempest/services/network/json/network_client.py
+++ b/tempest/services/network/json/network_client.py
@@ -165,21 +165,6 @@
resp, body = self.delete(uri)
return resp, body
- def create_vpnservice(self, subnet_id, router_id, **kwargs):
- post_body = {
- "vpnservice": {
- "subnet_id": subnet_id,
- "router_id": router_id
- }
- }
- for key, val in kwargs.items():
- post_body['vpnservice'][key] = val
- body = json.dumps(post_body)
- uri = '%s/vpn/vpnservices' % (self.uri_prefix)
- resp, body = self.post(uri, body)
- body = json.loads(body)
- return resp, body
-
def list_router_interfaces(self, uuid):
uri = '%s/ports?device_id=%s' % (self.uri_prefix, uuid)
resp, body = self.get(uri)
diff --git a/tempest/services/network/xml/network_client.py b/tempest/services/network/xml/network_client.py
index 50a1954..a9d4880 100644
--- a/tempest/services/network/xml/network_client.py
+++ b/tempest/services/network/xml/network_client.py
@@ -257,38 +257,6 @@
body = _root_tag_fetcher_and_xml_to_json_parse(body)
return resp, body
- def create_vpnservice(self, subnet_id, router_id, **kwargs):
- uri = '%s/vpn/vpnservices' % (self.uri_prefix)
- vpnservice = common.Element("vpnservice")
- p1 = common.Element("subnet_id", subnet_id)
- p2 = common.Element("router_id", router_id)
- vpnservice.append(p1)
- vpnservice.append(p2)
- common.deep_dict_to_xml(vpnservice, kwargs)
- resp, body = self.post(uri, str(common.Document(vpnservice)))
- body = _root_tag_fetcher_and_xml_to_json_parse(body)
- return resp, body
-
- def create_ikepolicy(self, name, **kwargs):
- uri = '%s/vpn/ikepolicies' % (self.uri_prefix)
- ikepolicy = common.Element("ikepolicy")
- p1 = common.Element("name", name)
- ikepolicy.append(p1)
- common.deep_dict_to_xml(ikepolicy, kwargs)
- resp, body = self.post(uri, str(common.Document(ikepolicy)))
- body = _root_tag_fetcher_and_xml_to_json_parse(body)
- return resp, body
-
- def create_ipsecpolicy(self, name, **kwargs):
- uri = '%s/vpn/ipsecpolicies' % (self.uri_prefix)
- ipsecpolicy = common.Element("ipsecpolicy")
- p1 = common.Element("name", name)
- ipsecpolicy.append(p1)
- common.deep_dict_to_xml(ipsecpolicy, kwargs)
- resp, body = self.post(uri, str(common.Document(ipsecpolicy)))
- body = _root_tag_fetcher_and_xml_to_json_parse(body)
- return resp, body
-
def _root_tag_fetcher_and_xml_to_json_parse(xml_returned_body):
body = ET.fromstring(xml_returned_body)
diff --git a/tempest/stress/driver.py b/tempest/stress/driver.py
index 517cfd5..642108a 100644
--- a/tempest/stress/driver.py
+++ b/tempest/stress/driver.py
@@ -19,6 +19,7 @@
from six import moves
+from tempest import auth
from tempest import clients
from tempest.common import ssh
from tempest.common.utils import data_utils
@@ -147,9 +148,10 @@
password,
tenant['id'],
"email")
- manager = clients.Manager(username=username,
- password="pass",
- tenant_name=tenant_name)
+ creds = auth.get_credentials(username=username,
+ password=password,
+ tenant_name=tenant_name)
+ manager = clients.Manager(credentials=creds)
test_obj = importutils.import_class(test['action'])
test_run = test_obj(manager, max_runs, stop_on_error)
diff --git a/tempest/test.py b/tempest/test.py
index 254fffa..748a98c 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -307,26 +307,18 @@
cls.__name__, network_resources=cls.network_resources)
force_tenant_isolation = getattr(cls, 'force_tenant_isolation', None)
- if (CONF.compute.allow_tenant_isolation or
- force_tenant_isolation):
+ if CONF.compute.allow_tenant_isolation or force_tenant_isolation:
creds = cls.isolated_creds.get_primary_creds()
- username, tenant_name, password = creds
if getattr(cls, '_interface', None):
- os = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name,
+ os = clients.Manager(credentials=creds,
interface=cls._interface,
service=cls._service)
elif interface:
- os = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name,
+ os = clients.Manager(credentials=creds,
interface=interface,
service=cls._service)
else:
- os = clients.Manager(username=username,
- password=password,
- tenant_name=tenant_name,
+ os = clients.Manager(credentials=creds,
service=cls._service)
else:
if getattr(cls, '_interface', None):
diff --git a/tempest/tests/test_hacking.py b/tempest/tests/test_hacking.py
index f584cb9..ab81836 100644
--- a/tempest/tests/test_hacking.py
+++ b/tempest/tests/test_hacking.py
@@ -17,6 +17,36 @@
class HackingTestCase(base.TestCase):
+ """
+ This class tests the hacking checks in tempest.hacking.checks by passing
+ strings to the check methods like the pep8/flake8 parser would. The parser
+ loops over each line in the file and then passes the parameters to the
+ check method. The parameter names in the check method dictate what type of
+ object is passed to the check method. The parameter types are::
+
+ logical_line: A processed line with the following modifications:
+ - Multi-line statements converted to a single line.
+ - Stripped left and right.
+ - Contents of strings replaced with "xxx" of same length.
+ - Comments removed.
+ physical_line: Raw line of text from the input file.
+ lines: a list of the raw lines from the input file
+ tokens: the tokens that contribute to this logical line
+ line_number: line number in the input file
+ total_lines: number of lines in the input file
+ blank_lines: blank lines before this one
+ indent_char: indentation character in this file (" " or "\t")
+ indent_level: indentation (with tabs expanded to multiples of 8)
+ previous_indent_level: indentation on previous line
+ previous_logical: previous logical line
+ filename: Path of the file being run through pep8
+
+ When running a test on a check method the return will be False/None if
+ there is no violation in the sample input. If there is an error a tuple is
+ returned with a position in the line, and a message. So to check the result
+ just assertTrue if the check is expected to fail and assertFalse if it
+ should pass.
+ """
def test_no_setupclass_for_unit_tests(self):
self.assertTrue(checks.no_setupclass_for_unit_tests(
" def setUpClass(cls):", './tempest/tests/fake_test.py'))
@@ -24,3 +54,42 @@
" def setUpClass(cls): # noqa", './tempest/tests/fake_test.py'))
self.assertFalse(checks.no_setupclass_for_unit_tests(
" def setUpClass(cls):", './tempest/api/fake_test.py'))
+
+ def test_import_no_clients_in_api(self):
+ for client in checks.PYTHON_CLIENTS:
+ string = "import " + client + "client"
+ self.assertTrue(checks.import_no_clients_in_api(
+ string, './tempest/api/fake_test.py'))
+ self.assertFalse(checks.import_no_clients_in_api(
+ string, './tempest/scenario/fake_test.py'))
+
+ def test_scenario_tests_need_service_tags(self):
+ self.assertFalse(checks.scenario_tests_need_service_tags(
+ 'def test_fake:', './tempest/scenario/test_fake.py',
+ "@test.services('compute')"))
+ self.assertFalse(checks.scenario_tests_need_service_tags(
+ 'def test_fake_test:', './tempest/api/compute/test_fake.py',
+ "@test.services('image')"))
+ self.assertTrue(checks.scenario_tests_need_service_tags(
+ 'def test_fake_test:', './tempest/scenario/test_fake.py',
+ '\n'))
+
+ def test_no_vi_headers(self):
+ # NOTE(mtreinish) The lines parameter is used only for finding the
+ # line location in the file. So these tests just pass a list of an
+ # arbitrary length to use for verifying the check function.
+ self.assertTrue(checks.no_vi_headers(
+ '# vim: tabstop=4 shiftwidth=4 softtabstop=4', 1, range(250)))
+ self.assertTrue(checks.no_vi_headers(
+ '# vim: tabstop=4 shiftwidth=4 softtabstop=4', 249, range(250)))
+ self.assertFalse(checks.no_vi_headers(
+ '# vim: tabstop=4 shiftwidth=4 softtabstop=4', 149, range(250)))
+
+ def test_service_tags_not_in_module_path(self):
+ self.assertTrue(checks.service_tags_not_in_module_path(
+ "@test.services('compute')", './tempest/api/compute/fake_test.py'))
+ self.assertFalse(checks.service_tags_not_in_module_path(
+ "@test.services('compute')",
+ './tempest/scenario/compute/fake_test.py'))
+ self.assertFalse(checks.service_tags_not_in_module_path(
+ "@test.services('compute')", './tempest/api/image/fake_test.py'))
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 084b6d2..98a896f 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -17,6 +17,7 @@
import neutronclient.v2_0.client as neutronclient
from oslo.config import cfg
+from tempest import clients
from tempest.common import http
from tempest.common import isolated_creds
from tempest import config
@@ -52,6 +53,12 @@
def test_official_client(self):
self.useFixture(mockpatch.PatchObject(keystoneclient.Client,
'authenticate'))
+ self.useFixture(mockpatch.PatchObject(clients.OfficialClientManager,
+ '_get_image_client'))
+ self.useFixture(mockpatch.PatchObject(clients.OfficialClientManager,
+ '_get_object_storage_client'))
+ self.useFixture(mockpatch.PatchObject(clients.OfficialClientManager,
+ '_get_orchestration_client'))
iso_creds = isolated_creds.IsolatedCreds('test class',
tempest_client=False)
self.assertTrue(isinstance(iso_creds.identity_admin_client,
@@ -142,7 +149,7 @@
self.addCleanup(user_mock.stop)
with patch.object(json_iden_client.IdentityClientJSON,
'assign_user_role') as user_mock:
- admin_creds = iso_creds.get_admin_creds(old_style=False)
+ admin_creds = iso_creds.get_admin_creds()
user_mock.assert_called_once_with('1234', '1234', '1234')
self.assertEqual(admin_creds.username, 'fake_admin_user')
self.assertEqual(admin_creds.tenant_name, 'fake_admin_tenant')
@@ -176,7 +183,7 @@
[{'id': '123456', 'name': 'admin'}])))
with patch.object(json_iden_client.IdentityClientJSON,
'assign_user_role'):
- iso_creds.get_admin_creds(old_style=False)
+ iso_creds.get_admin_creds()
user_mock = self.patch(
'tempest.services.identity.json.identity_client.'
'IdentityClientJSON.delete_user')
@@ -290,7 +297,7 @@
[{'id': '123456', 'name': 'admin'}])))
with patch.object(json_iden_client.IdentityClientJSON,
'assign_user_role'):
- iso_creds.get_admin_creds(old_style=False)
+ iso_creds.get_admin_creds()
self.patch('tempest.services.identity.json.identity_client.'
'IdentityClientJSON.delete_user')
self.patch('tempest.services.identity.json.identity_client.'
@@ -353,7 +360,7 @@
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClientJSON.'
'add_router_interface_with_subnet_id')
- username, tenant_name, password = iso_creds.get_alt_creds()
+ iso_creds.get_alt_creds()
router_interface_mock.called_once_with('1234', '1234')
network = iso_creds.get_alt_network()
subnet = iso_creds.get_alt_subnet()
@@ -384,7 +391,7 @@
[{'id': '123456', 'name': 'admin'}])))
with patch.object(json_iden_client.IdentityClientJSON,
'assign_user_role'):
- username, tenant_name, password = iso_creds.get_admin_creds()
+ iso_creds.get_admin_creds()
router_interface_mock.called_once_with('1234', '1234')
network = iso_creds.get_admin_network()
subnet = iso_creds.get_admin_subnet()
@@ -419,7 +426,7 @@
'delete_router')
router_mock = router.start()
- username, tenant_name, password = iso_creds.get_primary_creds()
+ iso_creds.get_primary_creds()
self.assertEqual(net_mock.mock_calls, [])
self.assertEqual(subnet_mock.mock_calls, [])
self.assertEqual(router_mock.mock_calls, [])
diff --git a/tempest/tests/test_wrappers.py b/tempest/tests/test_wrappers.py
index 49809eb..bba4012 100644
--- a/tempest/tests/test_wrappers.py
+++ b/tempest/tests/test_wrappers.py
@@ -14,6 +14,7 @@
import os
import shutil
+import StringIO
import subprocess
import tempfile
@@ -45,55 +46,47 @@
shutil.copy('tempest/tests/files/setup.cfg', self.setup_cfg_file)
shutil.copy('tempest/tests/files/__init__.py', self.init_file)
shutil.copy('tools/subunit-trace.py', self.subunit_trace)
+ # copy over the pretty_tox scripts
+ shutil.copy('tools/pretty_tox.sh',
+ os.path.join(self.directory, 'pretty_tox.sh'))
+ shutil.copy('tools/pretty_tox_serial.sh',
+ os.path.join(self.directory, 'pretty_tox_serial.sh'))
+
+ self.stdout = StringIO.StringIO()
+ self.stderr = StringIO.StringIO()
+ # Change directory, run wrapper and check result
+ self.addCleanup(os.chdir, os.path.abspath(os.curdir))
+ os.chdir(self.directory)
+
+ def assertRunExit(self, cmd, expected):
+ p = subprocess.Popen(
+ "bash %s" % cmd, shell=True,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ # wait in the general case is dangerous, however the amount of
+ # data coming back on those pipes is small enough it shouldn't be
+ # a problem.
+ p.wait()
+
+ self.assertEqual(
+ p.returncode, expected,
+ "Stdout: %s; Stderr: %s" % (p.stdout, p.stderr))
def test_pretty_tox(self):
- # Copy wrapper script and requirements:
- pretty_tox = os.path.join(self.directory, 'pretty_tox.sh')
- shutil.copy('tools/pretty_tox.sh', pretty_tox)
- # Change directory, run wrapper and check result
- self.addCleanup(os.chdir, os.path.abspath(os.curdir))
- os.chdir(self.directory)
# Git init is required for the pbr testr command. pbr requires a git
# version or an sdist to work. so make the test directory a git repo
# too.
- subprocess.call(['git', 'init'])
- exit_code = subprocess.call('bash pretty_tox.sh tests.passing',
- shell=True, stdout=DEVNULL, stderr=DEVNULL)
- self.assertEqual(exit_code, 0)
+ subprocess.call(['git', 'init'], stderr=DEVNULL)
+ self.assertRunExit('pretty_tox.sh tests.passing', 0)
def test_pretty_tox_fails(self):
- # Copy wrapper script and requirements:
- pretty_tox = os.path.join(self.directory, 'pretty_tox.sh')
- shutil.copy('tools/pretty_tox.sh', pretty_tox)
- # Change directory, run wrapper and check result
- self.addCleanup(os.chdir, os.path.abspath(os.curdir))
- os.chdir(self.directory)
# Git init is required for the pbr testr command. pbr requires a git
# version or an sdist to work. so make the test directory a git repo
# too.
- subprocess.call(['git', 'init'])
- exit_code = subprocess.call('bash pretty_tox.sh', shell=True,
- stdout=DEVNULL, stderr=DEVNULL)
- self.assertEqual(exit_code, 1)
+ subprocess.call(['git', 'init'], stderr=DEVNULL)
+ self.assertRunExit('pretty_tox.sh', 1)
def test_pretty_tox_serial(self):
- # Copy wrapper script and requirements:
- pretty_tox = os.path.join(self.directory, 'pretty_tox_serial.sh')
- shutil.copy('tools/pretty_tox_serial.sh', pretty_tox)
- # Change directory, run wrapper and check result
- self.addCleanup(os.chdir, os.path.abspath(os.curdir))
- os.chdir(self.directory)
- exit_code = subprocess.call('bash pretty_tox_serial.sh tests.passing',
- shell=True, stdout=DEVNULL, stderr=DEVNULL)
- self.assertEqual(exit_code, 0)
+ self.assertRunExit('pretty_tox_serial.sh tests.passing', 0)
def test_pretty_tox_serial_fails(self):
- # Copy wrapper script and requirements:
- pretty_tox = os.path.join(self.directory, 'pretty_tox_serial.sh')
- shutil.copy('tools/pretty_tox_serial.sh', pretty_tox)
- # Change directory, run wrapper and check result
- self.addCleanup(os.chdir, os.path.abspath(os.curdir))
- os.chdir(self.directory)
- exit_code = subprocess.call('bash pretty_tox_serial.sh', shell=True,
- stdout=DEVNULL, stderr=DEVNULL)
- self.assertEqual(exit_code, 1)
+ self.assertRunExit('pretty_tox_serial.sh', 1)
diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py
index 46822e3..743b59d 100644
--- a/tools/install_venv_common.py
+++ b/tools/install_venv_common.py
@@ -101,7 +101,6 @@
print('done.')
else:
print("venv already exists...")
- pass
def pip_install(self, *args):
self.run_command(['tools/with_venv.sh',
diff --git a/tools/subunit-trace.py b/tools/subunit-trace.py
index cb710aa..7bb88a4 100755
--- a/tools/subunit-trace.py
+++ b/tools/subunit-trace.py
@@ -19,6 +19,7 @@
"""Trace a subunit stream in reasonable detail and high accuracy."""
import functools
+import re
import sys
import mimeparse
@@ -207,6 +208,45 @@
stream.write('\n')
+def count_tests(key, value):
+ count = 0
+ for k, v in RESULTS.items():
+ for item in v:
+ if key in item:
+ if re.search(value, item[key]):
+ count += 1
+ return count
+
+
+def worker_stats(worker):
+ tests = RESULTS[worker]
+ num_tests = len(tests)
+ delta = tests[-1]['timestamps'][1] - tests[0]['timestamps'][0]
+ return num_tests, delta
+
+
+def print_summary(stream):
+ stream.write("\n======\nTotals\n======\n")
+ stream.write("Run: %s\n" % count_tests('status', '.*'))
+ stream.write(" - Passed: %s\n" % count_tests('status', 'success'))
+ stream.write(" - Skipped: %s\n" % count_tests('status', 'skip'))
+ stream.write(" - Failed: %s\n" % count_tests('status', 'fail'))
+
+ # we could have no results, especially as we filter out the process-codes
+ if RESULTS:
+ stream.write("\n==============\nWorker Balance\n==============\n")
+
+ for w in range(max(RESULTS.keys()) + 1):
+ if w not in RESULTS:
+ stream.write(
+ " - WARNING: missing Worker %s! "
+ "Race in testr accounting.\n" % w)
+ else:
+ num, time = worker_stats(w)
+ stream.write(" - Worker %s (%s tests) => %ss\n" %
+ (w, num, time))
+
+
def main():
stream = subunit.ByteStreamToStreamResult(
sys.stdin, non_subunit_name='stdout')
@@ -220,6 +260,7 @@
stream.run(result)
finally:
result.stopTestRun()
+ print_summary(sys.stdout)
return (0 if summary.wasSuccessful() else 1)