Add option `power_off_after_discovery`
Option controls whether to shut down node after the discovery. Change-Id: I447a640a963eafac820c94db3dcd005268ae6bef Implements: blueprint returning-to-ramdisk
This commit is contained in:
parent
2f63aaba24
commit
9b1a164cfa
|
@ -189,6 +189,10 @@ HTTP API consist of 2 endpoints:
|
|||
* 403 - node is not on discovery
|
||||
* 404 - node cannot be found or multiple nodes found
|
||||
|
||||
Successful response body is a JSON dictionary with keys:
|
||||
|
||||
* ``node`` node as returned by Ironic
|
||||
|
||||
.. _bug #1391866: https://bugs.launchpad.net/ironic-discoverd/+bug/1391866
|
||||
|
||||
Change Log
|
||||
|
@ -198,6 +202,8 @@ v1.0.0
|
|||
~~~~~~
|
||||
|
||||
* ``/v1/continue`` is now sync and errors are returned.
|
||||
* Option ``power_off_after_discovery`` controls whether to force power off
|
||||
after the successful discovery, and is ``False`` by default.
|
||||
* Discovery now times out by default.
|
||||
* Add support for plugins that hook into data processing pipeline, see
|
||||
`plugin-architecture blueprint`_ for details.
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
;timeout = 3600
|
||||
; Amount of time in seconds, after which repeat clean up of timed out nodes.
|
||||
;firewall_update_period = 60
|
||||
; Whether to power off the ramdisk immediately after the successful discovery.
|
||||
;power_off_after_discovery = false
|
||||
|
||||
; IP to listen on.
|
||||
;listen_address = 0.0.0.0
|
||||
|
|
|
@ -28,6 +28,7 @@ DEFAULTS = {
|
|||
'processing_hooks': 'scheduler',
|
||||
'timeout': '3600',
|
||||
'clean_up_period': '60',
|
||||
'power_off_after_discovery': 'false',
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -97,9 +97,6 @@ def _process_node(ironic, node, node_info, valid_macs):
|
|||
'database - skipping',
|
||||
{'mac': mac, 'node': node.uuid})
|
||||
|
||||
patch = [{'op': 'add', 'path': '/extra/newly_discovered', 'value': 'true'},
|
||||
{'op': 'remove', 'path': '/extra/on_discovery'}]
|
||||
|
||||
node_patches = []
|
||||
port_patches = {}
|
||||
for hook_ext in hooks:
|
||||
|
@ -114,22 +111,28 @@ def _process_node(ironic, node, node_info, valid_macs):
|
|||
port_patches = {mac: patch for (mac, patch) in port_patches.items()
|
||||
if mac in ports and patch}
|
||||
|
||||
ironic.node.update(node.uuid, patch + node_patches)
|
||||
ironic.node.update(node.uuid, node_patches)
|
||||
|
||||
for mac, patches in port_patches.items():
|
||||
ironic.port.update(ports[mac].uuid, patches)
|
||||
|
||||
LOG.info('Node %s was updated with data from discovery process, forcing '
|
||||
'power off', node.uuid)
|
||||
LOG.info('Node %s was updated with data from discovery process', node.uuid)
|
||||
|
||||
firewall.update_filters(ironic)
|
||||
|
||||
try:
|
||||
ironic.node.set_power_state(node.uuid, 'off')
|
||||
except Exception as exc:
|
||||
LOG.error('Failed to power off node %s, check it\'s power '
|
||||
'management configuration:\n%s', node.uuid, exc)
|
||||
raise utils.DiscoveryFailed('Failed to power off node %s' % node.uuid)
|
||||
if conf.getboolean('discoverd', 'power_off_after_discovery'):
|
||||
LOG.info('Forcing power off of node %s', node.uuid)
|
||||
try:
|
||||
ironic.node.set_power_state(node.uuid, 'off')
|
||||
except Exception as exc:
|
||||
LOG.error('Failed to power off node %s, check it\'s power '
|
||||
'management configuration:\n%s', node.uuid, exc)
|
||||
raise utils.DiscoveryFailed('Failed to power off node %s' %
|
||||
node.uuid)
|
||||
|
||||
patch = [{'op': 'add', 'path': '/extra/newly_discovered', 'value': 'true'},
|
||||
{'op': 'remove', 'path': '/extra/on_discovery'}]
|
||||
ironic.node.update(node.uuid, patch)
|
||||
|
||||
|
||||
def discover(uuids):
|
||||
|
|
|
@ -51,16 +51,19 @@ class BaseTest(unittest.TestCase):
|
|||
@patch.object(utils, 'get_client', autospec=True)
|
||||
class TestProcess(BaseTest):
|
||||
def setUp(self):
|
||||
super(TestProcess, self).setUp()
|
||||
self.node = Mock(driver_info={'ipmi_address': '1.2.3.4'},
|
||||
properties={'cpu_arch': 'i386', 'local_gb': 40},
|
||||
uuid='uuid',
|
||||
extra={'on_discovery': 'true'})
|
||||
self.patch = [
|
||||
{'op': 'add', 'path': '/extra/newly_discovered', 'value': 'true'},
|
||||
{'op': 'remove', 'path': '/extra/on_discovery'},
|
||||
self.patch1 = [
|
||||
{'op': 'add', 'path': '/properties/cpus', 'value': '2'},
|
||||
{'op': 'add', 'path': '/properties/memory_mb', 'value': '1024'},
|
||||
]
|
||||
self.patch2 = [
|
||||
{'op': 'add', 'path': '/extra/newly_discovered', 'value': 'true'},
|
||||
{'op': 'remove', 'path': '/extra/on_discovery'},
|
||||
]
|
||||
self.data = {
|
||||
'ipmi_address': '1.2.3.4',
|
||||
'cpus': 2,
|
||||
|
@ -105,16 +108,17 @@ class TestProcess(BaseTest):
|
|||
self.assertEqual(['11:22:33:44:55:66', '66:55:44:33:22:11'],
|
||||
sorted(pop_mock.call_args[1]['mac']))
|
||||
|
||||
cli.node.update.assert_called_once_with(self.node.uuid,
|
||||
self.patch + ['fake patch',
|
||||
'fake patch 2'])
|
||||
cli.node.update.assert_any_call(self.node.uuid,
|
||||
self.patch1 + ['fake patch',
|
||||
'fake patch 2'])
|
||||
cli.node.update.assert_any_call(self.node.uuid, self.patch2)
|
||||
self.assertEqual(2, cli.node.update.call_count)
|
||||
cli.port.create.assert_any_call(node_uuid=self.node.uuid,
|
||||
address='11:22:33:44:55:66')
|
||||
cli.port.create.assert_any_call(node_uuid=self.node.uuid,
|
||||
address='66:55:44:33:22:11')
|
||||
self.assertEqual(2, cli.port.create.call_count)
|
||||
filters_mock.assert_called_once_with(cli)
|
||||
cli.node.set_power_state.assert_called_once_with(self.node.uuid, 'off')
|
||||
cli.port.update.assert_called_once_with(self.port.uuid, ['port patch'])
|
||||
|
||||
pre_mock.assert_called_once_with(self.data)
|
||||
|
@ -123,6 +127,14 @@ class TestProcess(BaseTest):
|
|||
def test_ok(self, client_mock, pop_mock, filters_mock, pre_mock,
|
||||
post_mock):
|
||||
self._do_test(client_mock, pop_mock, filters_mock, pre_mock, post_mock)
|
||||
self.assertFalse(client_mock.return_value.node.set_power_state.called)
|
||||
|
||||
def test_force_off(self, client_mock, pop_mock, filters_mock, pre_mock,
|
||||
post_mock):
|
||||
conf.CONF.set('discoverd', 'power_off_after_discovery', 'true')
|
||||
self._do_test(client_mock, pop_mock, filters_mock, pre_mock, post_mock)
|
||||
client_mock.return_value.node.set_power_state.assert_called_once_with(
|
||||
self.node.uuid, 'off')
|
||||
|
||||
def test_deprecated_macs(self, client_mock, pop_mock, filters_mock,
|
||||
pre_mock, post_mock):
|
||||
|
|
Loading…
Reference in New Issue