commit
f1395fa2c2
13
README.rst
13
README.rst
|
@ -13,6 +13,7 @@ To experiment with it you need a working tempest installation and
|
|||
configuration. I used devstack with::
|
||||
|
||||
enable_service tempest
|
||||
INSTALL_TEMPEST=True
|
||||
|
||||
in local.conf.
|
||||
|
||||
|
@ -24,14 +25,18 @@ cd into it and do the equivalent of::
|
|||
If you are using virtualenvs or need sudo, your form will be
|
||||
different.
|
||||
|
||||
Go to the tempest directory and run testr limit the test run to
|
||||
gabbi related tests::
|
||||
Go to the tempest directory (often ``/opt/stack/tempest``) and run
|
||||
tempest limiting the test run to gabbi related tests::
|
||||
|
||||
testr run gabbi --subunit |subunit-trace
|
||||
tempest run --regex gabbi
|
||||
|
||||
You can be more specific if you like::
|
||||
|
||||
tempest run --regex PlacementNovaGabbi
|
||||
|
||||
This will run the tests described by the YAML files in
|
||||
``gabbi_tempest/tests/scenario/gabbits/``. Edit those files and run
|
||||
the testr command again for fun and adventure.
|
||||
the tempest command again for fun and adventure.
|
||||
|
||||
.. _gnocchi: https://review.openstack.org/#/c/301585/
|
||||
.. _gabbi: https://gabbi.readthedocs.org/
|
||||
|
|
|
@ -14,6 +14,7 @@ import os
|
|||
import unittest
|
||||
|
||||
from gabbi import driver
|
||||
from gabbi.handlers import jsonhandler
|
||||
import six.moves.urllib.parse as urlparse
|
||||
from tempest import config
|
||||
import tempest.test
|
||||
|
@ -39,24 +40,33 @@ class GenericGabbiTest(tempest.test.BaseTestCase):
|
|||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(GenericGabbiTest, cls).resource_setup()
|
||||
url, token = cls._get_service_auth()
|
||||
parsed_url = urlparse.urlsplit(url)
|
||||
prefix = parsed_url.path.rstrip('/') # turn it into a prefix
|
||||
port = 443 if parsed_url.scheme == 'https' else 80
|
||||
host = parsed_url.hostname
|
||||
if parsed_url.port:
|
||||
port = parsed_url.port
|
||||
endpoints, token = cls._get_service_auth()
|
||||
|
||||
# Set test ENVIRON substitutions.
|
||||
for service_type, url in endpoints.items():
|
||||
name = '%s_SERVICE' % service_type.upper()
|
||||
os.environ[name] = url
|
||||
name = '%s_BASE' % service_type.upper()
|
||||
os.environ[name] = '://'.join(urlparse.urlparse(url)[0:2])
|
||||
os.environ['SERVICE_TOKEN'] = token
|
||||
os.environ['IMAGE_REF'] = CONF.compute.image_ref
|
||||
os.environ['FLAVOR_REF'] = CONF.compute.flavor_ref
|
||||
os.environ['FLAVOR_REF_ALT'] = CONF.compute.flavor_ref_alt
|
||||
|
||||
if cls.service_type in endpoints:
|
||||
host = None
|
||||
url = endpoints[cls.service_type]
|
||||
else:
|
||||
host = 'stub'
|
||||
url = None
|
||||
|
||||
test_dir = os.path.join(os.path.dirname(__file__), 'gabbits',
|
||||
cls.service_type)
|
||||
cls.tests = driver.build_tests(
|
||||
test_dir, unittest.TestLoader(),
|
||||
host=host, port=port, prefix=prefix,
|
||||
test_dir, unittest.TestLoader(), host=host, url=url,
|
||||
test_loader_name='tempest.scenario.%s.%s' % (
|
||||
cls.__name__, cls.service_type))
|
||||
|
||||
os.environ["SERVICE_TOKEN"] = token
|
||||
|
||||
@classmethod
|
||||
def clear_credentials(cls):
|
||||
# FIXME(sileht): We don't want the token to be invalided, but
|
||||
|
@ -75,14 +85,20 @@ class GenericGabbiTest(tempest.test.BaseTestCase):
|
|||
|
||||
@classmethod
|
||||
def _get_service_auth(cls):
|
||||
endpoint_type = 'publicURL'
|
||||
|
||||
interface = 'public'
|
||||
auth = cls.os_admin.auth_provider.get_auth()
|
||||
endpoints = [e for e in auth[1]['serviceCatalog']
|
||||
if e['type'] == cls.service_type]
|
||||
if not endpoints:
|
||||
raise Exception("%s endpoint not found" % cls.service_type)
|
||||
return endpoints[0]['endpoints'][0][endpoint_type], auth[0]
|
||||
token = auth[0]
|
||||
catalog = auth[1]['catalog']
|
||||
|
||||
endpoint_lookup = {}
|
||||
for entry in catalog:
|
||||
service_type = entry['type']
|
||||
endpoints = entry['endpoints']
|
||||
for endpoint in endpoints:
|
||||
if endpoint['interface'] == interface:
|
||||
endpoint_lookup[service_type] = endpoint['url']
|
||||
|
||||
return endpoint_lookup, token
|
||||
|
||||
def test_fake(self):
|
||||
# NOTE(sileht): A fake test is needed to have the class loaded
|
||||
|
@ -92,20 +108,17 @@ class GenericGabbiTest(tempest.test.BaseTestCase):
|
|||
|
||||
class NovaGabbiTest(GenericGabbiTest):
|
||||
credentials = ['admin']
|
||||
# NOTE(cdent): WTF? 'nova' being the thing in service_available?
|
||||
# Boo!
|
||||
service_name = 'nova'
|
||||
service_type = 'compute'
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(NovaGabbiTest, cls).resource_setup()
|
||||
# TODO(cdent): not very generic!
|
||||
os.environ['IMAGE_REF'] = CONF.compute.image_ref
|
||||
os.environ['FLAVOR_REF'] = CONF.compute.flavor_ref
|
||||
|
||||
|
||||
class GlanceGabbiTest(GenericGabbiTest):
|
||||
credentials = ['admin']
|
||||
service_name = 'glance'
|
||||
service_type = 'image'
|
||||
|
||||
|
||||
class PlacementNovaGabbiTest(GenericGabbiTest):
|
||||
credentials = ['admin']
|
||||
service_name = 'nova'
|
||||
service_type = 'multi'
|
||||
|
|
|
@ -12,7 +12,7 @@ tests:
|
|||
GET: /
|
||||
response_json_paths:
|
||||
# $NETLOC contains the /v2.1 prefix
|
||||
$.version.links[?rel = "self"].href: $SCHEME://$NETLOC/
|
||||
$.version.links[?rel = "self"].href: /$ENVIRON['COMPUTE_SERVICE']/
|
||||
$.version.status: CURRENT
|
||||
|
||||
- name: retrieve empty servers
|
||||
|
@ -66,11 +66,11 @@ tests:
|
|||
response_json_paths:
|
||||
$.server.status: ACTIVE
|
||||
|
||||
- name: get bookmark
|
||||
GET: $RESPONSE['$.server.links[?rel = "bookmark"].href']
|
||||
status: 300
|
||||
# bookmark link, whatever it is, is busted. Goes to bad version
|
||||
# - name: get bookmark
|
||||
# GET: $RESPONSE['$.server.links[?rel = "bookmark"].href']
|
||||
|
||||
- name: get 2.1 server via bookmark
|
||||
GET: $RESPONSE['$.choices[?status = "CURRENT"].links[?rel = "self"].href']
|
||||
- name: get server
|
||||
GET: $RESPONSE['$.server.links[?rel = "self"].href']
|
||||
response_json_paths:
|
||||
$.server.name: new-server-one
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
|
||||
defaults:
|
||||
request_headers:
|
||||
x-auth-token: $ENVIRON['SERVICE_TOKEN']
|
||||
content-type: application/json
|
||||
accept: application/json
|
||||
openstack-api-version: 'compute latest, placement latest'
|
||||
|
||||
# These replace full nodes, there is no YAML interpolation
|
||||
# Experimenting with using YAML anchors to avoid repeating long expansions
|
||||
# within the tests.
|
||||
vars:
|
||||
- &cn1_rp $ENVIRON['PLACEMENT_SERVICE']/resource_providers/$HISTORY['list hypervisors'].$RESPONSE['$.hypervisors[0].id']
|
||||
- &cn1_inv $ENVIRON['PLACEMENT_SERVICE']/resource_providers/$HISTORY['list hypervisors'].$RESPONSE['$.hypervisors[0].id']/inventories
|
||||
- &cn1_alloc $ENVIRON['PLACEMENT_SERVICE']/resource_providers/$HISTORY['list hypervisors'].$RESPONSE['$.hypervisors[0].id']/allocations
|
||||
- &cn1_usages $ENVIRON['PLACEMENT_SERVICE']/resource_providers/$HISTORY['list hypervisors'].$RESPONSE['$.hypervisors[0].id']/usages
|
||||
|
||||
- &s1_url $ENVIRON['COMPUTE_SERVICE']/servers/$HISTORY['get server'].$RESPONSE['$.server.id']
|
||||
- &s1_action $ENVIRON['COMPUTE_SERVICE']/servers/$HISTORY['get server'].$RESPONSE['$.server.id']/action
|
||||
- &s1_alloc $ENVIRON['PLACEMENT_SERVICE']/allocations/$HISTORY['get server'].$RESPONSE['$.server.id']
|
||||
|
||||
tests:
|
||||
|
||||
- name: list hypervisors
|
||||
GET: $ENVIRON['COMPUTE_SERVICE']/os-hypervisors
|
||||
response_json_paths:
|
||||
$.hypervisors.`len`: 1
|
||||
|
||||
- name: confirm resource provider
|
||||
GET: *cn1_rp
|
||||
response_json_paths:
|
||||
$.uuid: $RESPONSE['$.hypervisors[0].id']
|
||||
|
||||
- name: confirm inventory
|
||||
GET: *cn1_inv
|
||||
response_json_paths:
|
||||
$.inventories.VCPU.allocation_ratio: 16
|
||||
|
||||
- &cn1_zero
|
||||
name: confirm empty allocation
|
||||
GET: *cn1_alloc
|
||||
response_json_paths:
|
||||
$.allocations.`len`: 0
|
||||
|
||||
- name: create server
|
||||
POST: $ENVIRON['COMPUTE_SERVICE']/servers
|
||||
data:
|
||||
server:
|
||||
name: new-server-one
|
||||
networks: auto
|
||||
imageRef: $ENVIRON['IMAGE_REF']
|
||||
flavorRef: $ENVIRON['FLAVOR_REF']
|
||||
status: 202
|
||||
|
||||
- name: get server
|
||||
GET: $LOCATION
|
||||
|
||||
- name: watch allocations
|
||||
GET: *s1_alloc
|
||||
poll:
|
||||
count: 4
|
||||
delay: 1
|
||||
response_json_paths:
|
||||
$.allocations.["$HISTORY['list hypervisors'].$RESPONSE['$.hypervisors[0].id']"].resources:
|
||||
VCPU: 1
|
||||
MEMORY_MB: 64
|
||||
|
||||
- name: server active
|
||||
GET: *s1_url
|
||||
poll:
|
||||
count: 10
|
||||
delay: .5
|
||||
response_json_paths:
|
||||
$.server.status: ACTIVE
|
||||
|
||||
- name: resize server
|
||||
POST: *s1_action
|
||||
data:
|
||||
resize:
|
||||
flavorRef: $ENVIRON['FLAVOR_REF_ALT']
|
||||
OS-DCF:diskConfig: AUTO
|
||||
status: 202
|
||||
|
||||
- name: wait for verify resize
|
||||
GET: *s1_url
|
||||
poll:
|
||||
count: 12
|
||||
delay: 5
|
||||
response_json_paths:
|
||||
$.server.status: VERIFY_RESIZE
|
||||
|
||||
# These next two fail. We are not managing allocations for local
|
||||
# resize (yet).
|
||||
- name: check for double allocations
|
||||
verbose: True
|
||||
GET: *s1_alloc
|
||||
poll:
|
||||
count: 10
|
||||
delay: 1
|
||||
response_json_paths:
|
||||
$.allocations.["$HISTORY['list hypervisors'].$RESPONSE['$.hypervisors[0].id']"].resources:
|
||||
VCPU: 2
|
||||
MEMORY_MB: 192
|
||||
|
||||
- name: confirm usages pending
|
||||
verbose: True
|
||||
GET: *cn1_usages
|
||||
response_json_paths:
|
||||
$.usages:
|
||||
DISK_GB: 0
|
||||
MEMORY_MB: 192
|
||||
VCPU: 2
|
||||
|
||||
- name: confirm resize
|
||||
POST: *s1_action
|
||||
data:
|
||||
confirmResize: null
|
||||
status: 204
|
||||
|
||||
- name: wait for active
|
||||
GET: *s1_url
|
||||
poll:
|
||||
count: 12
|
||||
delay: 5
|
||||
response_json_paths:
|
||||
$.server.status: ACTIVE
|
||||
|
||||
- name: changed to correct allocations
|
||||
GET: *s1_alloc
|
||||
poll:
|
||||
count: 12
|
||||
delay: 5
|
||||
response_json_paths:
|
||||
$.allocations.["$HISTORY['list hypervisors'].$RESPONSE['$.hypervisors[0].id']"].resources:
|
||||
VCPU: 1
|
||||
MEMORY_MB: 128
|
||||
|
||||
- name: confirm usages active
|
||||
GET: *cn1_usages
|
||||
response_json_paths:
|
||||
$.usages:
|
||||
DISK_GB: 0
|
||||
MEMORY_MB: 128
|
||||
VCPU: 1
|
||||
|
||||
### Clean Up
|
||||
|
||||
- name: delete server
|
||||
DELETE: *s1_url
|
||||
status: 204
|
||||
|
||||
- name: reconfirm empty allocation
|
||||
<<: *cn1_zero
|
||||
poll:
|
||||
count: 10
|
||||
delay: 1
|
Loading…
Reference in New Issue