Add tempest tests for instance creation

Change-Id: I6fc1b8b5f962ab78777821e7812a444ef1f4f7ca
This commit is contained in:
liusheng 2016-11-30 10:53:38 +08:00
parent e508d77796
commit 9b84bac67d
5 changed files with 223 additions and 10 deletions

View File

@ -190,6 +190,10 @@ function update_ironic_node_type {
if is_service_enabled mogan; then
if is_service_enabled tempest; then
iniset $TEMPEST_CONFIG compute fixed_network_name $PRIVATE_NETWORK_NAME
fi
if [[ "$1" == "stack" && "$2" == "install" ]]; then
echo_summary "Installing mogan"
install_mogan

View File

@ -160,7 +160,7 @@ class EngineManager(base_manager.BaseEngineManager):
def create_instance(self, context, instance, requested_networks,
request_spec=None, filter_properties=None):
"""Perform a deployment."""
LOG.debug("Starting instance...")
LOG.debug("Starting instance...", instance=instance)
if filter_properties is None:
filter_properties = {}

View File

@ -13,7 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import time
from mogan.common import exception
from tempest.common.utils import data_utils
from tempest import config
from tempest.lib import exceptions as lib_exc
import tempest.test
@ -26,7 +29,11 @@ CONF = config.CONF
class BaseBaremetalComputeTest(tempest.test.BaseTestCase):
"""Base test case class for all Baremetal Compute API tests."""
credentials = ['primary']
# NOTE(liusheng) because the baremetal sever deployment need some
# network related configurations which configured by ironic. The
# 'private' network is choosed by default, we need to admin user
# to use the 'private' network.
credentials = ['admin']
client_manager = client.Manager
@classmethod
@ -38,13 +45,72 @@ class BaseBaremetalComputeTest(tempest.test.BaseTestCase):
@classmethod
def setup_clients(cls):
super(BaseBaremetalComputeTest, cls).setup_clients()
cls.baremetal_compute_client = cls.os.baremetal_compute_client
cls.baremetal_compute_client = cls.os_admin.baremetal_compute_client
cls.compute_networks_client = cls.os_admin.compute_networks_client
@classmethod
def _get_small_flavor(cls):
types = cls.baremetal_compute_client.list_instance_types()
for t in types:
if t['name'] == 'small':
return t['uuid']
else:
# TODO(liusheng) we shouldn't depend on the default
# type created by devstack
raise exception.InstanceTypeNotFound("'small' type not found.")
@classmethod
def _get_net_id(cls):
for net in cls.compute_networks_client.list_networks()['networks']:
if net['label'] == CONF.compute.fixed_network_name:
return net['id']
else:
raise lib_exc.TempestException('Could not find fixed network!')
@classmethod
def resource_setup(cls):
super(BaseBaremetalComputeTest, cls).resource_setup()
cls.type_ids = []
cls.instance_ids = []
cls.small_flavor = cls._get_small_flavor()
cls.image_id = CONF.compute.image_ref
cls.net_id = cls._get_net_id()
@classmethod
def create_instance(cls, wait_until_active=True):
body = {'name': data_utils.rand_name('mogan_instance'),
'description': "mogan tempest instance",
'instance_type_uuid': cls.small_flavor,
'image_uuid': cls.image_id,
"networks": [{"net_id": cls.net_id}]
}
resp = cls.baremetal_compute_client.create_instance(**body)
cls.instance_ids.append(resp['uuid'])
if wait_until_active:
cls._wait_for_instances_status(resp['uuid'], 'active', 15, 900)
return resp
@classmethod
def _wait_for_instances_status(cls, inst_id, status,
build_interval, build_timeout):
"""Waits for a Instance to reach a given status."""
inst_status = None
start = int(time.time())
while inst_status != status:
time.sleep(build_interval)
body = cls.baremetal_compute_client.show_instance(inst_id)
inst_status = body['status']
if inst_status == 'error' and status != 'error':
msg = ('Failed to provision instance %s' % inst_id)
raise exception.InstanceDeployFailure(msg)
if int(time.time()) - start >= build_timeout:
message = ('Instance %s failed to reach %s status '
'(current %s) within the required time (%s s).' %
(inst_id, status, inst_status,
build_timeout))
raise lib_exc.TimeoutException(message)
@staticmethod
def cleanup_resources(method, list_of_ids):
@ -58,7 +124,6 @@ class BaseBaremetalComputeTest(tempest.test.BaseTestCase):
def resource_cleanup(cls):
cls.cleanup_resources(
cls.baremetal_compute_client.delete_instance_type, cls.type_ids)
# TODO(liusheng)
# cls.cleanup_resources(cls.baremetal_compute_client.delete_instance,
# cls.instance_ids)
cls.cleanup_resources(cls.baremetal_compute_client.delete_instance,
cls.instance_ids)
super(BaseBaremetalComputeTest, cls).resource_cleanup()

View File

@ -0,0 +1,76 @@
#
# Copyright 2016 Huawei Technologies Co., Ltd.
#
# 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 time
from mogan.tests.tempest.api import base
class BaremetalComputeAPIInstancesTest(base.BaseBaremetalComputeTest):
def test_instance_all_cases(self):
# NOTE(liusheng) Since the mogan server deployment is a
# time-consuming operation and the ironic resource cleanup
# will be performed after a server deleted, we'd better to
# put all test cases in a test
# Test post
resp = self.create_instance()
self.assertEqual(self.instance_ids[0], resp['uuid'])
self.assertEqual('building', resp['status'])
self.assertEqual(self.small_flavor, resp['instance_type_uuid'])
self.assertEqual('mogan tempest instance', resp['description'])
self.assertEqual(self.image_id, resp['image_uuid'])
self.assertIn('launched_at', resp)
self.assertIn('updated_at', resp)
self.assertIn('extra', resp)
self.assertIn('links', resp)
self.assertIn('project_id', resp)
self.assertIn('user_id', resp)
self.assertIn('availability_zone', resp)
self.assertIn('network_info', resp)
self.assertIn('name', resp)
# Test show
resp = self.baremetal_compute_client.show_instance(
self.instance_ids[0])
self.assertEqual('active', resp['status'])
self.assertEqual(self.small_flavor, resp['instance_type_uuid'])
self.assertEqual('mogan tempest instance', resp['description'])
self.assertEqual(self.image_id, resp['image_uuid'])
self.assertEqual('power on', resp['power_state'])
self.assertIn('launched_at', resp)
self.assertIn('updated_at', resp)
self.assertIn('extra', resp)
self.assertIn('links', resp)
self.assertIn('project_id', resp)
self.assertIn('user_id', resp)
self.assertIn('availability_zone', resp)
self.assertIn('network_info', resp)
self.assertIn('name', resp)
# Test list
resp = self.baremetal_compute_client.list_instances()
self.assertEqual(1, len(resp))
self.assertEqual(self.instance_ids[0], resp[0]['uuid'])
self.assertEqual('active', resp[0]['status'])
self.assertIn('name', resp[0])
self.assertEqual('mogan tempest instance', resp[0]['description'])
self.assertIn('links', resp[0])
# Test delete
self.baremetal_compute_client.delete_instance(
self.instance_ids[0])
self.instance_ids.remove(self.instance_ids[0])
# FIXME(liusheng) time to wait for deleting completed
time.sleep(180)

View File

@ -16,6 +16,8 @@
from oslo_serialization import jsonutils as json
from tempest import config
from tempest.lib.common import rest_client
from tempest.lib.services.compute import networks_client as network_cli
from tempest.lib.services.image.v2 import images_client as image_cli
from tempest import manager
CONF = config.CONF
@ -64,8 +66,45 @@ class BaremetalComputeClient(rest_client.RestClient):
body = self.deserialize(body)
return rest_client.ResponseBody(resp, body)
def create_instance(self, **kwargs):
uri = "%s/instances" % self.uri_prefix
body = self.serialize(kwargs)
resp, body = self.post(uri, body)
self.expected_success(201, resp.status)
body = self.deserialize(body)
return rest_client.ResponseBody(resp, body)
def list_instances(self):
uri = '%s/instances' % self.uri_prefix
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)['instances']
return rest_client.ResponseBodyList(resp, body)
def show_instance(self, instance_id):
uri = '%s/instances/%s' % (self.uri_prefix, instance_id)
resp, body = self.get(uri)
self.expected_success(200, resp.status)
body = self.deserialize(body)
return rest_client.ResponseBody(resp, body)
def delete_instance(self, instance_id):
uri = "%s/instances/%s" % (self.uri_prefix, instance_id)
resp, body = self.delete(uri)
self.expected_success(204, resp.status)
if body:
body = self.deserialize(body)
return rest_client.ResponseBody(resp, body)
class Manager(manager.Manager):
load_clients = [
'baremetal_compute_client',
'compute_networks_client',
'image_client_v2',
]
default_params = {
'disable_ssl_certificate_validation':
CONF.identity.disable_ssl_certificate_validation,
@ -73,17 +112,46 @@ class Manager(manager.Manager):
'trace_requests': CONF.debug.trace_requests
}
alarming_params = {
baremetal_compute_params = {
'service': CONF.baremetal_compute_plugin.catalog_type,
'region': CONF.identity.region,
'endpoint_type': CONF.baremetal_compute_plugin.endpoint_type,
}
alarming_params.update(default_params)
baremetal_compute_params.update(default_params)
compute_params = {
'service': CONF.compute.catalog_type,
'region': CONF.compute.region or CONF.identity.region,
'endpoint_type': CONF.compute.endpoint_type,
'build_interval': CONF.compute.build_interval,
'build_timeout': CONF.compute.build_timeout,
}
compute_params.update(default_params)
image_params = {
'service': CONF.image.catalog_type,
'region': CONF.image.region or CONF.identity.region,
'endpoint_type': CONF.image.endpoint_type,
'build_interval': CONF.image.build_interval,
'build_timeout': CONF.image.build_timeout,
}
image_params.update(default_params)
def __init__(self, credentials=None, service=None):
super(Manager, self).__init__(credentials)
self.set_baremetal_compute_client()
for client in self.load_clients:
getattr(self, 'set_%s' % client)()
def set_baremetal_compute_client(self):
self.baremetal_compute_client = BaremetalComputeClient(
self.auth_provider, **self.alarming_params)
self.auth_provider, **self.baremetal_compute_params)
def set_compute_networks_client(self):
self.compute_networks_client = network_cli.NetworksClient(
self.auth_provider,
**self.compute_params)
def set_image_client_v2(self):
self.image_client_v2 = image_cli.ImagesClient(
self.auth_provider,
**self.image_params)