Add tempest tests for instance creation
Change-Id: I6fc1b8b5f962ab78777821e7812a444ef1f4f7ca
This commit is contained in:
parent
e508d77796
commit
9b84bac67d
@ -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
|
||||
|
@ -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 = {}
|
||||
|
@ -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()
|
||||
|
76
mogan/tests/tempest/api/test_instances.py
Normal file
76
mogan/tests/tempest/api/test_instances.py
Normal 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)
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user