From e05257035ca9dfa53c59ec5b7aa451dc061b452d Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 19 May 2017 10:58:13 +0200 Subject: [PATCH] Completely remove support for setting IPMI credentials This experimental feature was deprecated in the Ocata release, as it was found unstable, untested and dangerous. API version is bumped to 1.12 to indicate this change to users. Change-Id: I1aad6ddfd03946edc19ae510accd6c8daf5fc268 Closes-Bug: #1654318 --- doc/source/http-api.rst | 14 +-- doc/source/usage.rst | 1 - ironic_inspector/common/ironic.py | 11 +- ironic_inspector/conf.py | 6 - ironic_inspector/introspect.py | 104 ++++++------------ ironic_inspector/main.py | 22 +--- ironic_inspector/process.py | 51 +-------- ironic_inspector/test/functional.py | 40 +------ ironic_inspector/test/unit/test_introspect.py | 87 --------------- ironic_inspector/test/unit/test_main.py | 31 ------ ironic_inspector/test/unit/test_process.py | 58 ---------- ...-credentials-removal-0021f89424fbf7a3.yaml | 8 ++ 12 files changed, 49 insertions(+), 384 deletions(-) create mode 100644 releasenotes/notes/ipmi-credentials-removal-0021f89424fbf7a3.yaml diff --git a/doc/source/http-api.rst b/doc/source/http-api.rst index df882c103..c51b07002 100644 --- a/doc/source/http-api.rst +++ b/doc/source/http-api.rst @@ -15,11 +15,6 @@ done prior to calling the endpoint. Requires X-Auth-Token header with Keystone token for authentication. -Deprecated parameters (only available in API before version ``1.9``): - -* ``new_ipmi_password`` -* ``new_ipmi_username`` - Response: * 202 - accepted introspection request @@ -289,12 +284,7 @@ Response: * 403 - node is not on introspection * 404 - node cannot be found or multiple nodes found -Response body: JSON dictionary. If setting IPMI credentials (deprecated -feature) is requested, body will contain the following keys: - -* ``ipmi_setup_credentials`` boolean ``True`` -* ``ipmi_username`` new IPMI user name -* ``ipmi_password`` new IPMI password +Response body: JSON dictionary with ``uuid`` key. .. _hardware inventory: http://docs.openstack.org/developer/ironic-python-agent/#hardware-inventory .. _Specifying the disk for deployment root device hints: @@ -398,3 +388,5 @@ Version History * **1.10** adds node state to the GET /v1/introspection/ and GET /v1/introspection API response data. * **1.11** adds invert&multiple fields into rules response data +* **1.12** this version indicates that support for setting IPMI credentials + was completely removed from API (all versions). diff --git a/doc/source/usage.rst b/doc/source/usage.rst index f246faa4e..a09d2c983 100644 --- a/doc/source/usage.rst +++ b/doc/source/usage.rst @@ -320,7 +320,6 @@ These steps are avoided, based on the feature requirements: Limitations: -* IPMI credentials are not updated --- ramdisk not running * there's no way to update the unprocessed data atm. * the unprocessed data is never cleaned from the store * check for stored data presence is performed in background; diff --git a/ironic_inspector/common/ironic.py b/ironic_inspector/common/ironic.py index af0cfe3be..f61cf6e4f 100644 --- a/ironic_inspector/common/ironic.py +++ b/ironic_inspector/common/ironic.py @@ -27,7 +27,6 @@ LOG = utils.getProcessingLogger(__name__) # See http://specs.openstack.org/openstack/ironic-specs/specs/kilo/new-ironic-state-machine.html # noqa VALID_STATES = {'enroll', 'manageable', 'inspecting', 'inspect failed'} -SET_CREDENTIALS_VALID_STATES = {'enroll'} # 1.19 is API version, which supports port.pxe_enabled DEFAULT_IRONIC_API_VERSION = '1.19' @@ -143,15 +142,9 @@ def get_client(token=None, return client.Client(1, **args) -def check_provision_state(node, with_credentials=False): +def check_provision_state(node): state = node.provision_state.lower() - if with_credentials and state not in SET_CREDENTIALS_VALID_STATES: - msg = _('Invalid provision state for setting IPMI credentials: ' - '"%(state)s", valid states are %(valid)s') - raise utils.Error(msg % {'state': state, - 'valid': list(SET_CREDENTIALS_VALID_STATES)}, - node_info=node) - elif not with_credentials and state not in VALID_STATES: + if state not in VALID_STATES: msg = _('Invalid provision state for introspection: ' '"%(state)s", valid states are "%(valid)s"') raise utils.Error(msg % {'state': state, 'valid': list(VALID_STATES)}, diff --git a/ironic_inspector/conf.py b/ironic_inspector/conf.py index 64fde16cf..a67f93443 100644 --- a/ironic_inspector/conf.py +++ b/ironic_inspector/conf.py @@ -76,12 +76,6 @@ PROCESSING_OPTS = [ help=_('Whether to overwrite existing values in node ' 'database. Disable this option to make ' 'introspection a non-destructive operation.')), - cfg.BoolOpt('enable_setting_ipmi_credentials', - default=False, - help=_('Whether to enable setting IPMI credentials during ' - 'introspection. This feature will be removed in the ' - 'Pike release.'), - deprecated_for_removal=True), cfg.StrOpt('default_processing_hooks', default='ramdisk_error,root_disk_selection,scheduler,' 'validate_interfaces,capabilities,pci_devices', diff --git a/ironic_inspector/introspect.py b/ironic_inspector/introspect.py index 520809a80..cc55e231b 100644 --- a/ironic_inspector/introspect.py +++ b/ironic_inspector/introspect.py @@ -14,7 +14,6 @@ """Handling introspection request.""" import re -import string import time from eventlet import semaphore @@ -31,67 +30,32 @@ CONF = cfg.CONF LOG = utils.getProcessingLogger(__name__) -PASSWORD_ACCEPTED_CHARS = set(string.ascii_letters + string.digits) -PASSWORD_MAX_LENGTH = 20 # IPMI v2.0 _LAST_INTROSPECTION_TIME = 0 _LAST_INTROSPECTION_LOCK = semaphore.BoundedSemaphore() -def _validate_ipmi_credentials(node, new_ipmi_credentials): - if not CONF.processing.enable_setting_ipmi_credentials: - raise utils.Error( - _('IPMI credentials setup is disabled in configuration')) - - new_username, new_password = new_ipmi_credentials - if not new_username: - new_username = node.driver_info.get('ipmi_username') - if not new_username: - raise utils.Error(_('Setting IPMI credentials requested, but neither ' - 'new user name nor driver_info[ipmi_username] ' - 'are provided'), - node_info=node) - wrong_chars = {c for c in new_password - if c not in PASSWORD_ACCEPTED_CHARS} - if wrong_chars: - raise utils.Error(_('Forbidden characters encountered in new IPMI ' - 'password: "%s"; use only letters and numbers') - % ''.join(wrong_chars), node_info=node) - if not 0 < len(new_password) <= PASSWORD_MAX_LENGTH: - raise utils.Error(_('IPMI password length should be > 0 and <= %d') - % PASSWORD_MAX_LENGTH, node_info=node) - - return new_username, new_password - - -def introspect(node_id, new_ipmi_credentials=None, token=None): +def introspect(node_id, token=None): """Initiate hardware properties introspection for a given node. :param node_id: node UUID or name - :param new_ipmi_credentials: tuple (new username, new password) or None :param token: authentication token :raises: Error """ ironic = ir_utils.get_client(token) node = ir_utils.get_node(node_id, ironic=ironic) - ir_utils.check_provision_state(node, with_credentials=new_ipmi_credentials) - - if new_ipmi_credentials: - new_ipmi_credentials = ( - _validate_ipmi_credentials(node, new_ipmi_credentials)) - else: - validation = ironic.node.validate(node.uuid) - if not validation.power['result']: - msg = _('Failed validation of power interface, reason: %s') - raise utils.Error(msg % validation.power['reason'], - node_info=node) + ir_utils.check_provision_state(node) + validation = ironic.node.validate(node.uuid) + if not validation.power['result']: + msg = _('Failed validation of power interface, reason: %s') + raise utils.Error(msg % validation.power['reason'], + node_info=node) bmc_address = ir_utils.get_ipmi_address(node) node_info = node_cache.start_introspection(node.uuid, bmc_address=bmc_address, ironic=ironic) - node_info.set_option('new_ipmi_credentials', new_ipmi_credentials) def _handle_exceptions(fut): try: @@ -111,17 +75,16 @@ def introspect(node_id, new_ipmi_credentials=None, token=None): def _background_introspect(ironic, node_info): global _LAST_INTROSPECTION_TIME - if not node_info.options.get('new_ipmi_credentials'): - if re.match(CONF.introspection_delay_drivers, node_info.node().driver): - LOG.debug('Attempting to acquire lock on last introspection time') - with _LAST_INTROSPECTION_LOCK: - delay = (_LAST_INTROSPECTION_TIME - time.time() - + CONF.introspection_delay) - if delay > 0: - LOG.debug('Waiting %d seconds before sending the next ' - 'node on introspection', delay) - time.sleep(delay) - _LAST_INTROSPECTION_TIME = time.time() + if re.match(CONF.introspection_delay_drivers, node_info.node().driver): + LOG.debug('Attempting to acquire lock on last introspection time') + with _LAST_INTROSPECTION_LOCK: + delay = (_LAST_INTROSPECTION_TIME - time.time() + + CONF.introspection_delay) + if delay > 0: + LOG.debug('Waiting %d seconds before sending the next ' + 'node on introspection', delay) + time.sleep(delay) + _LAST_INTROSPECTION_TIME = time.time() node_info.acquire_lock() try: @@ -151,26 +114,21 @@ def _background_introspect_locked(node_info, ironic): LOG.info('The following attributes will be used for look up: %s', attrs, node_info=node_info) - if not node_info.options.get('new_ipmi_credentials'): - try: - ironic.node.set_boot_device(node_info.uuid, 'pxe', - persistent=False) - except Exception as exc: - LOG.warning('Failed to set boot device to PXE: %s', - exc, node_info=node_info) + try: + ironic.node.set_boot_device(node_info.uuid, 'pxe', + persistent=False) + except Exception as exc: + LOG.warning('Failed to set boot device to PXE: %s', + exc, node_info=node_info) - try: - ironic.node.set_power_state(node_info.uuid, 'reboot') - except Exception as exc: - raise utils.Error(_('Failed to power on the node, check it\'s ' - 'power management configuration: %s'), - exc, node_info=node_info) - LOG.info('Introspection started successfully', - node_info=node_info) - else: - LOG.info('Introspection environment is ready, manual power on is ' - 'required within %d seconds', CONF.timeout, - node_info=node_info) + try: + ironic.node.set_power_state(node_info.uuid, 'reboot') + except Exception as exc: + raise utils.Error(_('Failed to power on the node, check it\'s ' + 'power management configuration: %s'), + exc, node_info=node_info) + LOG.info('Introspection started successfully', + node_info=node_info) def abort(node_id, token=None): diff --git a/ironic_inspector/main.py b/ironic_inspector/main.py index fa30f0eae..5bd8a2c3d 100644 --- a/ironic_inspector/main.py +++ b/ironic_inspector/main.py @@ -48,10 +48,8 @@ app = flask.Flask(__name__) LOG = utils.getProcessingLogger(__name__) MINIMUM_API_VERSION = (1, 0) -# TODO(dtantsur): set to the current version as soon we move setting IPMI -# credentials support completely. -DEFAULT_API_VERSION = (1, 8) -CURRENT_API_VERSION = (1, 11) +CURRENT_API_VERSION = (1, 12) +DEFAULT_API_VERSION = CURRENT_API_VERSION _LOGGING_EXCLUDED_KEYS = ('logs',) @@ -214,23 +212,7 @@ def api_introspection(node_id): utils.check_auth(flask.request) if flask.request.method == 'POST': - new_ipmi_password = flask.request.args.get('new_ipmi_password', - type=str, - default=None) - if new_ipmi_password: - new_ipmi_username = flask.request.args.get('new_ipmi_username', - type=str, - default=None) - new_ipmi_credentials = (new_ipmi_username, new_ipmi_password) - else: - new_ipmi_credentials = None - - if new_ipmi_credentials and _get_version() >= (1, 9): - return _('Setting IPMI credentials is deprecated and not allowed ' - 'starting with API version 1.9'), 400 - introspect.introspect(node_id, - new_ipmi_credentials=new_ipmi_credentials, token=flask.request.headers.get('X-Auth-Token')) return '', 202 else: diff --git a/ironic_inspector/process.py b/ironic_inspector/process.py index 03d2dbf5a..26d30b635 100644 --- a/ironic_inspector/process.py +++ b/ironic_inspector/process.py @@ -18,7 +18,6 @@ import datetime import json import os -import eventlet from oslo_config import cfg from oslo_serialization import base64 from oslo_utils import excutils @@ -38,8 +37,6 @@ CONF = cfg.CONF LOG = utils.getProcessingLogger(__name__) -_CREDENTIALS_WAIT_RETRIES = 10 -_CREDENTIALS_WAIT_PERIOD = 3 _STORAGE_EXCLUDED_KEYS = {'logs'} _UNPROCESSED_DATA_STORE_SUFFIX = 'UNPROCESSED' @@ -279,56 +276,12 @@ def _process_node(node_info, node, introspection_data): resp = {'uuid': node.uuid} - if node_info.options.get('new_ipmi_credentials'): - new_username, new_password = ( - node_info.options.get('new_ipmi_credentials')) - utils.executor().submit(_finish_set_ipmi_credentials, - node_info, ironic, node, introspection_data, - new_username, new_password) - resp['ipmi_setup_credentials'] = True - resp['ipmi_username'] = new_username - resp['ipmi_password'] = new_password - else: - utils.executor().submit(_finish, node_info, ironic, introspection_data, - power_off=CONF.processing.power_off) + utils.executor().submit(_finish, node_info, ironic, introspection_data, + power_off=CONF.processing.power_off) return resp -@node_cache.fsm_transition(istate.Events.finish) -def _finish_set_ipmi_credentials(node_info, ironic, node, introspection_data, - new_username, new_password): - patch = [{'op': 'add', 'path': '/driver_info/ipmi_username', - 'value': new_username}, - {'op': 'add', 'path': '/driver_info/ipmi_password', - 'value': new_password}] - new_ipmi_address = utils.get_ipmi_address_from_data(introspection_data) - if not ir_utils.get_ipmi_address(node) and new_ipmi_address: - patch.append({'op': 'add', 'path': '/driver_info/ipmi_address', - 'value': new_ipmi_address}) - node_info.patch(patch) - - for attempt in range(_CREDENTIALS_WAIT_RETRIES): - try: - # We use this call because it requires valid credentials. - # We don't care about boot device, obviously. - ironic.node.get_boot_device(node_info.uuid) - except Exception as exc: - LOG.info('Waiting for credentials update, attempt %(attempt)d ' - 'current error is %(exc)s', - {'attempt': attempt, 'exc': exc}, - node_info=node_info, data=introspection_data) - eventlet.greenthread.sleep(_CREDENTIALS_WAIT_PERIOD) - else: - _finish_common(node_info, ironic, introspection_data) - return - - msg = (_('Failed to validate updated IPMI credentials for node ' - '%s, node might require maintenance') % node_info.uuid) - node_info.finished(error=msg) - raise utils.Error(msg, node_info=node_info, data=introspection_data) - - def _finish_common(node_info, ironic, introspection_data, power_off=True): if power_off: LOG.debug('Forcing power off of node %s', node_info.uuid) diff --git a/ironic_inspector/test/functional.py b/ironic_inspector/test/functional.py index ccea85155..8bb0f711a 100644 --- a/ironic_inspector/test/functional.py +++ b/ironic_inspector/test/functional.py @@ -54,8 +54,6 @@ os_password = password os_tenant_name = tenant [firewall] manage_firewall = False -[processing] -enable_setting_ipmi_credentials = True [DEFAULT] debug = True auth_strategy = noauth @@ -163,13 +161,8 @@ class Base(base.NodeTest): raise AssertionError(msg) return res - def call_introspect(self, uuid, new_ipmi_username=None, - new_ipmi_password=None, **kwargs): + def call_introspect(self, uuid, **kwargs): endpoint = '/v1/introspection/%s' % uuid - if new_ipmi_password: - endpoint += '?new_ipmi_password=%s' % new_ipmi_password - if new_ipmi_username: - endpoint += '&new_ipmi_username=%s' % new_ipmi_username return self.call('post', endpoint, **kwargs) def call_get_status(self, uuid, **kwargs): @@ -309,37 +302,6 @@ class Test(Base): status = self.call_get_status(self.uuid) self.check_status(status, finished=True, state=istate.States.finished) - def test_setup_ipmi(self): - patch_credentials = [ - {'op': 'add', 'path': '/driver_info/ipmi_username', - 'value': 'admin'}, - {'op': 'add', 'path': '/driver_info/ipmi_password', - 'value': 'pwd'}, - ] - self.node.provision_state = 'enroll' - self.call_introspect(self.uuid, new_ipmi_username='admin', - new_ipmi_password='pwd') - eventlet.greenthread.sleep(DEFAULT_SLEEP) - self.assertFalse(self.cli.node.set_power_state.called) - - status = self.call_get_status(self.uuid) - self.check_status(status, finished=False, state=istate.States.waiting) - - res = self.call_continue(self.data) - self.assertEqual('admin', res['ipmi_username']) - self.assertEqual('pwd', res['ipmi_password']) - self.assertTrue(res['ipmi_setup_credentials']) - eventlet.greenthread.sleep(DEFAULT_SLEEP) - - self.assertCalledWithPatch(self.patch + patch_credentials, - self.cli.node.update) - self.cli.port.create.assert_called_once_with( - node_uuid=self.uuid, address='11:22:33:44:55:66', extra={}, - pxe_enabled=True) - - status = self.call_get_status(self.uuid) - self.check_status(status, finished=True, state=istate.States.finished) - def test_introspection_statuses(self): self.call_introspect(self.uuid) eventlet.greenthread.sleep(DEFAULT_SLEEP) diff --git a/ironic_inspector/test/unit/test_introspect.py b/ironic_inspector/test/unit/test_introspect.py index fae45dc98..cf1fe1a5a 100644 --- a/ironic_inspector/test/unit/test_introspect.py +++ b/ironic_inspector/test/unit/test_introspect.py @@ -72,8 +72,6 @@ class TestIntrospect(BaseTest): persistent=False) cli.node.set_power_state.assert_called_once_with(self.uuid, 'reboot') - self.node_info.set_option.assert_called_once_with( - 'new_ipmi_credentials', None) self.node_info.acquire_lock.assert_called_once_with() self.node_info.release_lock.assert_called_once_with() @@ -99,8 +97,6 @@ class TestIntrospect(BaseTest): persistent=False) cli.node.set_power_state.assert_called_once_with(self.uuid, 'reboot') - self.node_info.set_option.assert_called_once_with( - 'new_ipmi_credentials', None) self.node_info.acquire_lock.assert_called_once_with() self.node_info.release_lock.assert_called_once_with() @@ -332,89 +328,6 @@ class TestIntrospect(BaseTest): self.assertEqual(42, introspect._LAST_INTROSPECTION_TIME) -@mock.patch.object(firewall, 'update_filters', autospec=True) -@mock.patch.object(node_cache, 'start_introspection', autospec=True) -@mock.patch.object(ir_utils, 'get_client', autospec=True) -class TestSetIpmiCredentials(BaseTest): - def setUp(self): - super(TestSetIpmiCredentials, self).setUp() - CONF.set_override('enable_setting_ipmi_credentials', True, - 'processing') - self.new_creds = ('user', 'password') - self.node_info.options['new_ipmi_credentials'] = self.new_creds - self.node.provision_state = 'enroll' - - def test_ok(self, client_mock, start_mock, filters_mock): - cli = self._prepare(client_mock) - start_mock.return_value = self.node_info - - introspect.introspect(self.uuid, new_ipmi_credentials=self.new_creds) - - start_mock.assert_called_once_with(self.uuid, - bmc_address=self.bmc_address, - ironic=cli) - filters_mock.assert_called_with(cli) - self.assertFalse(cli.node.validate.called) - self.assertFalse(cli.node.set_boot_device.called) - self.assertFalse(cli.node.set_power_state.called) - start_mock.return_value.set_option.assert_called_once_with( - 'new_ipmi_credentials', self.new_creds) - - def test_disabled(self, client_mock, start_mock, filters_mock): - CONF.set_override('enable_setting_ipmi_credentials', False, - 'processing') - self._prepare(client_mock) - - self.assertRaisesRegex(utils.Error, 'disabled', - introspect.introspect, self.uuid, - new_ipmi_credentials=self.new_creds) - - def test_no_username(self, client_mock, start_mock, filters_mock): - self._prepare(client_mock) - - self.assertRaises(utils.Error, introspect.introspect, self.uuid, - new_ipmi_credentials=(None, 'password')) - - def test_default_username(self, client_mock, start_mock, filters_mock): - cli = self._prepare(client_mock) - start_mock.return_value = self.node_info - self.node.driver_info['ipmi_username'] = self.new_creds[0] - - introspect.introspect(self.uuid, - new_ipmi_credentials=(None, self.new_creds[1])) - - start_mock.assert_called_once_with(self.uuid, - bmc_address=self.bmc_address, - ironic=cli) - filters_mock.assert_called_with(cli) - self.assertFalse(cli.node.validate.called) - self.assertFalse(cli.node.set_boot_device.called) - self.assertFalse(cli.node.set_power_state.called) - start_mock.return_value.set_option.assert_called_once_with( - 'new_ipmi_credentials', self.new_creds) - - def test_wrong_letters(self, client_mock, start_mock, filters_mock): - self.new_creds = ('user', 'p ssw@rd') - self._prepare(client_mock) - - self.assertRaises(utils.Error, introspect.introspect, self.uuid, - new_ipmi_credentials=self.new_creds) - - def test_too_long(self, client_mock, start_mock, filters_mock): - self.new_creds = ('user', 'password' * 100) - self._prepare(client_mock) - - self.assertRaises(utils.Error, introspect.introspect, self.uuid, - new_ipmi_credentials=self.new_creds) - - def test_wrong_state(self, client_mock, start_mock, filters_mock): - self.node.provision_state = 'manageable' - self._prepare(client_mock) - - self.assertRaises(utils.Error, introspect.introspect, self.uuid, - new_ipmi_credentials=self.new_creds) - - @mock.patch.object(firewall, 'update_filters', autospec=True) @mock.patch.object(node_cache, 'get_node', autospec=True) @mock.patch.object(ir_utils, 'get_client', autospec=True) diff --git a/ironic_inspector/test/unit/test_main.py b/ironic_inspector/test/unit/test_main.py index dc02c88e7..66d233d89 100644 --- a/ironic_inspector/test/unit/test_main.py +++ b/ironic_inspector/test/unit/test_main.py @@ -59,38 +59,8 @@ class TestApiIntrospect(BaseAPITest): res = self.app.post('/v1/introspection/%s' % self.uuid) self.assertEqual(202, res.status_code) introspect_mock.assert_called_once_with(self.uuid, - new_ipmi_credentials=None, token=None) - @mock.patch.object(introspect, 'introspect', autospec=True) - def test_introspect_set_ipmi_credentials(self, introspect_mock): - res = self.app.post('/v1/introspection/%s?new_ipmi_username=user&' - 'new_ipmi_password=password' % self.uuid) - self.assertEqual(202, res.status_code) - introspect_mock.assert_called_once_with( - self.uuid, - new_ipmi_credentials=('user', 'password'), - token=None) - - @mock.patch.object(introspect, 'introspect', autospec=True) - def test_introspect_set_ipmi_credentials_disabled(self, introspect_mock): - headers = {conf.VERSION_HEADER: '1.9'} - res = self.app.post('/v1/introspection/%s?new_ipmi_username=user&' - 'new_ipmi_password=password' % self.uuid, - headers=headers) - self.assertEqual(400, res.status_code) - self.assertFalse(introspect_mock.called) - - @mock.patch.object(introspect, 'introspect', autospec=True) - def test_introspect_set_ipmi_credentials_no_user(self, introspect_mock): - res = self.app.post('/v1/introspection/%s?' - 'new_ipmi_password=password' % self.uuid) - self.assertEqual(202, res.status_code) - introspect_mock.assert_called_once_with( - self.uuid, - new_ipmi_credentials=(None, 'password'), - token=None) - @mock.patch.object(introspect, 'introspect', autospec=True) def test_intospect_failed(self, introspect_mock): introspect_mock.side_effect = utils.Error("boom") @@ -101,7 +71,6 @@ class TestApiIntrospect(BaseAPITest): json.loads(res.data.decode('utf-8'))['error']['message']) introspect_mock.assert_called_once_with( self.uuid, - new_ipmi_credentials=None, token=None) @mock.patch.object(utils, 'check_auth', autospec=True) diff --git a/ironic_inspector/test/unit/test_process.py b/ironic_inspector/test/unit/test_process.py index f4192504d..af14e1d94 100644 --- a/ironic_inspector/test/unit/test_process.py +++ b/ironic_inspector/test/unit/test_process.py @@ -353,14 +353,6 @@ class TestProcessNode(BaseTest): self.data['interfaces'] = self.valid_interfaces self.ports = self.all_ports - self.new_creds = ('user', 'password') - self.patch_credentials = [ - {'op': 'add', 'path': '/driver_info/ipmi_username', - 'value': self.new_creds[0]}, - {'op': 'add', 'path': '/driver_info/ipmi_password', - 'value': self.new_creds[1]}, - ] - self.cli.node.get_boot_device.side_effect = ( [RuntimeError()] * self.validate_attempts + [None]) self.cli.port.create.side_effect = self.ports @@ -382,12 +374,6 @@ class TestProcessNode(BaseTest): ret_val = process._process_node(self.node_info, self.node, self.data) self.assertEqual(self.uuid, ret_val.get('uuid')) - def test_return_includes_uuid_with_ipmi_creds(self): - self.node_info.set_option('new_ipmi_credentials', self.new_creds) - ret_val = process._process_node(self.node_info, self.node, self.data) - self.assertEqual(self.uuid, ret_val.get('uuid')) - self.assertTrue(ret_val.get('ipmi_setup_credentials')) - @mock.patch.object(example_plugin.ExampleProcessingHook, 'before_update') def test_wrong_provision_state(self, post_hook_mock): self.node.provision_state = 'active' @@ -428,49 +414,6 @@ class TestProcessNode(BaseTest): address=self.macs[1], extra={}, pxe_enabled=False) - def test_set_ipmi_credentials(self): - self.node_info.set_option('new_ipmi_credentials', self.new_creds) - - process._process_node(self.node_info, self.node, self.data) - - self.cli.node.update.assert_any_call(self.uuid, self.patch_credentials) - self.cli.node.set_power_state.assert_called_once_with(self.uuid, 'off') - self.cli.node.get_boot_device.assert_called_with(self.uuid) - self.assertEqual(self.validate_attempts + 1, - self.cli.node.get_boot_device.call_count) - - def test_set_ipmi_credentials_no_address(self): - self.node_info.set_option('new_ipmi_credentials', self.new_creds) - del self.node.driver_info['ipmi_address'] - self.patch_credentials.append({'op': 'add', - 'path': '/driver_info/ipmi_address', - 'value': self.bmc_address}) - - process._process_node(self.node_info, self.node, self.data) - - self.cli.node.update.assert_any_call(self.uuid, self.patch_credentials) - self.cli.node.set_power_state.assert_called_once_with(self.uuid, 'off') - self.cli.node.get_boot_device.assert_called_with(self.uuid) - self.assertEqual(self.validate_attempts + 1, - self.cli.node.get_boot_device.call_count) - - @mock.patch.object(node_cache.NodeInfo, 'finished', autospec=True) - def test_set_ipmi_credentials_timeout(self, finished_mock): - self.node_info.set_option('new_ipmi_credentials', self.new_creds) - self.cli.node.get_boot_device.side_effect = RuntimeError('boom') - - process._process_node(self.node_info, self.node, self.data) - - self.cli.node.update.assert_any_call(self.uuid, self.patch_credentials) - self.assertEqual(2, self.cli.node.update.call_count) - self.assertEqual(process._CREDENTIALS_WAIT_RETRIES, - self.cli.node.get_boot_device.call_count) - self.assertFalse(self.cli.node.set_power_state.called) - finished_mock.assert_called_once_with( - mock.ANY, - error='Failed to validate updated IPMI credentials for node %s, ' - 'node might require maintenance' % self.uuid) - @mock.patch.object(node_cache.NodeInfo, 'finished', autospec=True) def test_power_off_failed(self, finished_mock): self.cli.node.set_power_state.side_effect = RuntimeError('boom') @@ -609,7 +552,6 @@ class TestReapplyNode(BaseTest): started_at=self.started_at, node=self.node) self.node_info.invalidate_cache = mock.Mock() - self.new_creds = ('user', 'password') self.cli.port.create.side_effect = self.ports self.cli.node.update.return_value = self.node diff --git a/releasenotes/notes/ipmi-credentials-removal-0021f89424fbf7a3.yaml b/releasenotes/notes/ipmi-credentials-removal-0021f89424fbf7a3.yaml new file mode 100644 index 000000000..b9a6b77c0 --- /dev/null +++ b/releasenotes/notes/ipmi-credentials-removal-0021f89424fbf7a3.yaml @@ -0,0 +1,8 @@ +--- +upgrade: + - | + Experimental setting IPMI credentials support was removed from all versions + of the API. The current API version was bumped to 1.12 to mark this change. + - | + The default API version was synchronized with the current API version again + after removal of the IPMI credentials setting.