Merge "Restore "Add scenario 'test_preserve_preexisting_port'""
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index a7c8fb7..15369de 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -3,6 +3,21 @@
Tempest Configuration Guide
===========================
+This guide is a starting point for configuring tempest. It aims to elaborate
+on and explain some of the mandatory and common configuration settings and how
+they are used in conjunction. The source of truth on each option is the sample
+config file which explains the purpose of each individual option.
+
+Lock Path
+---------
+
+There are some tests and operations inside of tempest that need to be
+externally locked when running in parallel to prevent them from running at
+the same time. This is a mandatory step for configuring tempest and is still
+needed even when running serially. All that is needed to do this is:
+
+ #. Set the lock_path option in the oslo_concurrency group
+
Auth/Credentials
----------------
diff --git a/etc/tempest.conf.sample b/etc/tempest.conf.sample
index 428ca03..80d52a4 100644
--- a/etc/tempest.conf.sample
+++ b/etc/tempest.conf.sample
@@ -878,6 +878,9 @@
# Allowed values: public, admin, internal, publicURL, adminURL, internalURL
#endpoint_type = publicURL
+# Role required for users to be able to manage stacks (string value)
+#stack_owner_role = heat_stack_owner
+
# Time in seconds between build status checks. (integer value)
#build_interval = 1
diff --git a/requirements.txt b/requirements.txt
index 56796d8..e6fc09b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,7 +11,6 @@
netaddr>=0.7.12
python-ceilometerclient>=1.0.6
python-glanceclient>=0.15.0
-python-keystoneclient>=1.1.0
python-cinderclient>=1.1.0
python-heatclient>=0.3.0
python-ironicclient>=0.2.1
diff --git a/tempest/api/baremetal/admin/base.py b/tempest/api/baremetal/admin/base.py
index 2834b2b..cf2484d 100644
--- a/tempest/api/baremetal/admin/base.py
+++ b/tempest/api/baremetal/admin/base.py
@@ -16,6 +16,7 @@
from tempest_lib import exceptions as lib_exc
from tempest import clients
+from tempest.common import credentials
from tempest import config
from tempest import test
@@ -69,7 +70,11 @@
@classmethod
def setup_credentials(cls):
super(BaseBaremetalTest, cls).setup_credentials()
- cls.mgr = clients.AdminManager()
+ if (not hasattr(cls, 'isolated_creds') or
+ not cls.isolated_creds.name == cls.__name__):
+ cls.isolated_creds = credentials.get_isolated_credentials(
+ name=cls.__name__, network_resources=cls.network_resources)
+ cls.mgr = clients.Manager(cls.isolated_creds.get_admin_creds())
@classmethod
def setup_clients(cls):
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
index 3c5f507..3c48d9e 100644
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ b/tempest/api/compute/admin/test_floating_ips_bulk.py
@@ -17,6 +17,7 @@
from tempest.api.compute import base
from tempest import config
+from tempest import exceptions
from tempest import test
CONF = config.CONF
@@ -51,7 +52,7 @@
msg = ("Configured unallocated floating IP range is already "
"allocated. Configure the correct unallocated range "
"as 'floating_ip_range'")
- raise cls.skipException(msg)
+ raise exceptions.InvalidConfiguration(msg)
return
def _delete_floating_ips_bulk(self, ip_range):
diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py
index 578f73b..6d79a77 100644
--- a/tempest/api/compute/admin/test_security_groups.py
+++ b/tempest/api/compute/admin/test_security_groups.py
@@ -39,7 +39,7 @@
@test.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1')
@testtools.skipIf(CONF.service_available.neutron,
- "Skipped because neutron do not support all_tenants"
+ "Skipped because neutron does not support all_tenants "
"search filter.")
@test.attr(type='smoke')
@test.services('network')
diff --git a/tempest/api/data_processing/base.py b/tempest/api/data_processing/base.py
index 5992921..d91fbaa 100644
--- a/tempest/api/data_processing/base.py
+++ b/tempest/api/data_processing/base.py
@@ -66,7 +66,6 @@
cls.client.delete_job_binary_internal)
cls.cleanup_resources(getattr(cls, '_data_sources', []),
cls.client.delete_data_source)
- cls.clear_isolated_creds()
super(BaseDataProcessingTest, cls).resource_cleanup()
@staticmethod
diff --git a/tempest/api/identity/base.py b/tempest/api/identity/base.py
index 543dea1..882ef98 100644
--- a/tempest/api/identity/base.py
+++ b/tempest/api/identity/base.py
@@ -31,8 +31,8 @@
@classmethod
def setup_credentials(cls):
super(BaseIdentityAdminTest, cls).setup_credentials()
- cls.os_adm = clients.AdminManager()
- cls.os = clients.Manager()
+ cls.os = cls.get_client_manager()
+ cls.os_adm = clients.Manager(cls.isolated_creds.get_admin_creds())
@classmethod
def disable_user(cls, user_name):
diff --git a/tempest/api/image/base.py b/tempest/api/image/base.py
index 728d077..d513b0c 100644
--- a/tempest/api/image/base.py
+++ b/tempest/api/image/base.py
@@ -61,7 +61,6 @@
for image_id in cls.created_images:
cls.client.wait_for_resource_deletion(image_id)
- cls.isolated_creds.clear_isolated_creds()
super(BaseImageTest, cls).resource_cleanup()
@classmethod
diff --git a/tempest/api/network/base.py b/tempest/api/network/base.py
index e057bb8..cc2d21a 100644
--- a/tempest/api/network/base.py
+++ b/tempest/api/network/base.py
@@ -157,7 +157,6 @@
for network in cls.networks:
cls._try_delete_resource(cls.client.delete_network,
network['id'])
- cls.clear_isolated_creds()
super(BaseNetworkTest, cls).resource_cleanup()
@classmethod
diff --git a/tempest/api/object_storage/base.py b/tempest/api/object_storage/base.py
index f75f4c8..c8697e1 100644
--- a/tempest/api/object_storage/base.py
+++ b/tempest/api/object_storage/base.py
@@ -67,11 +67,6 @@
cls.account_client.auth_provider.clear_auth()
@classmethod
- def resource_cleanup(cls):
- cls.isolated_creds.clear_isolated_creds()
- super(BaseObjectTest, cls).resource_cleanup()
-
- @classmethod
def delete_containers(cls, containers, container_client=None,
object_client=None):
"""Remove given containers and all objects in them.
diff --git a/tempest/api/orchestration/base.py b/tempest/api/orchestration/base.py
index 1877bbf..59fdec0 100644
--- a/tempest/api/orchestration/base.py
+++ b/tempest/api/orchestration/base.py
@@ -18,6 +18,7 @@
import yaml
from tempest import clients
+from tempest.common import credentials
from tempest import config
import tempest.test
@@ -38,7 +39,19 @@
@classmethod
def setup_credentials(cls):
super(BaseOrchestrationTest, cls).setup_credentials()
- cls.os = clients.Manager()
+ if (not hasattr(cls, 'isolated_creds') or
+ not cls.isolated_creds.name == cls.__name__):
+ cls.isolated_creds = credentials.get_isolated_credentials(
+ name=cls.__name__, network_resources=cls.network_resources)
+ stack_owner_role = CONF.orchestration.stack_owner_role
+ if not cls.isolated_creds.is_role_available(stack_owner_role):
+ skip_msg = ("%s skipped because the configured credential provider"
+ " is not able to provide credentials with the %s role "
+ "assigned." % (cls.__name__, stack_owner_role))
+ raise cls.skipException(skip_msg)
+ else:
+ cls.os = clients.Manager(cls.isolated_creds.get_creds_by_roles(
+ [stack_owner_role]))
@classmethod
def setup_clients(cls):
@@ -70,7 +83,7 @@
@classmethod
def _get_identity_admin_client(cls):
"""Returns an instance of the Identity Admin API client."""
- manager = clients.AdminManager()
+ manager = clients.Manager(cls.isolated_creds.get_admin_creds())
admin_client = manager.identity_client
return admin_client
diff --git a/tempest/api/telemetry/base.py b/tempest/api/telemetry/base.py
index 336e2d4..ed719c2 100644
--- a/tempest/api/telemetry/base.py
+++ b/tempest/api/telemetry/base.py
@@ -101,7 +101,6 @@
cls.cleanup_resources(cls.telemetry_client.delete_alarm, cls.alarm_ids)
cls.cleanup_resources(cls.servers_client.delete_server, cls.server_ids)
cls.cleanup_resources(cls.image_client.delete_image, cls.image_ids)
- cls.clear_isolated_creds()
super(BaseTelemetryTest, cls).resource_cleanup()
def await_samples(self, metric, query):
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 8f3f1a3..157bd44 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -102,7 +102,6 @@
def resource_cleanup(cls):
cls.clear_snapshots()
cls.clear_volumes()
- cls.clear_isolated_creds()
super(BaseVolumeTest, cls).resource_cleanup()
@classmethod
diff --git a/tempest/api_schema/response/compute/baremetal_nodes.py b/tempest/api_schema/response/compute/baremetal_nodes.py
index e82792c..82506e7 100644
--- a/tempest/api_schema/response/compute/baremetal_nodes.py
+++ b/tempest/api_schema/response/compute/baremetal_nodes.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import copy
+
node = {
'type': 'object',
'properties': {
@@ -41,7 +43,7 @@
}
}
-get_baremetal_node = {
+baremetal_node = {
'status_code': [200],
'response_body': {
'type': 'object',
@@ -51,3 +53,8 @@
'required': ['node']
}
}
+get_baremetal_node = copy.deepcopy(baremetal_node)
+get_baremetal_node['response_body']['properties']['node'][
+ 'properties'].update({'instance_uuid': {'type': ['string', 'null']}})
+get_baremetal_node['response_body']['properties']['node'][
+ 'required'].append('instance_uuid')
diff --git a/tempest/api_schema/response/compute/hypervisors.py b/tempest/api_schema/response/compute/hypervisors.py
index fc3b828..d6f2bd1 100644
--- a/tempest/api_schema/response/compute/hypervisors.py
+++ b/tempest/api_schema/response/compute/hypervisors.py
@@ -80,8 +80,12 @@
'type': 'object',
'properties': {
'host': {'type': 'string'},
- 'id': {'type': ['integer', 'string']}
+ 'id': {'type': ['integer', 'string']},
+ 'disabled_reason': {'type': ['string', 'null']}
},
+ # NOTE(gmann): 'disabled_reason' is updated in
+ # 'service' dict if 'os-hypervisor-status'
+ # extension is loaded. So this is not required.
'required': ['host', 'id']
},
'vcpus': {'type': 'integer'},
@@ -137,8 +141,12 @@
'type': 'object',
'properties': {
'host': {'type': 'string'},
- 'id': {'type': ['integer', 'string']}
+ 'id': {'type': ['integer', 'string']},
+ 'disabled_reason': {'type': ['string', 'null']}
},
+ # NOTE: 'disabled_reason' is updated in 'service'
+ # dict if os-hypervisor-status' extension is loaded.
+ # So this is not required.
'required': ['host', 'id']
},
'vcpus': {'type': 'integer'},
diff --git a/tempest/api_schema/response/compute/parameter_types.py b/tempest/api_schema/response/compute/parameter_types.py
index 4a1dfdd..90d4c8f 100644
--- a/tempest/api_schema/response/compute/parameter_types.py
+++ b/tempest/api_schema/response/compute/parameter_types.py
@@ -65,3 +65,17 @@
}
}
}
+
+response_header = {
+ 'connection': {'type': 'string'},
+ 'content-length': {'type': 'string'},
+ 'content-type': {'type': 'string'},
+ 'status': {'type': 'string'},
+ 'x-compute-request-id': {'type': 'string'},
+ 'vary': {'type': 'string'},
+ 'x-openstack-nova-api-version': {'type': 'string'},
+ 'date': {
+ 'type': 'string',
+ 'format': 'data-time'
+ }
+}
diff --git a/tempest/api_schema/response/compute/servers.py b/tempest/api_schema/response/compute/servers.py
index f9c957b..3950173 100644
--- a/tempest/api_schema/response/compute/servers.py
+++ b/tempest/api_schema/response/compute/servers.py
@@ -71,6 +71,18 @@
},
'required': ['id', 'links']
},
+ 'fault': {
+ 'type': 'object',
+ 'properties': {
+ 'code': {'type': 'integer'},
+ 'created': {'type': 'string'},
+ 'message': {'type': 'string'},
+ 'details': {'type': 'string'},
+ },
+ # NOTE(gmann): 'details' is not necessary to be present
+ # in the 'fault'. So it is not defined as 'required'.
+ 'required': ['code', 'created', 'message']
+ },
'user_id': {'type': 'string'},
'tenant_id': {'type': 'string'},
'created': {'type': 'string'},
@@ -83,7 +95,9 @@
# NOTE(GMann): 'progress' attribute is present in the response
# only when server's status is one of the progress statuses
# ("ACTIVE","BUILD", "REBUILD", "RESIZE","VERIFY_RESIZE")
- # So it is not defined as 'required'.
+ # 'fault' attribute is present in the response
+ # only when server's status is one of the "ERROR", "DELETED".
+ # So they are not defined as 'required'.
'required': ['id', 'name', 'status', 'image', 'flavor',
'user_id', 'tenant_id', 'created', 'updated',
'metadata', 'links', 'addresses']
@@ -144,8 +158,11 @@
},
'required': ['id', 'links', 'name']
}
- }
+ },
+ 'servers_links': parameter_types.links
},
+ # NOTE(gmann): servers_links attribute is not necessary to be
+ # present always So it is not 'required'.
'required': ['servers']
}
}
diff --git a/tempest/api_schema/response/compute/v2/images.py b/tempest/api_schema/response/compute/v2/images.py
index 43dae38..3c0b80e 100644
--- a/tempest/api_schema/response/compute/v2/images.py
+++ b/tempest/api_schema/response/compute/v2/images.py
@@ -78,8 +78,11 @@
},
'required': ['id', 'links', 'name']
}
- }
+ },
+ 'images_links': parameter_types.links
},
+ # NOTE(gmann): images_links attribute is not necessary to be
+ # present always So it is not 'required'.
'required': ['images']
}
}
@@ -88,15 +91,16 @@
'status_code': [202],
'response_header': {
'type': 'object',
- 'properties': {
- 'location': {
- 'type': 'string',
- 'format': 'uri'
- }
- },
- 'required': ['location']
+ 'properties': parameter_types.response_header
}
}
+create_image['response_header']['properties'].update(
+ {'location': {
+ 'type': 'string',
+ 'format': 'uri'}
+ }
+)
+create_image['response_header']['required'] = ['location']
delete = {
'status_code': [204]
@@ -132,8 +136,11 @@
'images': {
'type': 'array',
'items': common_image_schema
- }
+ },
+ 'images_links': parameter_types.links
},
+ # NOTE(gmann): images_links attribute is not necessary to be
+ # present always So it is not 'required'.
'required': ['images']
}
}
diff --git a/tempest/api_schema/response/compute/v2/servers.py b/tempest/api_schema/response/compute/v2/servers.py
index c116bf5..ebee697 100644
--- a/tempest/api_schema/response/compute/v2/servers.py
+++ b/tempest/api_schema/response/compute/v2/servers.py
@@ -335,7 +335,11 @@
'items']['properties'].update({
'OS-EXT-IPS:type': {'type': 'string'},
'OS-EXT-IPS-MAC:mac_addr': parameter_types.mac_address})
-
+# Defining 'servers_links' attributes for V2 server schema
+list_servers_detail['response_body'][
+ 'properties'].update({'servers_links': parameter_types.links})
+# NOTE(gmann): servers_links attribute is not necessary to be
+# present always So it is not 'required'.
rebuild_server = copy.deepcopy(update_server)
rebuild_server['status_code'] = [202]
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 9c3a8f8..e970249 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -870,31 +870,14 @@
for server in servers:
client = client_for_user(server['owner'])
- res = _get_server_by_name(client, server['name'])
- if not res:
+ response = _get_server_by_name(client, server['name'])
+ if not response:
LOG.info("Server '%s' does not exist" % server['name'])
continue
- # we iterate all interfaces until we find a floating IP
- # and stop looping after dropping it.
- def _find_first_floating():
- if (CONF.service_available.neutron and
- not CONF.baremetal.driver_enabled and
- CONF.compute.use_floatingip_for_ssh):
- for body in res['addresses'].items():
- for addr in body:
- ip = addr['addr']
- if addr.get('OS-EXT-IPS:type',
- 'floating') == 'floating':
- (client.floating_ips.
- disassociate_floating_ip_from_server(
- ip, res['id']))
- client.floating_ips.delete_floating_ip(ip)
- return
-
- _find_first_floating()
- client.servers.delete_server(res['id'])
- client.servers.wait_for_server_termination(res['id'],
+ # TODO(EmilienM): disassociate floating IP from server and release it.
+ client.servers.delete_server(response['id'])
+ client.servers.wait_for_server_termination(response['id'],
ignore_error=True)
diff --git a/tempest/config.py b/tempest/config.py
index b86d54a..12620de 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -696,6 +696,8 @@
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the orchestration service."),
+ cfg.StrOpt('stack_owner_role', default='heat_stack_owner',
+ help='Role required for users to be able to manage stacks'),
cfg.IntOpt('build_interval',
default=1,
help="Time in seconds between build status checks."),
@@ -1205,7 +1207,6 @@
_path = None
_extra_log_defaults = [
- ('keystoneclient.session', std_logging.INFO),
('paramiko.transport', std_logging.INFO),
('requests.packages.urllib3.connectionpool', std_logging.WARN),
]
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 81e771c..f8cc17c 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -14,7 +14,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import os
import subprocess
import netaddr
@@ -24,7 +23,6 @@
from tempest_lib import exceptions as lib_exc
from tempest import clients
-from tempest.common import cred_provider
from tempest.common import credentials
from tempest.common.utils.linux import remote_client
from tempest import config
@@ -50,7 +48,6 @@
cls.manager = clients.Manager(
credentials=cls.credentials()
)
- cls.admin_manager = clients.Manager(cls.admin_credentials())
@classmethod
def setup_clients(cls):
@@ -63,7 +60,6 @@
# Compute image client
cls.images_client = cls.manager.images_client
cls.keypairs_client = cls.manager.keypairs_client
- cls.networks_client = cls.admin_manager.networks_client
# Nova security groups client
cls.security_groups_client = cls.manager.security_groups_client
cls.servers_client = cls.manager.servers_client
@@ -542,6 +538,14 @@
super(NetworkScenarioTest, cls).skip_checks()
if not CONF.service_available.neutron:
raise cls.skipException('Neutron not available')
+ if not credentials.is_admin_available():
+ msg = ("Missing Identity Admin API credentials in configuration.")
+ raise cls.skipException(msg)
+
+ @classmethod
+ def setup_credentials(cls):
+ super(NetworkScenarioTest, cls).setup_credentials()
+ cls.admin_manager = clients.Manager(cls.admin_credentials())
@classmethod
def resource_setup(cls):
@@ -1283,9 +1287,17 @@
"""
@classmethod
+ def skip_checks(cls):
+ super(EncryptionScenarioTest, cls).skip_checks()
+ if not credentials.is_admin_available():
+ msg = ("Missing Identity Admin API credentials in configuration.")
+ raise cls.skipException(msg)
+
+ @classmethod
def setup_clients(cls):
super(EncryptionScenarioTest, cls).setup_clients()
- cls.admin_volume_types_client = cls.admin_manager.volume_types_client
+ admin_manager = clients.Manager(cls.admin_credentials())
+ cls.admin_volume_types_client = admin_manager.volume_types_client
def _wait_for_volume_status(self, status):
self.status_timeout(
@@ -1324,49 +1336,6 @@
control_location=control_location)
-class OrchestrationScenarioTest(ScenarioTest):
- """
- Base class for orchestration scenario tests
- """
-
- @classmethod
- def skip_checks(cls):
- super(OrchestrationScenarioTest, cls).skip_checks()
- if not CONF.service_available.heat:
- raise cls.skipException("Heat support is required")
-
- @classmethod
- def credentials(cls):
- admin_creds = cred_provider.get_configured_credentials(
- 'identity_admin')
- creds = cred_provider.get_configured_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)),
- file_name)
- with open(filepath) as f:
- return f.read()
-
- @classmethod
- def _stack_rand_name(cls):
- return data_utils.rand_name(cls.__name__ + '-')
-
- @classmethod
- def _get_default_network(cls):
- networks = cls.networks_client.list_networks()
- for net in networks:
- if net['label'] == CONF.compute.fixed_network_name:
- return net
-
- @staticmethod
- def _stack_output(stack, output_key):
- """Return a stack output value for a given key."""
- return next((o['output_value'] for o in stack['outputs']
- if o['output_key'] == output_key), None)
-
-
class SwiftScenarioTest(ScenarioTest):
"""
Provide harness to do Swift scenario tests.
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index eed3d0b..e6912d8 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -35,8 +35,8 @@
self.glance_image_create()
self.nova_boot()
- def create_encrypted_volume(self, encryption_provider):
- volume_type = self.create_volume_type(name='luks')
+ def create_encrypted_volume(self, encryption_provider, volume_type):
+ volume_type = self.create_volume_type(name=volume_type)
self.create_encryption_type(type_id=volume_type['id'],
provider=encryption_provider,
key_size=512,
@@ -53,7 +53,8 @@
def test_encrypted_cinder_volumes_luks(self):
self.launch_instance()
self.create_encrypted_volume('nova.volume.encryptors.'
- 'luks.LuksEncryptor')
+ 'luks.LuksEncryptor',
+ volume_type='luks')
self.attach_detach_volume()
@test.idempotent_id('cbc752ed-b716-4717-910f-956cce965722')
@@ -61,5 +62,6 @@
def test_encrypted_cinder_volumes_cryptsetup(self):
self.launch_instance()
self.create_encrypted_volume('nova.volume.encryptors.'
- 'cryptsetup.CryptsetupEncryptor')
+ 'cryptsetup.CryptsetupEncryptor',
+ volume_type='cryptsetup')
self.attach_detach_volume()
diff --git a/tempest/tests/test_auth.py b/tempest/tests/test_auth.py
index f54ff4f..eb63b30 100644
--- a/tempest/tests/test_auth.py
+++ b/tempest/tests/test_auth.py
@@ -19,12 +19,10 @@
from oslotest import mockpatch
from tempest import auth
-from tempest import config
from tempest import exceptions
from tempest.services.identity.v2.json import token_client as v2_client
from tempest.services.identity.v3.json import token_client as v3_client
from tempest.tests import base
-from tempest.tests import fake_config
from tempest.tests import fake_credentials
from tempest.tests import fake_http
from tempest.tests import fake_identity
@@ -46,8 +44,6 @@
def setUp(self):
super(BaseAuthTestsSetUp, self).setUp()
- self.useFixture(fake_config.ConfigFixture())
- self.stubs.Set(config, 'TempestConfigPrivate', fake_config.FakePrivate)
self.fake_http = fake_http.fake_httplib2(return_type=200)
self.stubs.Set(auth, 'get_credentials', fake_get_credentials)
self.auth_provider = self._auth(self.credentials,
diff --git a/tempest/thirdparty/boto/test.py b/tempest/thirdparty/boto/test.py
index 90d0838..cd35e7f 100644
--- a/tempest/thirdparty/boto/test.py
+++ b/tempest/thirdparty/boto/test.py
@@ -23,7 +23,6 @@
from boto import ec2
from boto import exception
from boto import s3
-import keystoneclient.exceptions
from oslo_log import log as logging
import six
@@ -83,7 +82,7 @@
except lib_exc.Unauthorized:
EC2_CAN_CONNECT_ERROR = "AWS credentials not set," +\
- " failed to get them even by keystoneclient"
+ " also failed to get it from keystone"
except Exception as exc:
EC2_CAN_CONNECT_ERROR = str(exc)
@@ -98,7 +97,7 @@
_cred_sub_check(s3client.connection_data)
except Exception as exc:
S3_CAN_CONNECT_ERROR = str(exc)
- except keystoneclient.exceptions.Unauthorized:
+ except lib_exc.Unauthorized:
S3_CAN_CONNECT_ERROR = "AWS credentials not set," +\
" failed to get them even by keystoneclient"
boto_logger.logger.setLevel(level)
@@ -280,7 +279,6 @@
LOG.exception("Cleanup failed %s" % func_name)
finally:
del cls._resource_trash_bin[key]
- cls.clear_isolated_creds()
super(BotoTestCase, cls).resource_cleanup()
# NOTE(afazekas): let the super called even on exceptions
# The real exceptions already logged, if the super throws another,
diff --git a/tools/check_uuid.py b/tools/check_uuid.py
old mode 100644
new mode 100755
index 541e6c3..34effe4
--- a/tools/check_uuid.py
+++ b/tools/check_uuid.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+
# Copyright 2014 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -119,8 +121,10 @@
idempotent_id = None
for decorator in test_node.decorator_list:
if (hasattr(decorator, 'func') and
- decorator.func.attr == DECORATOR_NAME and
- decorator.func.value.id == DECORATOR_MODULE):
+ hasattr(decorator.func, 'attr') and
+ decorator.func.attr == DECORATOR_NAME and
+ hasattr(decorator.func, 'value') and
+ decorator.func.value.id == DECORATOR_MODULE):
for arg in decorator.args:
idempotent_id = ast.literal_eval(arg)
return idempotent_id