From d7e18416805f699f9e259f30a9f98aa06ccb9499 Mon Sep 17 00:00:00 2001 From: "John L. Villalovos" Date: Wed, 13 Dec 2017 08:57:20 -0800 Subject: [PATCH] Remove ironic_inspector/test/inspector_tempest_plugin/ directory We now use the project openstack/ironic-tempest-plugin to store our tempest plugin. All content from the ironic_inspector/test/inspector_tempest_plugin/ directory has been ported to that project. We no longer want to have the plugin content stored here so we can now delete it. Change-Id: Ia8ea3a74d5aba1ea27eb6715c21667a30bac56b4 --- .../test/inspector_tempest_plugin/README.rst | 18 -- .../test/inspector_tempest_plugin/__init__.py | 0 .../test/inspector_tempest_plugin/config.py | 66 ----- .../inspector_tempest_plugin/exceptions.py | 25 -- .../test/inspector_tempest_plugin/plugin.py | 41 --- .../rules/basic_ops_rule.json | 25 -- .../services/__init__.py | 0 .../services/introspection_client.py | 83 ------ .../tests/__init__.py | 0 .../inspector_tempest_plugin/tests/manager.py | 243 ------------------ .../tests/test_basic.py | 176 ------------- .../tests/test_discovery.py | 149 ----------- ...mpest_plugin_removal-91a01f5950f543e1.yaml | 10 + setup.cfg | 3 - 14 files changed, 10 insertions(+), 829 deletions(-) delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/README.rst delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/__init__.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/config.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/exceptions.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/plugin.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/rules/basic_ops_rule.json delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/services/__init__.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/services/introspection_client.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/tests/__init__.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/tests/manager.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/tests/test_basic.py delete mode 100644 ironic_inspector/test/inspector_tempest_plugin/tests/test_discovery.py create mode 100644 releasenotes/notes/tempest_plugin_removal-91a01f5950f543e1.yaml diff --git a/ironic_inspector/test/inspector_tempest_plugin/README.rst b/ironic_inspector/test/inspector_tempest_plugin/README.rst deleted file mode 100644 index 0ea008c42..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/README.rst +++ /dev/null @@ -1,18 +0,0 @@ -======================================= -Tempest Integration of ironic-inspector -======================================= - -This directory contains Tempest tests to cover the ironic-inspector project. - -It uses tempest plugin to automatically load these tests into tempest. More -information about tempest plugin could be found here: -`Plugin `_ - -The legacy method of running Tempest is to just treat the Tempest source code -as a python unittest: -`Run tests `_ - -There is also tox configuration for tempest, use following regex for running -introspection tests:: - - $ tox -e all-plugin -- inspector_tempest_plugin diff --git a/ironic_inspector/test/inspector_tempest_plugin/__init__.py b/ironic_inspector/test/inspector_tempest_plugin/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ironic_inspector/test/inspector_tempest_plugin/config.py b/ironic_inspector/test/inspector_tempest_plugin/config.py deleted file mode 100644 index e58690030..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/config.py +++ /dev/null @@ -1,66 +0,0 @@ -# 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 oslo_config import cfg - -service_option = cfg.BoolOpt("ironic-inspector", - default=True, - help="Whether or not ironic-inspector is expected" - " to be available") - -baremetal_introspection_group = cfg.OptGroup( - name="baremetal_introspection", - title="Baremetal introspection service options", - help="When enabling baremetal introspection tests," - "Ironic must be configured.") - -BaremetalIntrospectionGroup = [ - cfg.StrOpt('catalog_type', - default='baremetal-introspection', - help="Catalog type of the baremetal provisioning service"), - cfg.StrOpt('endpoint_type', - default='publicURL', - choices=['public', 'admin', 'internal', - 'publicURL', 'adminURL', 'internalURL'], - help="The endpoint type to use for the baremetal introspection" - " service"), - cfg.IntOpt('introspection_sleep', - default=30, - help="Introspection sleep before check status"), - cfg.IntOpt('introspection_timeout', - default=600, - help="Introspection time out"), - cfg.IntOpt('hypervisor_update_sleep', - default=60, - help="Time to wait until nova becomes aware of " - "bare metal instances"), - cfg.IntOpt('hypervisor_update_timeout', - default=300, - help="Time out for wait until nova becomes aware of " - "bare metal instances"), - # NOTE(aarefiev): status_check_period default is 60s, but checking - # node state takes some time(API call), so races appear here, - # 80s would be enough to make one more check. - cfg.IntOpt('ironic_sync_timeout', - default=80, - help="Time it might take for Ironic--Inspector " - "sync to happen"), - cfg.IntOpt('discovery_timeout', - default=300, - help="Time to wait until new node would enrolled in " - "ironic"), - cfg.BoolOpt('auto_discovery_feature', - default=False, - help="Is the auto-discovery feature enabled. Enroll hook " - "should be specified in node_not_found_hook - processing " - "section of inspector.conf"), -] diff --git a/ironic_inspector/test/inspector_tempest_plugin/exceptions.py b/ironic_inspector/test/inspector_tempest_plugin/exceptions.py deleted file mode 100644 index ac08d54ac..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/exceptions.py +++ /dev/null @@ -1,25 +0,0 @@ -# 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 exceptions - - -class IntrospectionFailed(exceptions.TempestException): - message = "Introspection failed" - - -class IntrospectionTimeout(exceptions.TempestException): - message = "Introspection time out" - - -class HypervisorUpdateTimeout(exceptions.TempestException): - message = "Hypervisor stats update time out" diff --git a/ironic_inspector/test/inspector_tempest_plugin/plugin.py b/ironic_inspector/test/inspector_tempest_plugin/plugin.py deleted file mode 100644 index 0428c7d25..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/plugin.py +++ /dev/null @@ -1,41 +0,0 @@ -# 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 os - -from tempest.test_discover import plugins - -from ironic_inspector.test.inspector_tempest_plugin import config - - -class InspectorTempestPlugin(plugins.TempestPlugin): - def load_tests(self): - base_path = os.path.split(os.path.dirname( - os.path.abspath(__file__)))[0] - test_dir = "inspector_tempest_plugin/tests" - full_test_dir = os.path.join(base_path, test_dir) - return full_test_dir, base_path - - def register_opts(self, conf): - conf.register_opt(config.service_option, - group='service_available') - conf.register_group(config.baremetal_introspection_group) - conf.register_opts(config.BaremetalIntrospectionGroup, - group="baremetal_introspection") - - def get_opt_lists(self): - return [ - (config.baremetal_introspection_group.name, - config.BaremetalIntrospectionGroup), - ('service_available', [config.service_option]) - ] diff --git a/ironic_inspector/test/inspector_tempest_plugin/rules/basic_ops_rule.json b/ironic_inspector/test/inspector_tempest_plugin/rules/basic_ops_rule.json deleted file mode 100644 index f1cfb0b2a..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/rules/basic_ops_rule.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "description": "Successful Rule", - "conditions": [ - {"op": "ge", "field": "memory_mb", "value": 256}, - {"op": "ge", "field": "local_gb", "value": 1} - ], - "actions": [ - {"action": "set-attribute", "path": "/extra/rule_success", - "value": "yes"} - ] - }, - { - "description": "Failing Rule", - "conditions": [ - {"op": "lt", "field": "memory_mb", "value": 42}, - {"op": "eq", "field": "local_gb", "value": 0} - ], - "actions": [ - {"action": "set-attribute", "path": "/extra/rule_success", - "value": "no"}, - {"action": "fail", "message": "This rule should not have run"} - ] - } -] diff --git a/ironic_inspector/test/inspector_tempest_plugin/services/__init__.py b/ironic_inspector/test/inspector_tempest_plugin/services/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ironic_inspector/test/inspector_tempest_plugin/services/introspection_client.py b/ironic_inspector/test/inspector_tempest_plugin/services/introspection_client.py deleted file mode 100644 index 3b1a75bd8..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/services/introspection_client.py +++ /dev/null @@ -1,83 +0,0 @@ -# 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 ironic_tempest_plugin.services.baremetal import base -from tempest import clients -from tempest.common import credentials_factory as common_creds -from tempest import config - - -CONF = config.CONF -ADMIN_CREDS = common_creds.get_configured_admin_credentials() - - -class Manager(clients.Manager): - def __init__(self, - credentials=ADMIN_CREDS, - api_microversions=None): - super(Manager, self).__init__(credentials) - self.introspection_client = BaremetalIntrospectionClient( - self.auth_provider, - CONF.baremetal_introspection.catalog_type, - CONF.identity.region, - endpoint_type=CONF.baremetal_introspection.endpoint_type) - - -class BaremetalIntrospectionClient(base.BaremetalClient): - """Base Tempest REST client for Ironic Inspector API v1.""" - version = '1' - uri_prefix = 'v1' - - @base.handle_errors - def purge_rules(self): - """Purge all existing rules.""" - return self._delete_request('rules', uuid=None) - - @base.handle_errors - def create_rules(self, rules): - """Create introspection rules.""" - if not isinstance(rules, list): - rules = [rules] - for rule in rules: - self._create_request('rules', rule) - - @base.handle_errors - def get_status(self, uuid): - """Get introspection status for a node.""" - return self._show_request('introspection', uuid=uuid) - - @base.handle_errors - def get_data(self, uuid): - """Get introspection data for a node.""" - return self._show_request('introspection', uuid=uuid, - uri='/%s/introspection/%s/data' % - (self.uri_prefix, uuid)) - - @base.handle_errors - def start_introspection(self, uuid): - """Start introspection for a node.""" - resp, _body = self.post(url=('/%s/introspection/%s' % - (self.uri_prefix, uuid)), - body=None) - self.expected_success(202, resp.status) - - return resp - - @base.handle_errors - def abort_introspection(self, uuid): - """Abort introspection for a node.""" - resp, _body = self.post(url=('/%s/introspection/%s/abort' % - (self.uri_prefix, uuid)), - body=None) - self.expected_success(202, resp.status) - - return resp diff --git a/ironic_inspector/test/inspector_tempest_plugin/tests/__init__.py b/ironic_inspector/test/inspector_tempest_plugin/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/ironic_inspector/test/inspector_tempest_plugin/tests/manager.py b/ironic_inspector/test/inspector_tempest_plugin/tests/manager.py deleted file mode 100644 index e6eb38922..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/tests/manager.py +++ /dev/null @@ -1,243 +0,0 @@ -# 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 json -import os -import time - -from ironic_tempest_plugin.tests.api.admin.api_microversion_fixture import \ - APIMicroversionFixture as IronicMicroversionFixture -from ironic_tempest_plugin.tests.scenario.baremetal_manager import \ - BaremetalProvisionStates -from ironic_tempest_plugin.tests.scenario.baremetal_manager import \ - BaremetalScenarioTest -import six -import tempest -from tempest import config -from tempest.lib.common.api_version_utils import LATEST_MICROVERSION -from tempest.lib.common.utils import test_utils -from tempest.lib import exceptions as lib_exc - -from ironic_inspector.test.inspector_tempest_plugin import exceptions -from ironic_inspector.test.inspector_tempest_plugin.services import \ - introspection_client - -CONF = config.CONF - - -class InspectorScenarioTest(BaremetalScenarioTest): - """Provide harness to do Inspector scenario tests.""" - - wait_provisioning_state_interval = 15 - - credentials = ['primary', 'admin'] - - ironic_api_version = LATEST_MICROVERSION - - @classmethod - def setup_clients(cls): - super(InspectorScenarioTest, cls).setup_clients() - inspector_manager = introspection_client.Manager() - cls.introspection_client = inspector_manager.introspection_client - - def setUp(self): - super(InspectorScenarioTest, self).setUp() - # we rely on the 'available' provision_state; using latest - # microversion - self.useFixture(IronicMicroversionFixture(self.ironic_api_version)) - self.flavor = self.baremetal_flavor() - self.node_ids = {node['uuid'] for node in - self.node_filter(filter=lambda node: - node['provision_state'] == - BaremetalProvisionStates.AVAILABLE)} - self.rule_purge() - - def item_filter(self, list_method, show_method, - filter=lambda item: True, items=None): - if items is None: - items = [show_method(item['uuid']) for item in - list_method()] - return [item for item in items if filter(item)] - - def node_list(self): - return self.baremetal_client.list_nodes()[1]['nodes'] - - def node_port_list(self, node_uuid): - return self.baremetal_client.list_node_ports(node_uuid)[1]['ports'] - - def node_update(self, uuid, patch): - return self.baremetal_client.update_node(uuid, **patch) - - def node_show(self, uuid): - return self.baremetal_client.show_node(uuid)[1] - - def node_delete(self, uuid): - return self.baremetal_client.delete_node(uuid) - - def node_filter(self, filter=lambda node: True, nodes=None): - return self.item_filter(self.node_list, self.node_show, - filter=filter, items=nodes) - - def node_set_power_state(self, uuid, state): - self.baremetal_client.set_node_power_state(uuid, state) - - def node_set_provision_state(self, uuid, state): - self.baremetal_client.set_node_provision_state(self, uuid, state) - - def hypervisor_stats(self): - return (self.os_admin.hypervisor_client. - show_hypervisor_statistics()) - - def server_show(self, uuid): - self.servers_client.show_server(uuid) - - def rule_purge(self): - self.introspection_client.purge_rules() - - def rule_import(self, rule_path): - with open(rule_path, 'r') as fp: - rules = json.load(fp) - self.introspection_client.create_rules(rules) - - def rule_import_from_dict(self, rules): - self.introspection_client.create_rules(rules) - - def introspection_status(self, uuid): - return self.introspection_client.get_status(uuid)[1] - - def introspection_data(self, uuid): - return self.introspection_client.get_data(uuid)[1] - - def introspection_start(self, uuid): - return self.introspection_client.start_introspection(uuid) - - def introspection_abort(self, uuid): - return self.introspection_client.abort_introspection(uuid) - - def baremetal_flavor(self): - flavor_id = CONF.compute.flavor_ref - flavor = self.flavors_client.show_flavor(flavor_id)['flavor'] - flavor['properties'] = self.flavors_client.list_flavor_extra_specs( - flavor_id)['extra_specs'] - return flavor - - def get_rule_path(self, rule_file): - base_path = os.path.split( - os.path.dirname(os.path.abspath(__file__)))[0] - base_path = os.path.split(base_path)[0] - return os.path.join(base_path, "inspector_tempest_plugin", - "rules", rule_file) - - def boot_instance(self): - return super(InspectorScenarioTest, self).boot_instance() - - def terminate_instance(self, instance): - return super(InspectorScenarioTest, self).terminate_instance(instance) - - def wait_for_node(self, node_name): - def check_node(): - try: - self.node_show(node_name) - except lib_exc.NotFound: - return False - return True - - if not test_utils.call_until_true( - check_node, - duration=CONF.baremetal_introspection.discovery_timeout, - sleep_for=20): - msg = ("Timed out waiting for node %s " % node_name) - raise lib_exc.TimeoutException(msg) - - inspected_node = self.node_show(self.node_info['name']) - self.wait_for_introspection_finished(inspected_node['uuid']) - - # TODO(aarefiev): switch to call_until_true - def wait_for_introspection_finished(self, node_ids): - """Waits for introspection of baremetal nodes to finish. - - """ - if isinstance(node_ids, six.text_type): - node_ids = [node_ids] - start = int(time.time()) - not_introspected = {node_id for node_id in node_ids} - - while not_introspected: - time.sleep(CONF.baremetal_introspection.introspection_sleep) - for node_id in node_ids: - status = self.introspection_status(node_id) - if status['finished']: - if status['error']: - message = ('Node %(node_id)s introspection failed ' - 'with %(error)s.' % - {'node_id': node_id, - 'error': status['error']}) - raise exceptions.IntrospectionFailed(message) - not_introspected = not_introspected - {node_id} - - if (int(time.time()) - start >= - CONF.baremetal_introspection.introspection_timeout): - message = ('Introspection timed out for nodes: %s' % - not_introspected) - raise exceptions.IntrospectionTimeout(message) - - def wait_for_nova_aware_of_bvms(self): - start = int(time.time()) - while True: - time.sleep(CONF.baremetal_introspection.hypervisor_update_sleep) - stats = self.hypervisor_stats() - expected_cpus = self.baremetal_flavor()['vcpus'] - if int(stats['hypervisor_statistics']['vcpus']) >= expected_cpus: - break - - timeout = CONF.baremetal_introspection.hypervisor_update_timeout - if (int(time.time()) - start >= timeout): - message = ( - 'Timeout while waiting for nova hypervisor-stats: ' - '%(stats)s required time (%(timeout)s s).' % - {'stats': stats, - 'timeout': timeout}) - raise exceptions.HypervisorUpdateTimeout(message) - - def node_cleanup(self, node_id): - if (self.node_show(node_id)['provision_state'] == - BaremetalProvisionStates.AVAILABLE): - return - # in case when introspection failed we need set provision state - # to 'manage' to make it possible transit into 'provide' state - if self.node_show(node_id)['provision_state'] == 'inspect failed': - self.baremetal_client.set_node_provision_state(node_id, 'manage') - - try: - self.baremetal_client.set_node_provision_state(node_id, 'provide') - except tempest.lib.exceptions.RestClientException: - # maybe node already cleaning or available - pass - - self.wait_provisioning_state( - node_id, [BaremetalProvisionStates.AVAILABLE, - BaremetalProvisionStates.NOSTATE], - timeout=CONF.baremetal.unprovision_timeout, - interval=self.wait_provisioning_state_interval) - - def introspect_node(self, node_id, remove_props=True): - if remove_props: - # in case there are properties remove those - patch = {('properties/%s' % key): None for key in - self.node_show(node_id)['properties']} - # reset any previous rule result - patch['extra/rule_success'] = None - self.node_update(node_id, patch) - - self.baremetal_client.set_node_provision_state(node_id, 'manage') - self.baremetal_client.set_node_provision_state(node_id, 'inspect') - self.addCleanup(self.node_cleanup, node_id) diff --git a/ironic_inspector/test/inspector_tempest_plugin/tests/test_basic.py b/ironic_inspector/test/inspector_tempest_plugin/tests/test_basic.py deleted file mode 100644 index a6087e3d0..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/tests/test_basic.py +++ /dev/null @@ -1,176 +0,0 @@ -# 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 ironic_tempest_plugin.tests.scenario import baremetal_manager -from tempest.common import utils -from tempest.config import CONF -from tempest.lib import decorators - -from ironic_inspector.test.inspector_tempest_plugin.tests import manager - - -class InspectorBasicTest(manager.InspectorScenarioTest): - - def verify_node_introspection_data(self, node): - data = self.introspection_data(node['uuid']) - self.assertEqual(data['cpu_arch'], - self.flavor['properties']['cpu_arch']) - self.assertEqual(int(data['memory_mb']), - int(self.flavor['ram'])) - self.assertEqual(int(data['cpus']), int(self.flavor['vcpus'])) - - def verify_node_flavor(self, node): - expected_cpus = self.flavor['vcpus'] - expected_memory_mb = self.flavor['ram'] - expected_cpu_arch = self.flavor['properties']['cpu_arch'] - disk_size = self.flavor['disk'] - ephemeral_size = self.flavor['OS-FLV-EXT-DATA:ephemeral'] - expected_local_gb = disk_size + ephemeral_size - - self.assertEqual(expected_cpus, - int(node['properties']['cpus'])) - self.assertEqual(expected_memory_mb, - int(node['properties']['memory_mb'])) - self.assertEqual(expected_local_gb, - int(node['properties']['local_gb'])) - self.assertEqual(expected_cpu_arch, - node['properties']['cpu_arch']) - - def verify_introspection_aborted(self, uuid): - status = self.introspection_status(uuid) - - self.assertEqual('Canceled by operator', status['error']) - self.assertTrue(status['finished']) - - self.wait_provisioning_state( - uuid, 'inspect failed', - timeout=CONF.baremetal.active_timeout, - interval=self.wait_provisioning_state_interval) - - @decorators.idempotent_id('03bf7990-bee0-4dd7-bf74-b97ad7b52a4b') - @utils.services('compute', 'image', 'network') - def test_baremetal_introspection(self): - """This smoke test case follows this set of operations: - - * Fetches expected properties from baremetal flavor - * Removes all properties from nodes - * Sets nodes to manageable state - * Imports introspection rule basic_ops_rule.json - * Inspects nodes - * Verifies all properties are inspected - * Verifies introspection data - * Sets node to available state - * Creates a keypair - * Boots an instance using the keypair - * Deletes the instance - - """ - # prepare introspection rule - rule_path = self.get_rule_path("basic_ops_rule.json") - self.rule_import(rule_path) - self.addCleanup(self.rule_purge) - - for node_id in self.node_ids: - self.introspect_node(node_id) - - # settle down introspection - self.wait_for_introspection_finished(self.node_ids) - for node_id in self.node_ids: - self.wait_provisioning_state( - node_id, 'manageable', - timeout=CONF.baremetal_introspection.ironic_sync_timeout, - interval=self.wait_provisioning_state_interval) - - for node_id in self.node_ids: - node = self.node_show(node_id) - self.assertEqual('yes', node['extra']['rule_success']) - if CONF.service_available.swift: - self.verify_node_introspection_data(node) - self.verify_node_flavor(node) - - for node_id in self.node_ids: - self.baremetal_client.set_node_provision_state(node_id, 'provide') - - for node_id in self.node_ids: - self.wait_provisioning_state( - node_id, baremetal_manager.BaremetalProvisionStates.AVAILABLE, - timeout=CONF.baremetal.active_timeout, - interval=self.wait_provisioning_state_interval) - - self.wait_for_nova_aware_of_bvms() - self.add_keypair() - ins, _node = self.boot_instance() - self.terminate_instance(ins) - - @decorators.idempotent_id('70ca3070-184b-4b7d-8892-e977d2bc2870') - def test_introspection_abort(self): - """This smoke test case follows this very basic set of operations: - - * Start nodes introspection - * Wait until nodes power on - * Abort introspection - * Verifies nodes status and power state - - """ - # start nodes introspection - for node_id in self.node_ids: - self.introspect_node(node_id, remove_props=False) - - # wait for nodes power on - for node_id in self.node_ids: - self.wait_power_state( - node_id, - baremetal_manager.BaremetalPowerStates.POWER_ON) - - # abort introspection - for node_id in self.node_ids: - self.introspection_abort(node_id) - - # wait for nodes power off - for node_id in self.node_ids: - self.wait_power_state( - node_id, - baremetal_manager.BaremetalPowerStates.POWER_OFF) - - # verify nodes status and provision state - for node_id in self.node_ids: - self.verify_introspection_aborted(node_id) - - -class InspectorSmokeTest(manager.InspectorScenarioTest): - - @decorators.idempotent_id('a702d1f1-88e4-42ce-88ef-cba2d9e3312e') - @decorators.attr(type='smoke') - @utils.services('object_storage') - def test_baremetal_introspection(self): - """This smoke test case follows this very basic set of operations: - - * Fetches expected properties from baremetal flavor - * Removes all properties from one node - * Sets the node to manageable state - * Inspects the node - * Sets the node to available state - - """ - # NOTE(dtantsur): we can't silently skip this test because it runs in - # grenade with several other tests, and we won't have any indication - # that it was not run. - assert self.node_ids, "No available nodes" - node_id = next(iter(self.node_ids)) - self.introspect_node(node_id) - - # settle down introspection - self.wait_for_introspection_finished([node_id]) - self.wait_provisioning_state( - node_id, 'manageable', - timeout=CONF.baremetal_introspection.ironic_sync_timeout, - interval=self.wait_provisioning_state_interval) diff --git a/ironic_inspector/test/inspector_tempest_plugin/tests/test_discovery.py b/ironic_inspector/test/inspector_tempest_plugin/tests/test_discovery.py deleted file mode 100644 index 0b10119db..000000000 --- a/ironic_inspector/test/inspector_tempest_plugin/tests/test_discovery.py +++ /dev/null @@ -1,149 +0,0 @@ -# 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 ironic_tempest_plugin.tests.scenario import baremetal_manager -import six -from tempest import config -from tempest.lib import decorators -from tempest import test # noqa - -from ironic_inspector.test.inspector_tempest_plugin.tests import manager - -CONF = config.CONF - -ProvisionStates = baremetal_manager.BaremetalProvisionStates - - -class InspectorDiscoveryTest(manager.InspectorScenarioTest): - @classmethod - def skip_checks(cls): - super(InspectorDiscoveryTest, cls).skip_checks() - if not CONF.baremetal_introspection.auto_discovery_feature: - msg = ("Please, provide a value for node_not_found_hook in " - "processing section of inspector.conf for enable " - "auto-discovery feature.") - raise cls.skipException(msg) - - def setUp(self): - super(InspectorDiscoveryTest, self).setUp() - - discovered_node = self._get_discovery_node() - self.node_info = self._get_node_info(discovered_node) - - rule = self._generate_discovery_rule(self.node_info) - - self.rule_import_from_dict(rule) - self.addCleanup(self.rule_purge) - - def _get_node_info(self, node_uuid): - node = self.node_show(node_uuid) - ports = self.node_port_list(node_uuid) - node['port_macs'] = [port['address'] for port in ports] - return node - - def _get_discovery_node(self): - nodes = self.node_list() - - discovered_node = None - for node in nodes: - if (node['provision_state'] == ProvisionStates.AVAILABLE or - node['provision_state'] == ProvisionStates.ENROLL or - node['provision_state'] is ProvisionStates.NOSTATE): - discovered_node = node['uuid'] - break - - self.assertIsNotNone(discovered_node) - return discovered_node - - def _generate_discovery_rule(self, node): - rule = dict() - rule["description"] = "Node %s discovery rule" % node['name'] - rule["actions"] = [ - {"action": "set-attribute", "path": "/name", - "value": "%s" % node['name']}, - {"action": "set-attribute", "path": "/driver", - "value": "%s" % node['driver']}, - ] - - for key, value in node['driver_info'].items(): - rule["actions"].append( - {"action": "set-attribute", "path": "/driver_info/%s" % key, - "value": "%s" % value}) - rule["conditions"] = [ - {"op": "eq", "field": "data://auto_discovered", "value": True} - ] - return rule - - def verify_node_introspection_data(self, node): - data = self.introspection_data(node['uuid']) - self.assertEqual(data['cpu_arch'], - self.flavor['properties']['cpu_arch']) - self.assertEqual(int(data['memory_mb']), - int(self.flavor['ram'])) - self.assertEqual(int(data['cpus']), int(self.flavor['vcpus'])) - - def verify_node_flavor(self, node): - expected_cpus = self.flavor['vcpus'] - expected_memory_mb = self.flavor['ram'] - expected_cpu_arch = self.flavor['properties']['cpu_arch'] - disk_size = self.flavor['disk'] - ephemeral_size = self.flavor['OS-FLV-EXT-DATA:ephemeral'] - expected_local_gb = disk_size + ephemeral_size - - self.assertEqual(expected_cpus, - int(node['properties']['cpus'])) - self.assertEqual(expected_memory_mb, - int(node['properties']['memory_mb'])) - self.assertEqual(expected_local_gb, - int(node['properties']['local_gb'])) - self.assertEqual(expected_cpu_arch, - node['properties']['cpu_arch']) - - def verify_node_driver_info(self, node_info, inspected_node): - for key in node_info['driver_info']: - self.assertEqual(six.text_type(node_info['driver_info'][key]), - inspected_node['driver_info'].get(key)) - - @decorators.idempotent_id('dd3abe5e-0d23-488d-bb4e-344cdeff7dcb') - def test_bearmetal_auto_discovery(self): - """This test case follows this set of operations: - - * Choose appropriate node, based on provision state; - * Get node info; - * Generate discovery rule; - * Delete discovered node from ironic; - * Start baremetal vm via virsh; - * Wating for node introspection; - * Verify introspected node. - """ - # NOTE(aarefiev): workaround for infra, 'tempest' user doesn't - # have virsh privileges, so lets power on the node via ironic - # and then delete it. Because of node is blacklisted in inspector - # we can't just power on it, therefor start introspection is used - # to whitelist discovered node first. - self.baremetal_client.set_node_provision_state( - self.node_info['uuid'], 'manage') - self.introspection_start(self.node_info['uuid']) - self.wait_power_state( - self.node_info['uuid'], - baremetal_manager.BaremetalPowerStates.POWER_ON) - self.node_delete(self.node_info['uuid']) - - self.wait_for_node(self.node_info['name']) - - inspected_node = self.node_show(self.node_info['name']) - self.verify_node_flavor(inspected_node) - if CONF.service_available.swift: - self.verify_node_introspection_data(inspected_node) - self.verify_node_driver_info(self.node_info, inspected_node) - self.assertEqual(ProvisionStates.ENROLL, - inspected_node['provision_state']) diff --git a/releasenotes/notes/tempest_plugin_removal-91a01f5950f543e1.yaml b/releasenotes/notes/tempest_plugin_removal-91a01f5950f543e1.yaml new file mode 100644 index 000000000..140ff9fe1 --- /dev/null +++ b/releasenotes/notes/tempest_plugin_removal-91a01f5950f543e1.yaml @@ -0,0 +1,10 @@ +--- +other: + - | + The tempest plugin code that was in + ``ironic_inspector/test/inspector_tempest_plugin/`` has been removed. + Tempest plugin code has been migrated to the project + `openstack/ironic-tempest-plugin + `_. This was + an OpenStack wide `goal for the Queens cycle + `_. diff --git a/setup.cfg b/setup.cfg index a80001287..85815c44c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -75,9 +75,6 @@ oslo.policy.enforcer = oslo.policy.policies = ironic_inspector.api = ironic_inspector.policy:list_policies -tempest.test_plugins = - ironic_inspector_tests = ironic_inspector.test.inspector_tempest_plugin.plugin:InspectorTempestPlugin - [compile_catalog] directory = ironic_inspector/locale domain = ironic_inspector