support passing disable_ramdisk for clean and service state
When manually cleaning or servicing a node, it is possible to not have it boot the ironic-python-agent. Wire this up to the CLI as well for manual cleaning and servicing. Change-Id: Ibcedfbc2e65756b98c9b7334c7eadfc925d70fd7
This commit is contained in:

committed by
Doug Goldstein

parent
6638d86baf
commit
9feda5a8e2
@@ -103,6 +103,13 @@ class ProvisionStateBaremetalNode(command.Command):
|
||||
|
||||
rescue_password = getattr(parsed_args, 'rescue_password', None)
|
||||
|
||||
disable_ramdisk = getattr(parsed_args, 'disable_ramdisk', None)
|
||||
|
||||
if runbook and disable_ramdisk:
|
||||
raise exc.CommandError(
|
||||
_("You cannot supply --runbook and --disable-ramdisk together")
|
||||
)
|
||||
|
||||
for node in parsed_args.nodes:
|
||||
baremetal_client.node.set_provision_state(
|
||||
node,
|
||||
@@ -112,7 +119,8 @@ class ProvisionStateBaremetalNode(command.Command):
|
||||
deploysteps=deploy_steps,
|
||||
rescue_password=rescue_password,
|
||||
servicesteps=service_steps,
|
||||
runbook=runbook)
|
||||
runbook=runbook,
|
||||
disable_ramdisk=disable_ramdisk)
|
||||
|
||||
|
||||
class ProvisionStateWithWait(ProvisionStateBaremetalNode):
|
||||
@@ -308,6 +316,13 @@ class CleanBaremetalNode(ProvisionStateWithWait):
|
||||
metavar='<runbook>',
|
||||
help=_("The identifier of a predefined runbook to use for "
|
||||
"cleaning."))
|
||||
parser.add_argument(
|
||||
'--disable-ramdisk',
|
||||
action='store_true',
|
||||
default=None,
|
||||
help=_("ironic-python-agent will not be booted for cleaning. "
|
||||
"Only steps explicitly marked as not requiring "
|
||||
"ironic-python-agent can be executed with this set."))
|
||||
return parser
|
||||
|
||||
|
||||
@@ -335,6 +350,13 @@ class ServiceBaremetalNode(ProvisionStateWithWait):
|
||||
metavar='<runbook>',
|
||||
help=_("The identifier of a predefined runbook to use for "
|
||||
"servicing."))
|
||||
parser.add_argument(
|
||||
'--disable-ramdisk',
|
||||
action='store_true',
|
||||
default=None,
|
||||
help=_("ironic-python-agent will not be booted for cleaning. "
|
||||
"Only steps explicitly marked as not requiring "
|
||||
"ironic-python-agent can be executed with this set."))
|
||||
return parser
|
||||
|
||||
|
||||
|
@@ -60,7 +60,7 @@ class TestAbort(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'abort', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
|
||||
class TestAdopt(TestBaremetal):
|
||||
@@ -84,7 +84,8 @@ class TestAdopt(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'adopt',
|
||||
cleansteps=None, deploysteps=None, configdrive=None,
|
||||
rescue_password=None, servicesteps=None, runbook=None)
|
||||
rescue_password=None, servicesteps=None, runbook=None,
|
||||
disable_ramdisk=None)
|
||||
self.baremetal_mock.node.wait_for_provision_state.assert_not_called()
|
||||
|
||||
def test_adopt_baremetal_provision_state_active_and_wait(self):
|
||||
@@ -104,7 +105,8 @@ class TestAdopt(TestBaremetal):
|
||||
test_node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'adopt',
|
||||
cleansteps=None, deploysteps=None, configdrive=None,
|
||||
rescue_password=None, servicesteps=None, runbook=None)
|
||||
rescue_password=None, servicesteps=None, runbook=None,
|
||||
disable_ramdisk=None)
|
||||
test_node.wait_for_provision_state.assert_called_once_with(
|
||||
['node_uuid'], expected_state='active',
|
||||
poll_interval=2, timeout=15)
|
||||
@@ -126,7 +128,8 @@ class TestAdopt(TestBaremetal):
|
||||
test_node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'adopt',
|
||||
cleansteps=None, deploysteps=None, configdrive=None,
|
||||
rescue_password=None, servicesteps=None, runbook=None)
|
||||
rescue_password=None, servicesteps=None, runbook=None,
|
||||
disable_ramdisk=None)
|
||||
test_node.wait_for_provision_state.assert_called_once_with(
|
||||
['node_uuid'], expected_state='active',
|
||||
poll_interval=2, timeout=0)
|
||||
@@ -176,7 +179,7 @@ class TestClean(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'clean', cleansteps=steps_dict, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
def test_clean_with_runbook(self):
|
||||
runbook_name = 'runbook_name'
|
||||
@@ -194,7 +197,7 @@ class TestClean(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'clean', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=runbook_name)
|
||||
runbook=runbook_name, disable_ramdisk=None)
|
||||
|
||||
def test_clean_with_runbook_and_steps(self):
|
||||
runbook_name = 'runbook_name'
|
||||
@@ -225,6 +228,58 @@ class TestClean(TestBaremetal):
|
||||
self.check_parser,
|
||||
self.cmd, arglist, verifylist)
|
||||
|
||||
def test_clean_with_steps_and_disable_ramdisk(self):
|
||||
steps_dict = {
|
||||
"clean_steps": [{
|
||||
"interface": "raid",
|
||||
"step": "delete_configuration"
|
||||
}, {
|
||||
"interface": "raid",
|
||||
"step": "create_configuration",
|
||||
"args": {"create_nonroot_volumes": False}
|
||||
}]
|
||||
}
|
||||
steps_json = json.dumps(steps_dict)
|
||||
|
||||
arglist = ['--clean-steps',
|
||||
steps_json,
|
||||
'--disable-ramdisk',
|
||||
'node_uuid']
|
||||
verifylist = [
|
||||
('clean_steps', steps_json),
|
||||
('provision_state', 'clean'),
|
||||
('disable_ramdisk', True),
|
||||
('nodes', ['node_uuid']),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'clean', cleansteps=steps_dict, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None, disable_ramdisk=True)
|
||||
|
||||
def test_clean_with_runbook_and_disable_ramdisk(self):
|
||||
runbook_name = 'runbook_name'
|
||||
|
||||
arglist = ['--runbook',
|
||||
runbook_name,
|
||||
'--disable-ramdisk',
|
||||
'node_uuid']
|
||||
verifylist = [
|
||||
('runbook', runbook_name),
|
||||
('provision_state', 'clean'),
|
||||
('disable_ramdisk', True),
|
||||
('nodes', ['node_uuid']),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.assertRaises(exc.CommandError,
|
||||
self.cmd.take_action, parsed_args)
|
||||
self.assertFalse(self.baremetal_mock.node.set_provision_state.called)
|
||||
|
||||
|
||||
class TestService(TestBaremetal):
|
||||
def setUp(self):
|
||||
@@ -260,7 +315,7 @@ class TestService(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'service', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=steps_dict,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
def test_service_with_runbook(self):
|
||||
runbook_name = 'runbook_name'
|
||||
@@ -276,9 +331,9 @@ class TestService(TestBaremetal):
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'service', cleansteps=None, configdrive=None,
|
||||
'node_uuid', 'service', configdrive=None, cleansteps=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=runbook_name)
|
||||
runbook=runbook_name, disable_ramdisk=None)
|
||||
|
||||
def test_service_with_runbook_and_steps(self):
|
||||
runbook_name = 'runbook_name'
|
||||
@@ -308,6 +363,58 @@ class TestService(TestBaremetal):
|
||||
self.check_parser,
|
||||
self.cmd, arglist, verifylist)
|
||||
|
||||
def test_service_with_steps_and_disable_ramdisk(self):
|
||||
steps_dict = {
|
||||
"service_steps": [{
|
||||
"interface": "raid",
|
||||
"step": "delete_configuration"
|
||||
}, {
|
||||
"interface": "raid",
|
||||
"step": "create_configuration",
|
||||
"args": {"create_nonroot_volumes": False}
|
||||
}]
|
||||
}
|
||||
steps_json = json.dumps(steps_dict)
|
||||
|
||||
arglist = ['--service-steps',
|
||||
steps_json,
|
||||
'--disable-ramdisk',
|
||||
'node_uuid']
|
||||
verifylist = [
|
||||
('service_steps', steps_json),
|
||||
('provision_state', 'service'),
|
||||
('disable_ramdisk', True),
|
||||
('nodes', ['node_uuid']),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.cmd.take_action(parsed_args)
|
||||
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'service', configdrive=None, cleansteps=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=steps_dict,
|
||||
runbook=None, disable_ramdisk=True)
|
||||
|
||||
def test_service_with_runbook_and_disable_ramdisk(self):
|
||||
runbook_name = 'runbook_name'
|
||||
|
||||
arglist = ['--runbook',
|
||||
runbook_name,
|
||||
'--disable-ramdisk',
|
||||
'node_uuid']
|
||||
verifylist = [
|
||||
('runbook', runbook_name),
|
||||
('provision_state', 'service'),
|
||||
('disable_ramdisk', True),
|
||||
('nodes', ['node_uuid']),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
self.assertRaises(exc.CommandError,
|
||||
self.cmd.take_action, parsed_args)
|
||||
self.assertFalse(self.baremetal_mock.node.set_provision_state.called)
|
||||
|
||||
|
||||
class TestInspect(TestBaremetal):
|
||||
def setUp(self):
|
||||
@@ -330,7 +437,7 @@ class TestInspect(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'inspect', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
|
||||
class TestManage(TestBaremetal):
|
||||
@@ -354,7 +461,7 @@ class TestManage(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'manage', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
|
||||
class TestProvide(TestBaremetal):
|
||||
@@ -378,7 +485,7 @@ class TestProvide(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'provide', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
|
||||
class TestRebuild(TestBaremetal):
|
||||
@@ -402,7 +509,7 @@ class TestRebuild(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'rebuild', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
|
||||
class TestUndeploy(TestBaremetal):
|
||||
@@ -426,7 +533,7 @@ class TestUndeploy(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'deleted', cleansteps=None, configdrive=None,
|
||||
deploysteps=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
|
||||
class TestBootdeviceSet(TestBaremetal):
|
||||
@@ -2013,7 +2120,7 @@ class TestDeployBaremetalProvisionState(TestBaremetal):
|
||||
'node_uuid', 'active',
|
||||
cleansteps=None, deploysteps=[{"interface": "deploy"}],
|
||||
configdrive='path/to/drive', rescue_password=None,
|
||||
servicesteps=None, runbook=None)
|
||||
servicesteps=None, runbook=None, disable_ramdisk=None)
|
||||
|
||||
def test_deploy_baremetal_provision_state_active_and_configdrive_dict(
|
||||
self):
|
||||
@@ -2032,7 +2139,8 @@ class TestDeployBaremetalProvisionState(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'active',
|
||||
cleansteps=None, deploysteps=None, configdrive={'meta_data': {}},
|
||||
rescue_password=None, servicesteps=None, runbook=None)
|
||||
rescue_password=None, servicesteps=None, runbook=None,
|
||||
disable_ramdisk=None)
|
||||
|
||||
def test_deploy_no_wait(self):
|
||||
arglist = ['node_uuid']
|
||||
@@ -2097,7 +2205,7 @@ class TestDeployBaremetalProvisionState(TestBaremetal):
|
||||
test_node.set_provision_state.assert_has_calls([
|
||||
mock.call(n, 'active', cleansteps=None, deploysteps=None,
|
||||
configdrive=None, rescue_password=None,
|
||||
servicesteps=None, runbook=None)
|
||||
servicesteps=None, runbook=None, disable_ramdisk=None)
|
||||
for n in ['node_uuid', 'node_name']
|
||||
])
|
||||
test_node.wait_for_provision_state.assert_called_once_with(
|
||||
@@ -2321,7 +2429,7 @@ class TestRescueBaremetalProvisionState(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'rescue', cleansteps=None, deploysteps=None,
|
||||
configdrive=None, rescue_password='supersecret',
|
||||
servicesteps=None, runbook=None)
|
||||
servicesteps=None, runbook=None, disable_ramdisk=None)
|
||||
|
||||
def test_rescue_baremetal_provision_state_rescue_and_wait(self):
|
||||
arglist = ['node_uuid',
|
||||
@@ -2513,7 +2621,7 @@ class TestRebuildBaremetalProvisionState(TestBaremetal):
|
||||
'node_uuid', 'rebuild',
|
||||
cleansteps=None, deploysteps=[{"interface": "deploy"}],
|
||||
configdrive='path/to/drive', rescue_password=None,
|
||||
servicesteps=None, runbook=None)
|
||||
servicesteps=None, runbook=None, disable_ramdisk=None)
|
||||
|
||||
def test_rebuild_no_wait(self):
|
||||
arglist = ['node_uuid']
|
||||
@@ -2529,7 +2637,8 @@ class TestRebuildBaremetalProvisionState(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'rebuild',
|
||||
cleansteps=None, deploysteps=None, configdrive=None,
|
||||
rescue_password=None, servicesteps=None, runbook=None)
|
||||
rescue_password=None, servicesteps=None, runbook=None,
|
||||
disable_ramdisk=None)
|
||||
|
||||
self.baremetal_mock.node.wait_for_provision_state.assert_not_called()
|
||||
|
||||
@@ -2648,7 +2757,7 @@ class TestUnrescueBaremetalProvisionState(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'unrescue', cleansteps=None, deploysteps=None,
|
||||
configdrive=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
def test_unrescue_baremetal_provision_state_active_and_wait(self):
|
||||
arglist = ['node_uuid',
|
||||
@@ -4764,7 +4873,7 @@ class TestUnholdBaremetalProvisionState(TestBaremetal):
|
||||
self.baremetal_mock.node.set_provision_state.assert_called_once_with(
|
||||
'node_uuid', 'unhold', cleansteps=None, deploysteps=None,
|
||||
configdrive=None, rescue_password=None, servicesteps=None,
|
||||
runbook=None)
|
||||
runbook=None, disable_ramdisk=None)
|
||||
|
||||
|
||||
class TestListFirmwareComponents(TestBaremetal):
|
||||
|
@@ -1771,6 +1771,20 @@ class NodeManagerTest(testtools.TestCase):
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
|
||||
def test_node_set_provision_state_with_cleansteps_disable_ramdisk(self):
|
||||
cleansteps = [{"step": "delete_configuration", "interface": "raid"}]
|
||||
target_state = 'clean'
|
||||
self.mgr.set_provision_state(NODE1['uuid'], target_state,
|
||||
cleansteps=cleansteps,
|
||||
disable_ramdisk=True)
|
||||
body = {'target': target_state,
|
||||
'clean_steps': cleansteps,
|
||||
'disable_ramdisk': True}
|
||||
expect = [
|
||||
('PUT', '/v1/nodes/%s/states/provision' % NODE1['uuid'], {}, body),
|
||||
]
|
||||
self.assertEqual(expect, self.api.calls)
|
||||
|
||||
def test_node_set_provision_state_with_deploysteps(self):
|
||||
deploysteps = [{"step": "upgrade", "interface": "deploy"}]
|
||||
target_state = 'active'
|
||||
|
@@ -729,7 +729,7 @@ class NodeManager(base.CreateManager):
|
||||
self, node_uuid, state, configdrive=None, cleansteps=None,
|
||||
rescue_password=None, os_ironic_api_version=None,
|
||||
global_request_id=None, deploysteps=None,
|
||||
servicesteps=None, runbook=None):
|
||||
servicesteps=None, runbook=None, disable_ramdisk=None):
|
||||
"""Set the provision state for the node.
|
||||
|
||||
:param node_uuid: The UUID or name of the node.
|
||||
@@ -769,6 +769,10 @@ class NodeManager(base.CreateManager):
|
||||
'service'.
|
||||
:param runbook: The identifier of a predefined runbook to use for
|
||||
provisioning.
|
||||
:param disable_ramdisk: Boolean if set to true will not boot the
|
||||
ironic-python-agent for cleaning. Only valid when setting 'state'
|
||||
to 'clean' or 'service' and only for steps explicitly marked as
|
||||
not requiring the ironic-python-agent can use this.
|
||||
:raises: InvalidAttribute if there was an error with the clean steps or
|
||||
deploy steps
|
||||
:returns: The status of the request
|
||||
@@ -812,6 +816,16 @@ class NodeManager(base.CreateManager):
|
||||
if runbook:
|
||||
body['runbook'] = runbook
|
||||
|
||||
if isinstance(disable_ramdisk, bool):
|
||||
body['disable_ramdisk'] = disable_ramdisk
|
||||
elif disable_ramdisk:
|
||||
try:
|
||||
body['disable_ramdisk'] = strutils.bool_from_string(state,
|
||||
True)
|
||||
except ValueError as e:
|
||||
raise exc.InvalidAttribute(_("Argument 'disable_ramdisk': "
|
||||
"%(err)s") % {'err': e})
|
||||
|
||||
return self.update(path, body, http_method='PUT',
|
||||
os_ironic_api_version=os_ironic_api_version,
|
||||
global_request_id=global_request_id)
|
||||
|
@@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for ``NodeManager.set_provision_state``,
|
||||
to accept ``disable_ramdisk`` keyword argument to disable booting
|
||||
ironic-python-agent for clean and service steps that support it.
|
||||
- |
|
||||
Add ``--disable-ramdisk`` CLI option to `node clean` and
|
||||
`node service` to disable booting ironic-python-agent for steps
|
||||
that support it.
|
Reference in New Issue
Block a user