Merge "Apply a naming rule of GET to orchestration client"
diff --git a/requirements.txt b/requirements.txt
index 35b5144..bf7471e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,7 +12,6 @@
python-glanceclient>=0.15.0
python-cinderclient>=1.1.0
python-heatclient>=0.3.0
-python-saharaclient>=0.8.0
python-swiftclient>=2.2.0
testrepository>=0.0.18
oslo.concurrency>=1.8.0,<1.9.0 # Apache-2.0
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 4995209..9f1a548 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -352,10 +352,10 @@
@classmethod
def skip_checks(cls):
+ super(BaseComputeAdminTest, cls).skip_checks()
if not credentials.is_admin_available():
msg = ("Missing Identity Admin API credentials in configuration.")
raise cls.skipException(msg)
- super(BaseComputeAdminTest, cls).skip_checks()
@classmethod
def setup_credentials(cls):
diff --git a/tempest/api/network/admin/test_l3_agent_scheduler.py b/tempest/api/network/admin/test_l3_agent_scheduler.py
index cf0b5e3..fca57c6 100644
--- a/tempest/api/network/admin/test_l3_agent_scheduler.py
+++ b/tempest/api/network/admin/test_l3_agent_scheduler.py
@@ -65,6 +65,21 @@
msg = "L3 Agent Scheduler enabled in conf, but L3 Agent not found"
raise exceptions.InvalidConfiguration(msg)
cls.router = cls.create_router(data_utils.rand_name('router'))
+ # NOTE(armax): If DVR is an available extension, and the created router
+ # is indeed a distributed one, more resources need to be provisioned
+ # in order to bind the router to the L3 agent.
+ # That said, let's preserve the existing test logic, where the extra
+ # query and setup steps are only required if the extension is available
+ # and only if the router's default type is distributed.
+ if test.is_extension_enabled('dvr', 'network'):
+ is_dvr_router = cls.admin_client.show_router(
+ cls.router['id'])['router'].get('distributed', False)
+ if is_dvr_router:
+ cls.network = cls.create_network()
+ cls.create_subnet(cls.network)
+ cls.port = cls.create_port(cls.network)
+ cls.client.add_router_interface_with_port_id(
+ cls.router['id'], cls.port['id'])
@test.attr(type='smoke')
@test.idempotent_id('b7ce6e89-e837-4ded-9b78-9ed3c9c6a45a')
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 1f76b1c..28676b0 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -18,6 +18,7 @@
from tempest_lib import exceptions as lib_exc
from tempest import clients
+from tempest.common import credentials
from tempest.common import fixed_network
from tempest import config
from tempest import exceptions
@@ -175,14 +176,17 @@
"""Base test case class for all Volume Admin API tests."""
@classmethod
+ def skip_checks(cls):
+ super(BaseVolumeAdminTest, cls).skip_checks()
+ if not credentials.is_admin_available():
+ msg = ("Missing Identity Admin API credentials in configuration.")
+ raise cls.skipException(msg)
+
+ @classmethod
def setup_credentials(cls):
super(BaseVolumeAdminTest, cls).setup_credentials()
- try:
- cls.adm_creds = cls.isolated_creds.get_admin_creds()
- cls.os_adm = clients.Manager(credentials=cls.adm_creds)
- except NotImplementedError:
- msg = "Missing Volume Admin API credentials in configuration."
- raise cls.skipException(msg)
+ cls.adm_creds = cls.isolated_creds.get_admin_creds()
+ cls.os_adm = clients.Manager(credentials=cls.adm_creds)
@classmethod
def setup_clients(cls):
diff --git a/tempest/api_schema/response/compute/hypervisors.py b/tempest/api_schema/response/compute/hypervisors.py
deleted file mode 100644
index d6f2bd1..0000000
--- a/tempest/api_schema/response/compute/hypervisors.py
+++ /dev/null
@@ -1,225 +0,0 @@
-# Copyright 2014 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.
-
-import copy
-
-hypervisor_statistics = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisor_statistics': {
- 'type': 'object',
- 'properties': {
- 'count': {'type': 'integer'},
- 'current_workload': {'type': 'integer'},
- 'disk_available_least': {'type': ['integer', 'null']},
- 'free_disk_gb': {'type': 'integer'},
- 'free_ram_mb': {'type': 'integer'},
- 'local_gb': {'type': 'integer'},
- 'local_gb_used': {'type': 'integer'},
- 'memory_mb': {'type': 'integer'},
- 'memory_mb_used': {'type': 'integer'},
- 'running_vms': {'type': 'integer'},
- 'vcpus': {'type': 'integer'},
- 'vcpus_used': {'type': 'integer'}
- },
- 'required': ['count', 'current_workload',
- 'disk_available_least', 'free_disk_gb',
- 'free_ram_mb', 'local_gb', 'local_gb_used',
- 'memory_mb', 'memory_mb_used', 'running_vms',
- 'vcpus', 'vcpus_used']
- }
- },
- 'required': ['hypervisor_statistics']
- }
-}
-
-common_list_hypervisors_detail = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisors': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'state': {'type': 'string'},
- 'cpu_info': {'type': 'string'},
- 'current_workload': {'type': 'integer'},
- 'disk_available_least': {'type': ['integer', 'null']},
- 'host_ip': {
- 'type': 'string',
- 'format': 'ip-address'
- },
- 'free_disk_gb': {'type': 'integer'},
- 'free_ram_mb': {'type': 'integer'},
- 'hypervisor_hostname': {'type': 'string'},
- 'hypervisor_type': {'type': 'string'},
- 'hypervisor_version': {'type': 'integer'},
- 'id': {'type': ['integer', 'string']},
- 'local_gb': {'type': 'integer'},
- 'local_gb_used': {'type': 'integer'},
- 'memory_mb': {'type': 'integer'},
- 'memory_mb_used': {'type': 'integer'},
- 'running_vms': {'type': 'integer'},
- 'service': {
- 'type': 'object',
- 'properties': {
- 'host': {'type': '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'},
- 'vcpus_used': {'type': 'integer'}
- },
- # NOTE: When loading os-hypervisor-status extension,
- # a response contains status and state. So these params
- # should not be required.
- 'required': ['cpu_info', 'current_workload',
- 'disk_available_least', 'host_ip',
- 'free_disk_gb', 'free_ram_mb',
- 'hypervisor_hostname', 'hypervisor_type',
- 'hypervisor_version', 'id', 'local_gb',
- 'local_gb_used', 'memory_mb',
- 'memory_mb_used', 'running_vms', 'service',
- 'vcpus', 'vcpus_used']
- }
- }
- },
- 'required': ['hypervisors']
- }
-}
-
-common_show_hypervisor = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisor': {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'state': {'type': 'string'},
- 'cpu_info': {'type': 'string'},
- 'current_workload': {'type': 'integer'},
- 'disk_available_least': {'type': ['integer', 'null']},
- 'host_ip': {
- 'type': 'string',
- 'format': 'ip-address'
- },
- 'free_disk_gb': {'type': 'integer'},
- 'free_ram_mb': {'type': 'integer'},
- 'hypervisor_hostname': {'type': 'string'},
- 'hypervisor_type': {'type': 'string'},
- 'hypervisor_version': {'type': 'integer'},
- 'id': {'type': ['integer', 'string']},
- 'local_gb': {'type': 'integer'},
- 'local_gb_used': {'type': 'integer'},
- 'memory_mb': {'type': 'integer'},
- 'memory_mb_used': {'type': 'integer'},
- 'running_vms': {'type': 'integer'},
- 'service': {
- 'type': 'object',
- 'properties': {
- 'host': {'type': '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'},
- 'vcpus_used': {'type': 'integer'}
- },
- # NOTE: When loading os-hypervisor-status extension,
- # a response contains status and state. So these params
- # should not be required.
- 'required': ['cpu_info', 'current_workload',
- 'disk_available_least', 'host_ip',
- 'free_disk_gb', 'free_ram_mb',
- 'hypervisor_hostname', 'hypervisor_type',
- 'hypervisor_version', 'id', 'local_gb',
- 'local_gb_used', 'memory_mb', 'memory_mb_used',
- 'running_vms', 'service', 'vcpus', 'vcpus_used']
- }
- },
- 'required': ['hypervisor']
- }
-}
-
-common_hypervisors_detail = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisors': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'state': {'type': 'string'},
- 'id': {'type': ['integer', 'string']},
- 'hypervisor_hostname': {'type': 'string'}
- },
- # NOTE: When loading os-hypervisor-status extension,
- # a response contains status and state. So these params
- # should not be required.
- 'required': ['id', 'hypervisor_hostname']
- }
- }
- },
- 'required': ['hypervisors']
- }
-}
-
-common_hypervisors_info = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'hypervisor': {
- 'type': 'object',
- 'properties': {
- 'status': {'type': 'string'},
- 'state': {'type': 'string'},
- 'id': {'type': ['integer', 'string']},
- 'hypervisor_hostname': {'type': 'string'},
- },
- # NOTE: When loading os-hypervisor-status extension,
- # a response contains status and state. So these params
- # should not be required.
- 'required': ['id', 'hypervisor_hostname']
- }
- },
- 'required': ['hypervisor']
- }
-}
-
-
-hypervisor_uptime = copy.deepcopy(common_hypervisors_info)
-hypervisor_uptime['response_body']['properties']['hypervisor'][
- 'properties']['uptime'] = {'type': 'string'}
-hypervisor_uptime['response_body']['properties']['hypervisor'][
- 'required'] = ['id', 'hypervisor_hostname', 'uptime']
diff --git a/tempest/api_schema/response/compute/v2_1/hypervisors.py b/tempest/api_schema/response/compute/v2_1/hypervisors.py
index cbb7698..3efa46b 100644
--- a/tempest/api_schema/response/compute/v2_1/hypervisors.py
+++ b/tempest/api_schema/response/compute/v2_1/hypervisors.py
@@ -14,13 +14,163 @@
import copy
-from tempest.api_schema.response.compute import hypervisors
+get_hypervisor_statistics = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'hypervisor_statistics': {
+ 'type': 'object',
+ 'properties': {
+ 'count': {'type': 'integer'},
+ 'current_workload': {'type': 'integer'},
+ 'disk_available_least': {'type': ['integer', 'null']},
+ 'free_disk_gb': {'type': 'integer'},
+ 'free_ram_mb': {'type': 'integer'},
+ 'local_gb': {'type': 'integer'},
+ 'local_gb_used': {'type': 'integer'},
+ 'memory_mb': {'type': 'integer'},
+ 'memory_mb_used': {'type': 'integer'},
+ 'running_vms': {'type': 'integer'},
+ 'vcpus': {'type': 'integer'},
+ 'vcpus_used': {'type': 'integer'}
+ },
+ 'required': ['count', 'current_workload',
+ 'disk_available_least', 'free_disk_gb',
+ 'free_ram_mb', 'local_gb', 'local_gb_used',
+ 'memory_mb', 'memory_mb_used', 'running_vms',
+ 'vcpus', 'vcpus_used']
+ }
+ },
+ 'required': ['hypervisor_statistics']
+ }
+}
-hypervisors_servers = copy.deepcopy(hypervisors.common_hypervisors_detail)
+hypervisor_detail = {
+ 'type': 'object',
+ 'properties': {
+ 'status': {'type': 'string'},
+ 'state': {'type': 'string'},
+ 'cpu_info': {'type': 'string'},
+ 'current_workload': {'type': 'integer'},
+ 'disk_available_least': {'type': ['integer', 'null']},
+ 'host_ip': {
+ 'type': 'string',
+ 'format': 'ip-address'
+ },
+ 'free_disk_gb': {'type': 'integer'},
+ 'free_ram_mb': {'type': 'integer'},
+ 'hypervisor_hostname': {'type': 'string'},
+ 'hypervisor_type': {'type': 'string'},
+ 'hypervisor_version': {'type': 'integer'},
+ 'id': {'type': ['integer', 'string']},
+ 'local_gb': {'type': 'integer'},
+ 'local_gb_used': {'type': 'integer'},
+ 'memory_mb': {'type': 'integer'},
+ 'memory_mb_used': {'type': 'integer'},
+ 'running_vms': {'type': 'integer'},
+ 'service': {
+ 'type': 'object',
+ 'properties': {
+ 'host': {'type': 'string'},
+ 'id': {'type': ['integer', 'string']},
+ 'disabled_reason': {'type': ['string', 'null']}
+ },
+ 'required': ['host', 'id']
+ },
+ 'vcpus': {'type': 'integer'},
+ 'vcpus_used': {'type': 'integer'}
+ },
+ # NOTE: When loading os-hypervisor-status extension,
+ # a response contains status and state. So these params
+ # should not be required.
+ 'required': ['cpu_info', 'current_workload',
+ 'disk_available_least', 'host_ip',
+ 'free_disk_gb', 'free_ram_mb',
+ 'hypervisor_hostname', 'hypervisor_type',
+ 'hypervisor_version', 'id', 'local_gb',
+ 'local_gb_used', 'memory_mb', 'memory_mb_used',
+ 'running_vms', 'service', 'vcpus', 'vcpus_used']
+}
-# Defining extra attributes for V3 show hypervisor schema
-hypervisors_servers['response_body']['properties']['hypervisors']['items'][
+list_hypervisors_detail = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'hypervisors': {
+ 'type': 'array',
+ 'items': hypervisor_detail
+ }
+ },
+ 'required': ['hypervisors']
+ }
+}
+
+get_hypervisor = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'hypervisor': hypervisor_detail
+ },
+ 'required': ['hypervisor']
+ }
+}
+
+list_search_hypervisors = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'hypervisors': {
+ 'type': 'array',
+ 'items': {
+ 'type': 'object',
+ 'properties': {
+ 'status': {'type': 'string'},
+ 'state': {'type': 'string'},
+ 'id': {'type': ['integer', 'string']},
+ 'hypervisor_hostname': {'type': 'string'}
+ },
+ # NOTE: When loading os-hypervisor-status extension,
+ # a response contains status and state. So these params
+ # should not be required.
+ 'required': ['id', 'hypervisor_hostname']
+ }
+ }
+ },
+ 'required': ['hypervisors']
+ }
+}
+
+get_hypervisor_uptime = {
+ 'status_code': [200],
+ 'response_body': {
+ 'type': 'object',
+ 'properties': {
+ 'hypervisor': {
+ 'type': 'object',
+ 'properties': {
+ 'status': {'type': 'string'},
+ 'state': {'type': 'string'},
+ 'id': {'type': ['integer', 'string']},
+ 'hypervisor_hostname': {'type': 'string'},
+ 'uptime': {'type': 'string'}
+ },
+ # NOTE: When loading os-hypervisor-status extension,
+ # a response contains status and state. So these params
+ # should not be required.
+ 'required': ['id', 'hypervisor_hostname', 'uptime']
+ }
+ },
+ 'required': ['hypervisor']
+ }
+}
+
+get_hypervisors_servers = copy.deepcopy(list_search_hypervisors)
+get_hypervisors_servers['response_body']['properties']['hypervisors']['items'][
'properties']['servers'] = {
'type': 'array',
'items': {
diff --git a/tempest/cli/simple_read_only/data_processing/__init__.py b/tempest/cli/simple_read_only/data_processing/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/tempest/cli/simple_read_only/data_processing/__init__.py
+++ /dev/null
diff --git a/tempest/cli/simple_read_only/data_processing/test_sahara.py b/tempest/cli/simple_read_only/data_processing/test_sahara.py
deleted file mode 100644
index 153dbd2..0000000
--- a/tempest/cli/simple_read_only/data_processing/test_sahara.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# Copyright (c) 2013 Mirantis Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-import logging
-import re
-
-from tempest_lib import exceptions
-import testtools
-
-from tempest import cli
-from tempest import config
-from tempest import test
-
-CONF = config.CONF
-
-LOG = logging.getLogger(__name__)
-
-
-class SimpleReadOnlySaharaClientTest(cli.ClientTestBase):
- """Basic, read-only tests for Sahara CLI client.
-
- Checks return values and output of read-only commands.
- These tests do not presume any content, nor do they create
- their own. They only verify the structure of output if present.
- """
-
- @classmethod
- def resource_setup(cls):
- if not CONF.service_available.sahara:
- msg = "Skipping all Sahara cli tests because it is not available"
- raise cls.skipException(msg)
- super(SimpleReadOnlySaharaClientTest, cls).resource_setup()
-
- def sahara(self, *args, **kwargs):
- return self.clients.sahara(
- *args, endpoint_type=CONF.data_processing.endpoint_type, **kwargs)
-
- @test.attr(type='negative')
- @test.idempotent_id('c8809259-710f-43f9-b452-54b2be3115a9')
- def test_sahara_fake_action(self):
- self.assertRaises(exceptions.CommandFailed,
- self.sahara,
- 'this-does-not-exist')
-
- @test.idempotent_id('39afe90c-0fd8-456e-89e2-da6de9680fff')
- def test_sahara_plugins_list(self):
- plugins = self.parser.listing(self.sahara('plugin-list'))
- self.assertTableStruct(plugins, [
- 'name',
- 'versions',
- 'title'
- ])
-
- @test.idempotent_id('3eb36fd8-bb06-4004-9e90-84ddf4dbcf5b')
- @testtools.skipUnless(CONF.data_processing_feature_enabled.plugins,
- 'No plugins defined')
- def test_sahara_plugins_show(self):
- name_param = '--name %s' % \
- (CONF.data_processing_feature_enabled.plugins[0])
- result = self.sahara('plugin-show', params=name_param)
- plugin = self.parser.listing(result)
- self.assertTableStruct(plugin, [
- 'Property',
- 'Value'
- ])
-
- @test.idempotent_id('502b684b-3d41-4619-aa6c-4db3465ae79d')
- def test_sahara_node_group_template_list(self):
- result = self.sahara('node-group-template-list')
- node_group_templates = self.parser.listing(result)
- self.assertTableStruct(node_group_templates, [
- 'name',
- 'id',
- 'plugin_name',
- 'node_processes',
- 'description'
- ])
-
- @test.idempotent_id('6c36fe4d-3b88-4b0d-b702-2a051db7dae7')
- def test_sahara_cluster_template_list(self):
- result = self.sahara('cluster-template-list')
- cluster_templates = self.parser.listing(result)
- self.assertTableStruct(cluster_templates, [
- 'name',
- 'id',
- 'plugin_name',
- 'node_groups',
- 'description'
- ])
-
- @test.idempotent_id('b951949d-b9a6-49db-add5-8a18ac533810')
- def test_sahara_cluster_list(self):
- result = self.sahara('cluster-list')
- clusters = self.parser.listing(result)
- self.assertTableStruct(clusters, [
- 'name',
- 'id',
- 'status',
- 'node_count'
- ])
-
- @test.idempotent_id('dbc83a8c-15b6-4aa8-b274-5896577397e1')
- def test_sahara_data_source_list(self):
- result = self.sahara('data-source-list')
- data_sources = self.parser.listing(result)
- self.assertTableStruct(data_sources, [
- 'name',
- 'id',
- 'type',
- 'description'
- ])
-
- @test.idempotent_id('a8f77e05-d4bf-45c3-8245-57835d0de37b')
- def test_sahara_job_binary_data_list(self):
- result = self.sahara('job-binary-data-list')
- job_binary_data_list = self.parser.listing(result)
- self.assertTableStruct(job_binary_data_list, [
- 'id',
- 'name'
- ])
-
- @test.idempotent_id('a8f4d0f3-fa1c-49ce-b73f-d624d89dc381')
- def test_sahara_job_binary_list(self):
- result = self.sahara('job-binary-list')
- job_binaries = self.parser.listing(result)
- self.assertTableStruct(job_binaries, [
- 'id',
- 'name',
- 'description'
- ])
-
- @test.idempotent_id('91164ca4-d049-49e0-a52a-686b408196ff')
- def test_sahara_job_template_list(self):
- result = self.sahara('job-template-list')
- job_templates = self.parser.listing(result)
- self.assertTableStruct(job_templates, [
- 'id',
- 'name',
- 'description'
- ])
-
- @test.idempotent_id('6829c251-a8b6-449d-af86-7dd98b69a7ce')
- def test_sahara_job_list(self):
- result = self.sahara('job-list')
- jobs = self.parser.listing(result)
- self.assertTableStruct(jobs, [
- 'id',
- 'cluster_id',
- 'status'
- ])
-
- @test.idempotent_id('e4bd5d3b-474b-4b7a-82ab-f6bb0bc89faf')
- def test_sahara_bash_completion(self):
- self.sahara('bash-completion')
-
- # Optional arguments
- @test.idempotent_id('699c14e5-632e-46b8-91e5-6bff8c8307e5')
- def test_sahara_help(self):
- help_text = self.sahara('help')
- lines = help_text.split('\n')
- self.assertFirstLineStartsWith(lines, 'usage: sahara')
-
- commands = []
- cmds_start = lines.index('Positional arguments:')
- cmds_end = lines.index('Optional arguments:')
- command_pattern = re.compile('^ {4}([a-z0-9\-\_]+)')
- for line in lines[cmds_start:cmds_end]:
- match = command_pattern.match(line)
- if match:
- commands.append(match.group(1))
- commands = set(commands)
- wanted_commands = set(('cluster-create', 'data-source-create',
- 'image-unregister', 'job-binary-create',
- 'plugin-list', 'job-binary-create', 'help'))
- self.assertFalse(wanted_commands - commands)
-
- @test.idempotent_id('84a18ea6-6379-4024-af6b-0e938f60dfc2')
- def test_sahara_version(self):
- version = self.sahara('', flags='--version')
- self.assertTrue(re.search('[0-9.]+', version))
diff --git a/tempest/cmd/javelin.py b/tempest/cmd/javelin.py
index 05aaabe..fec3bd4 100755
--- a/tempest/cmd/javelin.py
+++ b/tempest/cmd/javelin.py
@@ -86,6 +86,7 @@
owner: javelin
flavor: m1.small
image: javelin_cirros
+ floating_ip_pool: public
- name: hoplite
owner: javelin
flavor: m1.medium
@@ -306,10 +307,10 @@
return tenants
-def _assign_swift_role(user):
+def _assign_swift_role(user, swift_role):
admin = keystone_admin()
roles = admin.identity.list_roles()
- role = next(r for r in roles if r['name'] == 'Member')
+ role = next(r for r in roles if r['name'] == swift_role)
LOG.debug(USERS[user])
try:
admin.identity.assign_user_role(
@@ -583,7 +584,8 @@
LOG.info("Creating objects")
for obj in objects:
LOG.debug("Object %s" % obj)
- _assign_swift_role(obj['owner'])
+ swift_role = obj.get('swift_role', 'Member')
+ _assign_swift_role(obj['owner'], swift_role)
client = client_for_user(obj['owner'])
client.containers.create_container(obj['container'])
client.objects.create_object(
@@ -858,7 +860,9 @@
for secgroup in server['secgroups']:
client.servers.add_security_group(server_id, secgroup)
if CONF.compute.use_floatingip_for_ssh:
- floating_ip = client.floating_ips.create_floating_ip()
+ floating_ip_pool = server.get('floating_ip_pool')
+ floating_ip = client.floating_ips.create_floating_ip(
+ pool_name=floating_ip_pool)
client.floating_ips.associate_floating_ip_to_server(
floating_ip['ip'], server_id)
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index 909de96..3c71e07 100755
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -253,10 +253,9 @@
'database': 'trove'
}
# Get catalog list for endpoints to use for validation
- endpoints = os.endpoints_client.list_endpoints()
- for endpoint in endpoints:
- service = os.service_client.get_service(endpoint['service_id'])
- services.append(service['type'])
+ _token, auth_data = os.auth_provider.get_auth()
+ for entry in auth_data['serviceCatalog']:
+ services.append(entry['type'])
# Pull all catalog types from config file and compare against endpoint list
for cfgname in dir(CONF._config):
cfg = getattr(CONF, cfgname)
@@ -330,7 +329,7 @@
CONF_PARSER = moves.configparser.SafeConfigParser()
CONF_PARSER.optionxform = str
CONF_PARSER.readfp(conf_file)
- os = clients.AdminManager()
+ os = clients.Manager()
services = check_service_availability(os, update)
results = {}
for service in ['nova', 'cinder', 'neutron', 'swift']:
diff --git a/tempest/common/cred_provider.py b/tempest/common/cred_provider.py
index 9630d1c..2c6763d 100644
--- a/tempest/common/cred_provider.py
+++ b/tempest/common/cred_provider.py
@@ -147,3 +147,25 @@
@abc.abstractmethod
def is_role_available(self, role):
return
+
+
+class TestResources(object):
+ """Readonly Credentials, with network resources added."""
+
+ def __init__(self, credentials):
+ self._credentials = credentials
+ self.network = None
+ self.subnet = None
+ self.router = None
+
+ def __getattr__(self, item):
+ return getattr(self._credentials, item)
+
+ def set_resources(self, **kwargs):
+ for key in kwargs.keys():
+ if hasattr(self, key):
+ setattr(self, key, kwargs[key])
+
+ @property
+ def credentials(self):
+ return self._credentials
diff --git a/tempest/common/fixed_network.py b/tempest/common/fixed_network.py
index b533898..67fbab1 100644
--- a/tempest/common/fixed_network.py
+++ b/tempest/common/fixed_network.py
@@ -42,7 +42,8 @@
if (isinstance(creds_provider, isolated_creds.IsolatedCreds) and
(CONF.service_available.neutron and
not CONF.service_available.ironic)):
- network = creds_provider.get_primary_network()
+ # tenant_allow_isolation == True, so network is defined
+ network = creds_provider.get_primary_creds().network
else:
if fixed_network_name:
try:
diff --git a/tempest/common/isolated_creds.py b/tempest/common/isolated_creds.py
index 22fc9c3..1f85872 100644
--- a/tempest/common/isolated_creds.py
+++ b/tempest/common/isolated_creds.py
@@ -142,7 +142,6 @@
network_resources)
self.network_resources = network_resources
self.isolated_creds = {}
- self.isolated_net_resources = {}
self.ports = []
self.password = password
self.default_admin_creds = cred_provider.get_configured_credentials(
@@ -207,7 +206,8 @@
if roles:
for role in roles:
self.creds_client.assign_user_role(user, project, role)
- return self.creds_client.get_credentials(user, project, self.password)
+ creds = self.creds_client.get_credentials(user, project, self.password)
+ return cred_provider.TestResources(creds)
def _create_network_resources(self, tenant_id):
network = None
@@ -297,33 +297,6 @@
self.network_admin_client.add_router_interface_with_subnet_id(
router_id, subnet_id)
- def get_primary_network(self):
- return self.isolated_net_resources.get('primary')[0]
-
- def get_primary_subnet(self):
- return self.isolated_net_resources.get('primary')[1]
-
- def get_primary_router(self):
- return self.isolated_net_resources.get('primary')[2]
-
- def get_admin_network(self):
- return self.isolated_net_resources.get('admin')[0]
-
- def get_admin_subnet(self):
- return self.isolated_net_resources.get('admin')[1]
-
- def get_admin_router(self):
- return self.isolated_net_resources.get('admin')[2]
-
- def get_alt_network(self):
- return self.isolated_net_resources.get('alt')[0]
-
- def get_alt_subnet(self):
- return self.isolated_net_resources.get('alt')[1]
-
- def get_alt_router(self):
- return self.isolated_net_resources.get('alt')[2]
-
def get_credentials(self, credential_type):
if self.isolated_creds.get(str(credential_type)):
credentials = self.isolated_creds[str(credential_type)]
@@ -341,8 +314,8 @@
not CONF.baremetal.driver_enabled):
network, subnet, router = self._create_network_resources(
credentials.tenant_id)
- self.isolated_net_resources[str(credential_type)] = (
- network, subnet, router,)
+ credentials.set_resources(network=network, subnet=subnet,
+ router=router)
LOG.info("Created isolated network resources for : \n"
+ " credentials: %s" % credentials)
return credentials
@@ -368,12 +341,6 @@
new_index = str(roles) + '-' + str(len(self.isolated_creds))
self.isolated_creds[new_index] = exist_creds
del self.isolated_creds[str(roles)]
- # Handle isolated neutron resouces if they exist too
- if CONF.service_available.neutron:
- exist_net = self.isolated_net_resources.get(str(roles))
- if exist_net:
- self.isolated_net_resources[new_index] = exist_net
- del self.isolated_net_resources[str(roles)]
return self.get_credentials(roles)
def _clear_isolated_router(self, router_id, router_name):
@@ -414,27 +381,33 @@
def _clear_isolated_net_resources(self):
net_client = self.network_admin_client
- for cred in self.isolated_net_resources:
- network, subnet, router = self.isolated_net_resources.get(cred)
+ for cred in self.isolated_creds:
+ creds = self.isolated_creds.get(cred)
+ if (not creds or not any([creds.router, creds.network,
+ creds.subnet])):
+ continue
LOG.debug("Clearing network: %(network)s, "
"subnet: %(subnet)s, router: %(router)s",
- {'network': network, 'subnet': subnet, 'router': router})
+ {'network': creds.network, 'subnet': creds.subnet,
+ 'router': creds.router})
if (not self.network_resources or
- self.network_resources.get('router')):
+ (self.network_resources.get('router') and creds.subnet)):
try:
net_client.remove_router_interface_with_subnet_id(
- router['id'], subnet['id'])
+ creds.router['id'], creds.subnet['id'])
except lib_exc.NotFound:
LOG.warn('router with name: %s not found for delete' %
- router['name'])
- self._clear_isolated_router(router['id'], router['name'])
+ creds.router['name'])
+ self._clear_isolated_router(creds.router['id'],
+ creds.router['name'])
if (not self.network_resources or
self.network_resources.get('subnet')):
- self._clear_isolated_subnet(subnet['id'], subnet['name'])
+ self._clear_isolated_subnet(creds.subnet['id'],
+ creds.subnet['name'])
if (not self.network_resources or
self.network_resources.get('network')):
- self._clear_isolated_network(network['id'], network['name'])
- self.isolated_net_resources = {}
+ self._clear_isolated_network(creds.network['id'],
+ creds.network['name'])
def clear_isolated_creds(self):
if not self.isolated_creds:
diff --git a/tempest/manager.py b/tempest/manager.py
index a256f25..025ce65 100644
--- a/tempest/manager.py
+++ b/tempest/manager.py
@@ -46,8 +46,14 @@
# Check if passed or default credentials are valid
if not self.credentials.is_valid():
raise exceptions.InvalidCredentials()
+ # Tenant isolation creates TestResources, but Accounts and some tests
+ # creates Credentials
+ if isinstance(credentials, cred_provider.TestResources):
+ creds = self.credentials.credentials
+ else:
+ creds = self.credentials
# Creates an auth provider for the credentials
- self.auth_provider = get_auth_provider(self.credentials)
+ self.auth_provider = get_auth_provider(creds)
# FIXME(andreaf) unused
self.client_attr_names = []
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index ba80173..65d516f 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -186,7 +186,8 @@
if create_kwargs is None:
create_kwargs = {}
network = self.get_tenant_network()
- fixed_network.set_networks_kwarg(network, create_kwargs)
+ create_kwargs = fixed_network.set_networks_kwarg(network,
+ create_kwargs)
LOG.debug("Creating a server (name: %s, image: %s, flavor: %s)",
name, image, flavor)
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index 92e6c74..c5e8012 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -16,6 +16,7 @@
from oslo_log import log as logging
from tempest_lib.common.utils import data_utils
+from tempest.common import credentials
from tempest.common import tempest_fixtures as fixtures
from tempest.scenario import manager
from tempest import test
@@ -34,6 +35,13 @@
Deletes aggregate
"""
@classmethod
+ def skip_checks(cls):
+ super(TestAggregatesBasicOps, 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(TestAggregatesBasicOps, cls).setup_clients()
cls.aggregates_client = cls.manager.aggregates_client
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 4fab38b..1ecc212 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -125,6 +125,10 @@
if CONF.baremetal.driver_enabled:
msg = ('Not currently supported by baremetal.')
raise cls.skipException(msg)
+ if CONF.network.port_vnic_type in ['direct', 'macvtap']:
+ msg = ('Not currently supported when using vnic_type'
+ ' direct or macvtap')
+ raise cls.skipException(msg)
if not (CONF.network.tenant_networks_reachable or
CONF.network.public_network_id):
msg = ('Either tenant_networks_reachable must be "true", or '
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 8fa2df5..5bc24ea 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -41,6 +41,8 @@
super(TestVolumeBootPattern, cls).skip_checks()
if not CONF.volume_feature_enabled.snapshot:
raise cls.skipException("Cinder volume snapshots are disabled")
+ if CONF.volume.storage_protocol == 'ceph':
+ raise cls.skipException('Skip until bug 1439371 is fixed.')
def _create_volume_from_image(self):
img_uuid = CONF.compute.image_ref
diff --git a/tempest/services/compute/json/hypervisor_client.py b/tempest/services/compute/json/hypervisor_client.py
index bf4bc7f..49ac266 100644
--- a/tempest/services/compute/json/hypervisor_client.py
+++ b/tempest/services/compute/json/hypervisor_client.py
@@ -15,8 +15,7 @@
import json
-from tempest.api_schema.response.compute import hypervisors as common_schema
-from tempest.api_schema.response.compute.v2_1 import hypervisors as v2schema
+from tempest.api_schema.response.compute.v2_1 import hypervisors as schema
from tempest.common import service_client
@@ -26,51 +25,47 @@
"""List hypervisors information."""
resp, body = self.get('os-hypervisors')
body = json.loads(body)
- self.validate_response(common_schema.common_hypervisors_detail,
- resp, body)
+ self.validate_response(schema.list_search_hypervisors, resp, body)
return service_client.ResponseBodyList(resp, body['hypervisors'])
def get_hypervisor_list_details(self):
"""Show detailed hypervisors information."""
resp, body = self.get('os-hypervisors/detail')
body = json.loads(body)
- self.validate_response(common_schema.common_list_hypervisors_detail,
- resp, body)
+ self.validate_response(schema.list_hypervisors_detail, resp, body)
return service_client.ResponseBodyList(resp, body['hypervisors'])
def get_hypervisor_show_details(self, hyper_id):
"""Display the details of the specified hypervisor."""
resp, body = self.get('os-hypervisors/%s' % hyper_id)
body = json.loads(body)
- self.validate_response(common_schema.common_show_hypervisor,
- resp, body)
+ self.validate_response(schema.get_hypervisor, resp, body)
return service_client.ResponseBody(resp, body['hypervisor'])
def get_hypervisor_servers(self, hyper_name):
"""List instances belonging to the specified hypervisor."""
resp, body = self.get('os-hypervisors/%s/servers' % hyper_name)
body = json.loads(body)
- self.validate_response(v2schema.hypervisors_servers, resp, body)
+ self.validate_response(schema.get_hypervisors_servers, resp, body)
return service_client.ResponseBodyList(resp, body['hypervisors'])
def get_hypervisor_stats(self):
"""Get hypervisor statistics over all compute nodes."""
resp, body = self.get('os-hypervisors/statistics')
body = json.loads(body)
- self.validate_response(common_schema.hypervisor_statistics, resp, body)
+ self.validate_response(schema.get_hypervisor_statistics, resp, body)
return service_client.ResponseBody(resp, body['hypervisor_statistics'])
def get_hypervisor_uptime(self, hyper_id):
"""Display the uptime of the specified hypervisor."""
resp, body = self.get('os-hypervisors/%s/uptime' % hyper_id)
body = json.loads(body)
- self.validate_response(common_schema.hypervisor_uptime, resp, body)
+ self.validate_response(schema.get_hypervisor_uptime, resp, body)
return service_client.ResponseBody(resp, body['hypervisor'])
def search_hypervisor(self, hyper_name):
"""Search specified hypervisor."""
resp, body = self.get('os-hypervisors/%s/search' % hyper_name)
body = json.loads(body)
- self.validate_response(common_schema.common_hypervisors_detail,
- resp, body)
+ self.validate_response(schema.list_search_hypervisors, resp, body)
return service_client.ResponseBodyList(resp, body['hypervisors'])
diff --git a/tempest/test.py b/tempest/test.py
index da936b4..d57b1d8 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -445,7 +445,12 @@
# Make sure isolated_creds exists and get a network client
networks_client = cls.get_client_manager().networks_client
isolated_creds = getattr(cls, 'isolated_creds', None)
- if credentials.is_admin_available():
+ # In case of nova network, isolated tenants are not able to list the
+ # network configured in fixed_network_name, even if the can use it
+ # for their servers, so using an admin network client to validate
+ # the network name
+ if (not CONF.service_available.neutron and
+ credentials.is_admin_available()):
admin_creds = isolated_creds.get_admin_creds()
networks_client = clients.Manager(admin_creds).networks_client
return fixed_network.get_tenant_network(isolated_creds,
@@ -467,8 +472,6 @@
super(NegativeAutoTest, cls).setUpClass()
os = cls.get_client_manager()
cls.client = os.negative_client
- os_admin = clients.AdminManager(service=cls._service)
- cls.admin_client = os_admin.negative_client
@staticmethod
def load_tests(*args):
@@ -596,7 +599,13 @@
"mechanism")
if "admin_client" in description and description["admin_client"]:
- client = self.admin_client
+ if not credentials.is_admin_available():
+ msg = ("Missing Identity Admin API credentials in"
+ "configuration.")
+ raise self.skipException(msg)
+ creds = self.isolated_creds.get_admin_creds()
+ os_adm = clients.Manager(credentials=creds)
+ client = os_adm.negative_client
else:
client = self.client
resp, resp_body = client.send_request(method, new_url,
diff --git a/tempest/tests/test_tenant_isolation.py b/tempest/tests/test_tenant_isolation.py
index 82cbde9..fd8718f 100644
--- a/tempest/tests/test_tenant_isolation.py
+++ b/tempest/tests/test_tenant_isolation.py
@@ -278,11 +278,11 @@
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClientJSON.'
'add_router_interface_with_subnet_id')
- iso_creds.get_primary_creds()
+ primary_creds = iso_creds.get_primary_creds()
router_interface_mock.called_once_with('1234', '1234')
- network = iso_creds.get_primary_network()
- subnet = iso_creds.get_primary_subnet()
- router = iso_creds.get_primary_router()
+ network = primary_creds.network
+ subnet = primary_creds.subnet
+ router = primary_creds.router
self.assertEqual(network['id'], '1234')
self.assertEqual(network['name'], 'fake_net')
self.assertEqual(subnet['id'], '1234')
@@ -427,11 +427,11 @@
router_interface_mock = self.patch(
'tempest.services.network.json.network_client.NetworkClientJSON.'
'add_router_interface_with_subnet_id')
- iso_creds.get_alt_creds()
+ 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()
- router = iso_creds.get_alt_router()
+ network = alt_creds.network
+ subnet = alt_creds.subnet
+ router = alt_creds.router
self.assertEqual(network['id'], '1234')
self.assertEqual(network['name'], 'fake_alt_net')
self.assertEqual(subnet['id'], '1234')
@@ -453,11 +453,11 @@
'tempest.services.network.json.network_client.NetworkClientJSON.'
'add_router_interface_with_subnet_id')
self._mock_list_roles('123456', 'admin')
- iso_creds.get_admin_creds()
+ 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()
- router = iso_creds.get_admin_router()
+ network = admin_creds.network
+ subnet = admin_creds.subnet
+ router = admin_creds.router
self.assertEqual(network['id'], '1234')
self.assertEqual(network['name'], 'fake_admin_net')
self.assertEqual(subnet['id'], '1234')
@@ -490,13 +490,13 @@
'delete_router')
router_mock = router.start()
- iso_creds.get_primary_creds()
+ 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, [])
- network = iso_creds.get_primary_network()
- subnet = iso_creds.get_primary_subnet()
- router = iso_creds.get_primary_router()
+ network = primary_creds.network
+ subnet = primary_creds.subnet
+ router = primary_creds.router
self.assertIsNone(network)
self.assertIsNone(subnet)
self.assertIsNone(router)
diff --git a/tempest/thirdparty/boto/test_ec2_network.py b/tempest/thirdparty/boto/test_ec2_network.py
deleted file mode 100644
index ce20156..0000000
--- a/tempest/thirdparty/boto/test_ec2_network.py
+++ /dev/null
@@ -1,44 +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 import test
-from tempest.thirdparty.boto import test as boto_test
-
-
-class EC2NetworkTest(boto_test.BotoTestCase):
-
- @classmethod
- def setup_clients(cls):
- super(EC2NetworkTest, cls).setup_clients()
- cls.ec2_client = cls.os.ec2api_client
-
- # Note(afazekas): these tests for things duable without an instance
- @test.idempotent_id('48b912af-9403-4b4f-aa69-fa76d690a81f')
- def test_disassociate_not_associated_floating_ip(self):
- # EC2 disassociate not associated floating ip
- ec2_codes = self.ec2_error_code
- address = self.ec2_client.allocate_address()
- public_ip = address.public_ip
- rcuk = self.addResourceCleanUp(self.ec2_client.release_address,
- public_ip)
- addresses_get = self.ec2_client.get_all_addresses(
- addresses=(public_ip,))
- self.assertEqual(len(addresses_get), 1)
- self.assertEqual(addresses_get[0].public_ip, public_ip)
- self.assertBotoError(ec2_codes.client.InvalidAssociationID.NotFound,
- address.disassociate)
- self.ec2_client.release_address(public_ip)
- self.assertAddressReleasedWait(address)
- self.cancelResourceCleanUp(rcuk)