Add placement client for basic GET operations
The goal of this placement client for tempest is to make possible the end-to-end testing of the placement based bandwidth feature (see the nova and neutron specs: https://review.openstack.org/502306 https://review.openstack.org/508149) The minimum placement microversion is 1.29, and the following operations are supported: list_allocation_candidates, list_allocations. Change-Id: I0cf1caadeb40761ec79338510919f12baf2d8f56 Partial-Bug: #1578989 See-Also: https://review.openstack.org/502306 (nova spec) See-Also: https://review.openstack.org/508149 (neutron spec)
This commit is contained in:
parent
ccdd729aaf
commit
ceb882169a
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Add basic read-only Placement client to Tempest to make possible the
|
||||
testing of the placement based bandwidth allocation feature.
|
||||
The following API calls are available for tempest from now:
|
||||
|
||||
* GET /allocation_candidates
|
||||
* GET /allocations/{consumer_uuid}
|
||||
|
||||
Add new config group ``placement``, with the config options:
|
||||
|
||||
* ``endpoint_type`` to use for communication with placement service.
|
||||
* ``catalog_type`` of the placement service.
|
||||
* ``region`` as the placement region name to use.
|
||||
* ``min_microversion`` and ``max_microversion`` as the range between
|
||||
placement API requests are sent.
|
|
@ -365,6 +365,38 @@ ComputeGroup = [
|
|||
"with format 'X.Y' or string 'latest'"),
|
||||
]
|
||||
|
||||
placement_group = cfg.OptGroup(name='placement',
|
||||
title='Placement Service Options')
|
||||
|
||||
PlacementGroup = [
|
||||
cfg.StrOpt('endpoint_type',
|
||||
default='public',
|
||||
choices=['public', 'admin', 'internal'],
|
||||
help="The endpoint type to use for the placement service."),
|
||||
cfg.StrOpt('catalog_type',
|
||||
default='placement',
|
||||
help="Catalog type of the Placement service."),
|
||||
cfg.StrOpt('region',
|
||||
default='RegionOne',
|
||||
help="The placement region name to use. If empty, the value "
|
||||
"of [identity]/region is used instead. If no such region "
|
||||
"is found in the service catalog, the first region found "
|
||||
"is used."),
|
||||
cfg.StrOpt('min_microversion',
|
||||
default=None,
|
||||
help="Lower version of the test target microversion range. "
|
||||
"The format is 'X.Y', where 'X' and 'Y' are int values. "
|
||||
"Valid values are string with format 'X.Y' or string "
|
||||
"'latest'"),
|
||||
cfg.StrOpt('max_microversion',
|
||||
default=None,
|
||||
help="Upper version of the test target microversion range. "
|
||||
"The format is 'X.Y', where 'X' and 'Y' are int values. "
|
||||
"Valid values are string with format 'X.Y' or string "
|
||||
"'latest'"),
|
||||
]
|
||||
|
||||
|
||||
compute_features_group = cfg.OptGroup(name='compute-feature-enabled',
|
||||
title="Enabled Compute Service Features")
|
||||
|
||||
|
@ -1096,6 +1128,7 @@ _opts = [
|
|||
(scenario_group, ScenarioGroup),
|
||||
(service_available_group, ServiceAvailableGroup),
|
||||
(debug_group, DebugGroup),
|
||||
(placement_group, PlacementGroup),
|
||||
(None, DefaultGroup)
|
||||
]
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ from tempest.lib.services import identity
|
|||
from tempest.lib.services import image
|
||||
from tempest.lib.services import network
|
||||
from tempest.lib.services import object_storage
|
||||
from tempest.lib.services import placement
|
||||
from tempest.lib.services import volume
|
||||
|
||||
warnings.simplefilter("once")
|
||||
|
@ -46,6 +47,7 @@ def tempest_modules():
|
|||
"""
|
||||
return {
|
||||
'compute': compute,
|
||||
'placement': placement,
|
||||
'identity.v2': identity.v2,
|
||||
'identity.v3': identity.v3,
|
||||
'image.v1': image.v1,
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (c) 2019 Ericsson
|
||||
#
|
||||
# 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.lib.services.placement.placement_client import \
|
||||
PlacementClient
|
||||
|
||||
__all__ = ['PlacementClient']
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) 2019 Ericsson
|
||||
#
|
||||
# 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.lib.common import api_version_utils
|
||||
from tempest.lib.common import rest_client
|
||||
|
||||
PLACEMENT_MICROVERSION = None
|
||||
|
||||
|
||||
class BasePlacementClient(rest_client.RestClient):
|
||||
|
||||
api_microversion_header_name = 'OpenStack-API-Version'
|
||||
version_header_value = 'placement %s'
|
||||
|
||||
def get_headers(self):
|
||||
headers = super(BasePlacementClient, self).get_headers()
|
||||
if PLACEMENT_MICROVERSION:
|
||||
headers[self.api_microversion_header_name] = \
|
||||
self.version_header_value % PLACEMENT_MICROVERSION
|
||||
return headers
|
||||
|
||||
def request(self, method, url, extra_headers=False, headers=None,
|
||||
body=None, chunked=False):
|
||||
resp, resp_body = super(BasePlacementClient, self).request(
|
||||
method, url, extra_headers, headers, body, chunked)
|
||||
if (PLACEMENT_MICROVERSION and
|
||||
PLACEMENT_MICROVERSION != api_version_utils.LATEST_MICROVERSION):
|
||||
api_version_utils.assert_version_header_matches_request(
|
||||
self.api_microversion_header_name,
|
||||
self.version_header_value % PLACEMENT_MICROVERSION,
|
||||
resp)
|
||||
return resp, resp_body
|
|
@ -0,0 +1,50 @@
|
|||
# Copyright (c) 2019 Ericsson
|
||||
#
|
||||
# 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 oslo_serialization import jsonutils as json
|
||||
from six.moves.urllib import parse as urllib
|
||||
|
||||
from tempest.lib.common import rest_client
|
||||
from tempest.lib.services.placement import base_placement_client
|
||||
|
||||
|
||||
class PlacementClient(base_placement_client.BasePlacementClient):
|
||||
|
||||
def list_allocation_candidates(self, **params):
|
||||
"""List allocation candidates.
|
||||
|
||||
For full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://developer.openstack.org/api-ref/placement/#list-allocation-candidates
|
||||
"""
|
||||
url = '/allocation_candidates'
|
||||
if params:
|
||||
url += '?%s' % urllib.urlencode(params)
|
||||
resp, body = self.get(url)
|
||||
self.expected_success(200, resp.status)
|
||||
body = json.loads(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
||||
|
||||
def list_allocations(self, consumer_uuid):
|
||||
"""List all allocation records for the consumer.
|
||||
|
||||
For full list of available parameters, please refer to the official
|
||||
API reference:
|
||||
https://developer.openstack.org/api-ref/placement/#list-allocations
|
||||
"""
|
||||
url = '/allocations/%s' % consumer_uuid
|
||||
resp, body = self.get(url)
|
||||
self.expected_success(200, resp.status)
|
||||
body = json.loads(body)
|
||||
return rest_client.ResponseBody(resp, body)
|
|
@ -0,0 +1,89 @@
|
|||
# Copyright (c) 2019 Ericsson
|
||||
#
|
||||
# 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.lib.services.placement import placement_client
|
||||
from tempest.tests.lib import fake_auth_provider
|
||||
from tempest.tests.lib.services import base
|
||||
|
||||
|
||||
class TestPlacementClient(base.BaseServiceTest):
|
||||
FAKE_ALLOCATION_CANDIDATES = {
|
||||
'allocation_requests': [
|
||||
{'allocations': {
|
||||
'rp-uuid': {'resources': {'VCPU': 42}}
|
||||
}}
|
||||
],
|
||||
'provider_summaries': {
|
||||
'rp-uuid': {
|
||||
'resources': {
|
||||
'VCPU': {'used': 0, 'capacity': 64},
|
||||
'MEMORY_MB': {'capacity': 11196, 'used': 0},
|
||||
'DISK_GB': {'capacity': 19, 'used': 0}
|
||||
},
|
||||
'traits': ["HW_CPU_X86_SVM"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FAKE_ALLOCATIONS = {
|
||||
'allocations': {
|
||||
'rp-uuid-1': {
|
||||
'resources': {
|
||||
'NET_BW_IGR_KILOBIT_PER_SEC': 1
|
||||
},
|
||||
'generation': 14
|
||||
},
|
||||
'rp-uuid2': {
|
||||
'resources': {
|
||||
'MEMORY_MB': 256,
|
||||
'VCPU': 1
|
||||
},
|
||||
'generation': 9
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def setUp(self):
|
||||
super(TestPlacementClient, self).setUp()
|
||||
fake_auth = fake_auth_provider.FakeAuthProvider()
|
||||
self.client = placement_client.PlacementClient(
|
||||
fake_auth, 'placement', 'regionOne')
|
||||
|
||||
def _test_list_allocation_candidates(self, bytes_body=False):
|
||||
self.check_service_client_function(
|
||||
self.client.list_allocation_candidates,
|
||||
'tempest.lib.common.rest_client.RestClient.get',
|
||||
self.FAKE_ALLOCATION_CANDIDATES,
|
||||
to_utf=bytes_body,
|
||||
**{'resources1': 'NET_BW_IGR_KILOBIT_PER_SEC:1'})
|
||||
|
||||
def test_list_allocation_candidates_with_str_body(self):
|
||||
self._test_list_allocation_candidates()
|
||||
|
||||
def test_list_allocation_candidates_with_bytes_body(self):
|
||||
self._test_list_allocation_candidates(bytes_body=True)
|
||||
|
||||
def _test_list_allocations(self, bytes_body=False):
|
||||
self.check_service_client_function(
|
||||
self.client.list_allocations,
|
||||
'tempest.lib.common.rest_client.RestClient.get',
|
||||
self.FAKE_ALLOCATIONS,
|
||||
to_utf=bytes_body,
|
||||
**{'consumer_uuid': 'foo-bar'})
|
||||
|
||||
def test_list_allocations_with_str_body(self):
|
||||
self._test_list_allocations()
|
||||
|
||||
def test_list_allocations_with_bytes_body(self):
|
||||
self._test_list_allocations(bytes_body=True)
|
Loading…
Reference in New Issue