
When resource creation failed, the region's error message is retrieved and included as part of the tempest exception message. Change-Id: I6309b29ad516651b9a89ffe54763d11fb56949a4
365 lines
14 KiB
Python
Executable File
365 lines
14 KiB
Python
Executable File
# Copyright 2016 AT&T Corp
|
|
# 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 random
|
|
import time
|
|
import uuid
|
|
|
|
from oslo_log import log as logging
|
|
from ranger_tempest_plugin.tests.api import base
|
|
|
|
from tempest import config
|
|
from tempest.lib import exceptions
|
|
from tempest.lib.common.utils import data_utils
|
|
|
|
CONF = config.CONF
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
|
|
class FmsBaseOrmTest(base.BaseOrmTest):
|
|
credentials = ['admin', 'primary', 'alt']
|
|
|
|
@classmethod
|
|
def setup_clients(cls):
|
|
super(FmsBaseOrmTest, cls).setup_clients()
|
|
cls.client = cls.os_primary.fms_client
|
|
cls.flavors_client = cls.os_admin.flavors_client
|
|
cls.rms_client = cls.os_primary.rms_client
|
|
cls.cms_client = cls.os_primary.cms_client
|
|
|
|
@classmethod
|
|
def resource_setup(cls):
|
|
super(FmsBaseOrmTest, cls).resource_setup()
|
|
cls.tenant_id = None
|
|
cls.alt_tenant_id = None
|
|
|
|
@classmethod
|
|
def resource_cleanup(cls):
|
|
super(FmsBaseOrmTest, cls).resource_cleanup()
|
|
|
|
@classmethod
|
|
def _create_customer(cls):
|
|
cust = {}
|
|
cust['description'] = ''
|
|
cust['enabled'] = True
|
|
cust['name'] = data_utils.rand_name('ormTempestFms')
|
|
cust['regions'] = [{'name': CONF.identity.region, 'type': 'single'}]
|
|
cust['defaultQuotas'] = []
|
|
cust['users'] = []
|
|
cust['uuid'] = uuid.uuid4().hex
|
|
|
|
_, body = cls.cms_client.create_customer(**cust)
|
|
customer_id = body["customer"]["id"]
|
|
_, customer = cls.cms_client.get_customer(customer_id)
|
|
|
|
if customer["name"] != cust["name"]:
|
|
message = "Customer %s creation FAILED" % cust["name"]
|
|
exceptions.TempestException(message)
|
|
|
|
customer_status = customer["status"]
|
|
expected_status = 'Success'
|
|
start = int(time.time())
|
|
while customer_status != expected_status:
|
|
time.sleep(cls.build_interval)
|
|
_, customer = cls.cms_client.get_customer(customer_id)
|
|
customer_status = customer["status"]
|
|
|
|
if customer_status == 'Error':
|
|
message = ""
|
|
for region in customer["regions"]:
|
|
if "error_message" in region:
|
|
message += "Region %s Error: %s. " % (
|
|
region["name"], region["error_message"])
|
|
|
|
if not message:
|
|
message = ('Customer %s failed to reach %s status and is'
|
|
' in ERROR status' % (customer_id,
|
|
expected_status))
|
|
raise exceptions.ServerFault(message)
|
|
|
|
if int(time.time()) - start >= cls.build_timeout:
|
|
message = ('Customer %s failed to reach %s'
|
|
'status within the required time (%s s) '
|
|
'and is in %s status.'
|
|
% (customer_id, expected_status,
|
|
cls.build_timeout,
|
|
customer_status))
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
return customer_id
|
|
|
|
@classmethod
|
|
def _del_cust_validate_deletion_on_dcp_and_lcp(cls, customer_id):
|
|
_, customer = cls.cms_client.get_customer(customer_id)
|
|
regions_on_customer = \
|
|
[region['name'] for region in customer["regions"]]
|
|
|
|
for region in regions_on_customer:
|
|
cls.cms_client.delete_region_from_customer(customer_id, region)
|
|
|
|
time.sleep(cls.build_timeout)
|
|
_, body = cls.cms_client.get_customer(customer_id)
|
|
|
|
if len(body['regions']) != 0:
|
|
message = \
|
|
'Failed to delete regions for customer %s' % customer_id
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
cls.cms_client.delete_customer(customer_id)
|
|
cls._validate_customer_deletion_on_lcp(customer_id)
|
|
|
|
@classmethod
|
|
def _validate_customer_deletion_on_lcp(cls, customer_id):
|
|
body = cls.project_client.list_projects()["projects"]
|
|
customer_ids = [customer["id"]
|
|
for customer in body
|
|
if customer["id"] == customer_id]
|
|
if customer_ids:
|
|
message = "customer %s failed to get deleted on lcp" \
|
|
% customer_id
|
|
raise exceptions.TempestException(message)
|
|
|
|
@classmethod
|
|
def _get_flavor_params(cls, set_region=True, single_tenant=True,
|
|
public=False):
|
|
post_body, region = {}, {}
|
|
region["name"] = CONF.identity.region
|
|
ram = random.randint(1, 4) * 1024
|
|
swap = random.randint(1, 40) * 1024
|
|
vcpus = random.randint(2, 36)
|
|
disk = random.randint(2, 102)
|
|
post_body['id'] = uuid.uuid4().hex
|
|
post_body["description"] = \
|
|
"orm-plugin-BaseORMTest-flavor"
|
|
post_body["series"] = random.choice(CONF.ranger.flavor_series)
|
|
post_body["alias"] = "flavor_alias"
|
|
post_body["ram"] = str(ram)
|
|
post_body["vcpus"] = str(vcpus)
|
|
post_body["disk"] = str(disk)
|
|
post_body["swap"] = str(swap)
|
|
post_body["ephemeral"] = "1024"
|
|
post_body["regions"] = [region] if set_region else []
|
|
post_body["visibility"] = "private" if not public else "public"
|
|
post_body['tag'] = {'a': 'b', 'c': 'd'}
|
|
|
|
if public:
|
|
post_body["tenants"] = []
|
|
else:
|
|
if single_tenant:
|
|
post_body["tenants"] = [cls.tenant_id]
|
|
else:
|
|
post_body["tenants"] = [cls.tenant_id, cls.alt_tenant_id]
|
|
|
|
return post_body
|
|
|
|
@classmethod
|
|
def _create_flv_and_validate_creation_on_dcp_and_lcp(cls, **kwargs):
|
|
"""kwargs contain all field data needed in a flavor POST body:
|
|
|
|
- name
|
|
- description
|
|
- alias
|
|
- ram
|
|
- vcpus
|
|
- disk
|
|
- swap
|
|
- ephemeral
|
|
- regions
|
|
- visibility
|
|
- tenants
|
|
"""
|
|
_, body = cls.client.create_flavor(**kwargs)
|
|
flavor = body["flavor"]
|
|
flavor_id = flavor["id"]
|
|
|
|
_, body = cls.client.get_flavor(flavor_id)
|
|
flavor_detail = body["flavor"]
|
|
|
|
if flavor_detail["vcpus"] != kwargs["vcpus"]:
|
|
message = "Flavor %s not created successfully" % flavor_id
|
|
raise exceptions.TempestException(message)
|
|
|
|
if flavor_detail["regions"] != []:
|
|
flavor_id = flavor_detail["id"]
|
|
cls._wait_for_flavor_status_on_dcp(flavor_id, 'Success')
|
|
cls._validate_flavor_creation_on_lcp(flavor_id)
|
|
|
|
return flavor
|
|
|
|
@classmethod
|
|
def _wait_for_flavor_status_on_dcp(cls, flavor_id, status):
|
|
_, body = cls.client.get_flavor(flavor_id)
|
|
flavor = body["flavor"]
|
|
flavor_status = flavor["status"]
|
|
start = int(time.time())
|
|
while flavor_status != status:
|
|
time.sleep(cls.build_interval)
|
|
_, body = cls.client.get_flavor(flavor_id)
|
|
flavor = body["flavor"]
|
|
flavor_status = flavor["status"]
|
|
|
|
if flavor_status == 'Error':
|
|
# Some test cases have multiple regions
|
|
message = ""
|
|
for region in flavor["regions"]:
|
|
if "error_message" in region:
|
|
message += "Region %s Error: %s. " % (
|
|
region["name"], region["error_message"])
|
|
|
|
if not message:
|
|
message = ('Flavor %s failed to reach %s status'
|
|
' and is in ERROR status' % (flavor_id, status))
|
|
raise exceptions.ServerFault(message)
|
|
|
|
if int(time.time()) - start >= cls.build_timeout:
|
|
message = ('Flavor %s failed to reach %s status within'
|
|
' the required time (%s s) and is in'
|
|
' %s status.') % (flavor_id, status,
|
|
cls.build_timeout,
|
|
flavor_status)
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
@classmethod
|
|
def _validate_flavor_creation_on_lcp(cls, flavor_id):
|
|
_, body = cls.client.list_flavors()
|
|
flavor = [flavor["id"] for flavor in body["flavors"]
|
|
if flavor["id"] == flavor_id]
|
|
if not flavor:
|
|
message = "flavor %s not in nova flavor list" % flavor_id
|
|
raise exceptions.TempestException(message)
|
|
|
|
@classmethod
|
|
def _validate_flv_extraspecs_on_dcp_and_lcp(cls, flavor_id,
|
|
expected_specs):
|
|
expected_specs_count = len(expected_specs)
|
|
_, body = cls.client.get_flavor(flavor_id)
|
|
flavor_orm = body["flavor"]
|
|
flavor_lcp = cls.flavors_client.show_flavor(flavor_id)["flavor"]
|
|
|
|
def _validate_extra_specs(flv):
|
|
actual_specs_count = 0
|
|
actual_specs = {}
|
|
for spec in flv["extra-specs"]:
|
|
actual_specs[spec] = flv["extra-specs"][spec]
|
|
for spec in expected_specs:
|
|
if spec in actual_specs:
|
|
if expected_specs[spec] == actual_specs[spec]:
|
|
actual_specs_count += 1
|
|
return bool(expected_specs_count == actual_specs_count)
|
|
return bool(_validate_extra_specs(flavor_orm)
|
|
and _validate_extra_specs(flavor_lcp))
|
|
|
|
@classmethod
|
|
def _del_flv_and_validate_deletion_on_dcp_and_lcp(cls, flavor_id):
|
|
_, body = cls.client.get_flavor(flavor_id)
|
|
regions_on_flavor = \
|
|
[region['name'] for region in body["flavor"]["regions"]]
|
|
for regs in regions_on_flavor:
|
|
cls._delete_region_from_flavor_and_validate_deletion(
|
|
flavor_id, regs)
|
|
cls.client.delete_flavor(flavor_id)
|
|
cls._wait_for_flavor_deletion_on_dcp(flavor_id)
|
|
cls._validate_flavor_deletion_on_lcp(flavor_id)
|
|
|
|
@classmethod
|
|
def _delete_region_from_flavor_and_validate_deletion(
|
|
cls, flavor_id, rname):
|
|
cls.client.delete_region_from_flavor(flavor_id, rname)
|
|
|
|
_, body = cls.client.get_flavor(flavor_id)
|
|
loopcount = 0
|
|
|
|
while loopcount < 10:
|
|
if len(body['flavor']['regions']) == 0:
|
|
break
|
|
for regions_on_flavor in body['flavor']['regions']:
|
|
if regions_on_flavor['name'] == rname:
|
|
time.sleep(cls.build_interval)
|
|
_, body = cls.client.get_flavor(flavor_id)
|
|
break
|
|
loopcount += 1
|
|
|
|
for regions_on_flavor in body['flavor']['regions']:
|
|
if regions_on_flavor['name'] == rname:
|
|
message = \
|
|
'Region {} failed to get deleted from flavor {}' \
|
|
.format(rname, flavor_id)
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
@classmethod
|
|
def _wait_for_flavor_deletion_on_dcp(cls, flavor_id):
|
|
_, body = cls.client.list_flavors()
|
|
flavor_ids = [flavor["id"] for flavor in body["flavors"]
|
|
if flavor["id"] == flavor_id]
|
|
start = int(time.time())
|
|
while flavor_ids:
|
|
time.sleep(cls.build_interval)
|
|
_, body = cls.client.list_flavors()
|
|
flavor_ids = [flavor["id"] for flavor in body["flavors"]
|
|
if flavor["id"] == flavor_id]
|
|
if flavor_ids:
|
|
flavor_status = flavor_ids[0]["status"]
|
|
if flavor_status == 'Error':
|
|
message = \
|
|
('Flavor %s failed to get deleted'
|
|
'and is in error status') % flavor_id
|
|
raise exceptions.TempestException(message)
|
|
if int(time.time()) - start >= cls.build_timeout:
|
|
message = (
|
|
'flavor %s failed to get deleted within '
|
|
'the required time (%s s) and is in %s status.'
|
|
% (flavor_id, cls.build_timeout, flavor_status))
|
|
raise exceptions.TimeoutException(message)
|
|
|
|
@classmethod
|
|
def _validate_flavor_deletion_on_lcp(cls, flavor_id):
|
|
body = cls.flavors_client.list_flavors()["flavors"]
|
|
flavor_ids = [flavor["id"] for flavor in body]
|
|
|
|
if flavor_id in flavor_ids:
|
|
flavor_status = cls.flavors_client.show_flavor(
|
|
flavor_id)["flavor"]["status"]
|
|
message = "flavor %s failed to get deleted and is in %s status" \
|
|
% (flavor_id, flavor_status)
|
|
raise exceptions.TempestException(message)
|
|
|
|
@classmethod
|
|
def _get_project_id(cls, project_name):
|
|
body = cls.project_client.list_projects()
|
|
for project in body["projects"]:
|
|
if(project["name"] == project_name):
|
|
return project["id"]
|
|
message = ('project %s not found on projects list' % project_name)
|
|
raise exceptions.TempestException(message)
|
|
|
|
@classmethod
|
|
def _get_expected_flavor_name(cls, post_body):
|
|
name = post_body["series"] + "." + "c" + \
|
|
post_body["vcpus"] + "r" + \
|
|
str(int(post_body["ram"]) // 1024) \
|
|
+ "d" + post_body["disk"] + "s" + \
|
|
str(int(post_body["swap"]) // 1024) \
|
|
+ "e" + str(int(post_body["ephemeral"]) // 1024)
|
|
return name
|
|
|
|
@classmethod
|
|
def _validate_flv_geometry_on_lcp(cls, flavor_id, post_body):
|
|
flv = cls.flavors_client.show_flavor(flavor_id)["flavor"]
|
|
return bool(flv["vcpus"] == int(post_body["vcpus"])
|
|
and flv["ram"] == post_body["ram"]
|
|
and flv["swap"] == int(post_body["swap"])
|
|
and flv["disk"] == int(post_body["disk"])
|
|
and flv["ephemeral"] == post_body["ephemeral"])
|