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.