Fixes console port conflict occurs in certain path
The dynamically allocated console port for a node is saved into database and reused on subsequent console operations. In certain code path the port record cann't be trusted and we should do a re-allocation. This patch fixes the issue by ignores previous allocation record. The extra cleanup in the takeover is not required anymore and removed as well. Change-Id: I1a07ea9b30a2c760af7a6a4e39f3ff227df28fff Story: 2010489 Task: 47061
This commit is contained in:
parent
ef772c2c1e
commit
c9c9b3100d
@ -1773,10 +1773,6 @@ class ConductorManager(base_manager.BaseConductorManager):
|
|||||||
if task.node.console_enabled:
|
if task.node.console_enabled:
|
||||||
notify_utils.emit_console_notification(
|
notify_utils.emit_console_notification(
|
||||||
task, 'console_restore', fields.NotificationStatus.START)
|
task, 'console_restore', fields.NotificationStatus.START)
|
||||||
# NOTE(kaifeng) Clear allocated_ipmi_terminal_port if exists,
|
|
||||||
# so current conductor can allocate a new free port from local
|
|
||||||
# resources.
|
|
||||||
task.node.del_driver_internal_info('allocated_ipmi_terminal_port')
|
|
||||||
try:
|
try:
|
||||||
task.driver.console.start_console(task)
|
task.driver.console.start_console(task)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
@ -1556,6 +1556,9 @@ class IPMIShellinaboxConsole(IPMIConsole):
|
|||||||
created
|
created
|
||||||
:raises: ConsoleSubprocessFailed when invoking the subprocess failed
|
:raises: ConsoleSubprocessFailed when invoking the subprocess failed
|
||||||
"""
|
"""
|
||||||
|
# Dealloc allocated port if any, so the same host can never has
|
||||||
|
# duplicated port.
|
||||||
|
_release_allocated_port(task)
|
||||||
driver_info = _parse_driver_info(task.node)
|
driver_info = _parse_driver_info(task.node)
|
||||||
if not driver_info['port']:
|
if not driver_info['port']:
|
||||||
driver_info['port'] = _allocate_port(task)
|
driver_info['port'] = _allocate_port(task)
|
||||||
@ -1611,6 +1614,9 @@ class IPMISocatConsole(IPMIConsole):
|
|||||||
created
|
created
|
||||||
:raises: ConsoleSubprocessFailed when invoking the subprocess failed
|
:raises: ConsoleSubprocessFailed when invoking the subprocess failed
|
||||||
"""
|
"""
|
||||||
|
# Dealloc allocated port if any, so the same host can never has
|
||||||
|
# duplicated port.
|
||||||
|
_release_allocated_port(task)
|
||||||
driver_info = _parse_driver_info(task.node)
|
driver_info = _parse_driver_info(task.node)
|
||||||
if not driver_info['port']:
|
if not driver_info['port']:
|
||||||
driver_info['port'] = _allocate_port(
|
driver_info['port'] = _allocate_port(
|
||||||
|
@ -7244,44 +7244,6 @@ class DoNodeTakeOverTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
|||||||
mock.call(task, 'console_restore',
|
mock.call(task, 'console_restore',
|
||||||
obj_fields.NotificationStatus.ERROR)])
|
obj_fields.NotificationStatus.ERROR)])
|
||||||
|
|
||||||
@mock.patch.object(notification_utils, 'emit_console_notification',
|
|
||||||
autospec=True)
|
|
||||||
@mock.patch('ironic.drivers.modules.fake.FakeConsole.start_console',
|
|
||||||
autospec=True)
|
|
||||||
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.take_over',
|
|
||||||
autospec=True)
|
|
||||||
@mock.patch('ironic.drivers.modules.fake.FakeDeploy.prepare',
|
|
||||||
autospec=True)
|
|
||||||
def test__do_takeover_with_console_port_cleaned(self, mock_prepare,
|
|
||||||
mock_take_over,
|
|
||||||
mock_start_console,
|
|
||||||
mock_notify):
|
|
||||||
self._start_service(start_consoles=False)
|
|
||||||
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
|
|
||||||
console_enabled=True)
|
|
||||||
di_info = node.driver_internal_info
|
|
||||||
di_info['allocated_ipmi_terminal_port'] = 12345
|
|
||||||
node.driver_internal_info = di_info
|
|
||||||
node.save()
|
|
||||||
|
|
||||||
task = task_manager.TaskManager(self.context, node.uuid)
|
|
||||||
|
|
||||||
self.service._do_takeover(task)
|
|
||||||
node.refresh()
|
|
||||||
self.assertIsNone(node.last_error)
|
|
||||||
self.assertTrue(node.console_enabled)
|
|
||||||
self.assertIsNone(
|
|
||||||
node.driver_internal_info.get('allocated_ipmi_terminal_port',
|
|
||||||
None))
|
|
||||||
mock_prepare.assert_called_once_with(task.driver.deploy, task)
|
|
||||||
mock_take_over.assert_called_once_with(task.driver.deploy, task)
|
|
||||||
mock_start_console.assert_called_once_with(task.driver.console, task)
|
|
||||||
mock_notify.assert_has_calls(
|
|
||||||
[mock.call(task, 'console_restore',
|
|
||||||
obj_fields.NotificationStatus.START),
|
|
||||||
mock.call(task, 'console_restore',
|
|
||||||
obj_fields.NotificationStatus.END)])
|
|
||||||
|
|
||||||
|
|
||||||
@mgr_utils.mock_record_keepalive
|
@mgr_utils.mock_record_keepalive
|
||||||
class DoNodeAdoptionTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
class DoNodeAdoptionTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
|
||||||
|
@ -3255,6 +3255,11 @@ class IPMIToolShellinaboxTestCase(db_base.DbTestCase):
|
|||||||
mock_start.return_value = None
|
mock_start.return_value = None
|
||||||
mock_info.return_value = {'port': None}
|
mock_info.return_value = {'port': None}
|
||||||
mock_alloc.return_value = 1234
|
mock_alloc.return_value = 1234
|
||||||
|
# Ensure allocated port is not re-used
|
||||||
|
dii = self.node.driver_internal_info
|
||||||
|
dii['allocated_ipmi_terminal_port'] = 4321
|
||||||
|
self.node.driver_internal_info = dii
|
||||||
|
self.node.save()
|
||||||
|
|
||||||
with task_manager.acquire(self.context,
|
with task_manager.acquire(self.context,
|
||||||
self.node.uuid) as task:
|
self.node.uuid) as task:
|
||||||
@ -3468,6 +3473,11 @@ class IPMIToolSocatDriverTestCase(IPMIToolShellinaboxTestCase):
|
|||||||
mock_start.return_value = None
|
mock_start.return_value = None
|
||||||
mock_info.return_value = {'port': None}
|
mock_info.return_value = {'port': None}
|
||||||
mock_alloc.return_value = 1234
|
mock_alloc.return_value = 1234
|
||||||
|
# Ensure allocated port is not re-used
|
||||||
|
dii = self.node.driver_internal_info
|
||||||
|
dii['allocated_ipmi_terminal_port'] = 4321
|
||||||
|
self.node.driver_internal_info = dii
|
||||||
|
self.node.save()
|
||||||
|
|
||||||
with task_manager.acquire(self.context,
|
with task_manager.acquire(self.context,
|
||||||
self.node.uuid) as task:
|
self.node.uuid) as task:
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
Fixes issues that auto-allocated console port could conflict on the same
|
||||||
|
host under certain circumstances related to conductor takeover.
|
||||||
|
|
||||||
|
For more information, see `story 2010489
|
||||||
|
<https://storyboard.openstack.org/#!/story/2010489>`_.
|
Loading…
Reference in New Issue
Block a user