Add basic datamodel list tests

Adds both api and scenario tests for datamodel list
operation. This feature is available since microversion
1.3 but lacks some minimal testing in the plugin

Assisted-By: Cursor (claude-3.5-sonnet)

Change-Id: Ia91d78ee102c3537a25d0eb4d17a4cf2870027fd
Signed-off-by: Douglas Viroel <viroel@gmail.com>
This commit is contained in:
Douglas Viroel
2025-07-29 18:51:10 -03:00
parent ba54aab678
commit a1df4d09be
2 changed files with 156 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
# Copyright 2025 Red Hat, Inc.
#
# 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 import decorators
from tempest.lib import exceptions
from watcher_tempest_plugin.tests.api.admin import base
class TestListDataModel(base.BaseInfraOptimTest):
"""Tests for data models"""
min_microversion = "1.3"
@classmethod
def resource_setup(cls):
super(TestListDataModel, cls).resource_setup()
@decorators.attr(type='smoke')
@decorators.idempotent_id('61b54061-d68c-4179-bb00-d72c97373224')
def test_list_data_models(self):
_, body = self.client.list_data_models()
self.assertIn('context', body)
# NOTE(dviroel): list data model returns at least
# one element for each compute node. But we don't want to
# if there is no enabled compute nodes.
if len(body['context']) > 0:
context_keys = body['context'][0].keys()
# assert that the context has some of the expected fields
# note that since we don't have any instances, we don't have
# server fields available
expected_fields = set([
'node_hostname', 'node_uuid', 'node_vcpus', 'node_memory',
'node_state', 'node_vcpu_ratio', 'node_vcpu_reserved'])
self.assertTrue(expected_fields.issubset(set(context_keys)))
class TestNegativeListDataModel(base.BaseInfraOptimTest):
"""Negative tests for data models"""
min_microversion = "1.3"
@classmethod
def resource_setup(cls):
super(TestNegativeListDataModel, cls).resource_setup()
@decorators.attr(type='smoke')
@decorators.idempotent_id('dd0f7313-e170-4de8-b9ce-840ef3cfdd5f')
def test_list_data_models_storage(self):
self.assertRaises(exceptions.NotFound, self.client.list_data_models,
data_model_type="storage")

View File

@@ -0,0 +1,91 @@
# Copyright 2025 Red Hat, Inc.
#
# 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 import config
from tempest.lib import decorators
from watcher_tempest_plugin.tests.scenario import base
CONF = config.CONF
class TestDataModel(base.BaseInfraOptimScenarioTest):
"""Tests for data models with instances"""
# Minimal version required for _create_one_instance_per_host
compute_min_microversion = base.NOVA_API_VERSION_CREATE_WITH_HOST
# Minimal version required for listing data model
min_microversion = "1.3"
@classmethod
def resource_setup(cls):
super(TestDataModel, cls).resource_setup()
if CONF.compute.min_compute_nodes < 1:
raise cls.skipException(
"Data model tests requires at least 1 compute node, "
"skipping tests.")
enabled_compute_nodes = cls.get_enabled_compute_nodes()
cls.wait_for_compute_node_setup()
if len(enabled_compute_nodes) < 1:
raise cls.skipException(
"Data model tests requires at least 1 enabled compute "
"node, skipping tests.")
@decorators.idempotent_id('dabd41a4-e668-43c8-89a2-3d231e2ed79d')
def test_data_model_with_instances(self):
self.addCleanup(self.wait_delete_instances_from_model)
instances = self._create_one_instance_per_host()
# wait for compute model updates
self.wait_for_instances_in_model(instances)
_, body = self.client.list_data_models(data_model_type="compute")
self.assertEqual(len(instances), len(body['context']))
context_keys = body['context'][0].keys()
# Check some of the fields available in 1.3, including server fields
expected_fields = set([
'node_hostname', 'node_uuid', 'node_vcpus', 'node_memory',
'node_status', 'node_state', 'server_uuid', 'server_state',
'server_vcpus', 'server_memory'])
self.assertTrue(expected_fields.issubset(set(context_keys)))
# Sanity check in content returned by the data model
for instance in instances:
server_ctx = [elem for elem in body['context']
if elem['server_uuid'] == instance['id']][0]
node_details = self.get_hypervisor_details(
instance['OS-EXT-SRV-ATTR:host'])
self.assertEqual(server_ctx['node_hostname'],
node_details['hypervisor_hostname'])
self.assertEqual(server_ctx['node_uuid'], node_details['id'])
self.assertEqual(server_ctx['node_vcpus'], node_details['vcpus'])
self.assertEqual(server_ctx['node_memory'],
node_details['memory_mb'])
self.assertEqual(server_ctx['node_status'], node_details['status'])
self.assertEqual(server_ctx['node_state'], node_details['state'])
self.assertEqual(server_ctx['server_uuid'], instance['id'])
self.assertEqual(server_ctx['server_state'].upper(),
instance['status'].upper())
self.assertEqual(server_ctx['server_vcpus'],
instance['flavor']['vcpus'])
self.assertEqual(server_ctx['server_memory'],
instance['flavor']['ram'])