rhbz#1241199 - Make configure boot safe to run multiple times

https://bugzilla.redhat.com/show_bug.cgi?id=1241199

If properties/capabilities was already set on a node, baremetal configure
boot would overwrite them. This will only add boot_option:local if it
does not exist, and appends if capabilities are already present.

Change-Id: I72252dccf54daf7a95aecb5fe515066976070e6d
This commit is contained in:
Brad P. Crochet 2015-07-23 12:16:43 -04:00
parent 81eb820c93
commit f316f725e9
2 changed files with 103 additions and 4 deletions
rdomanager_oscplugin
tests/v1/baremetal
v1

@ -583,6 +583,11 @@ class TestConfigureBaremetalBoot(fakes.TestBaremetal):
mock.Mock(uuid="IJKLMNOP"),
]
bm_client.node.get.side_effect = [
mock.Mock(uuid="ABCDEFGH", properties={}),
mock.Mock(uuid="IJKLMNOP", properties={}),
]
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
@ -624,15 +629,20 @@ class TestConfigureBaremetalBoot(fakes.TestBaremetal):
power_state=None),
]
bm_client.node.get.side_effect = [mock.Mock(uuid="ABCDEFGH",
power_state=None),
power_state=None,
properties={}),
mock.Mock(uuid="ABCDEFGH",
power_state='available'),
power_state='available',
properties={}),
mock.Mock(uuid="ABCDEFGH",
power_state='available',
properties={}),
]
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
self.assertEqual(1, bm_client.node.list.call_count)
self.assertEqual(2, bm_client.node.get.call_count)
self.assertEqual(3, bm_client.node.get.call_count)
self.assertEqual(1, bm_client.node.update.call_count)
@mock.patch('openstackclient.common.utils.find_resource', autospec=True)
@ -662,8 +672,86 @@ class TestConfigureBaremetalBoot(fakes.TestBaremetal):
mock.Mock(uuid="ABCDEFGH", maintenance=False),
]
bm_client.node.get.return_value = mock.Mock(uuid="ABCDEFGH",
maintenance=False,
properties={})
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
self.assertEqual(bm_client.node.list.mock_calls, [mock.call(
maintenance=False)])
@mock.patch('openstackclient.common.utils.find_resource', autospec=True)
def test_configure_boot_existing_properties(self, find_resource_mock):
find_resource_mock.return_value = mock.Mock(id="IDIDID")
bm_client = self.app.client_manager.rdomanager_oscplugin.baremetal()
bm_client.node.list.return_value = [
mock.Mock(uuid="ABCDEFGH"),
mock.Mock(uuid="IJKLMNOP"),
mock.Mock(uuid="QRSTUVWX"),
mock.Mock(uuid="YZABCDEF"),
]
bm_client.node.get.side_effect = [
mock.Mock(uuid="ABCDEFGH", properties={
'capabilities': 'existing:cap'
}),
mock.Mock(uuid="IJKLMNOP", properties={
'capabilities': 'boot_option:local'
}),
mock.Mock(uuid="QRSTUVWX", properties={
'capabilities': 'boot_option:remote'
}),
mock.Mock(uuid="YZABCDEF", properties={}),
]
parsed_args = self.check_parser(self.cmd, [], [])
self.cmd.take_action(parsed_args)
self.assertEqual(find_resource_mock.call_count, 2)
self.assertEqual(bm_client.node.update.call_count, 4)
self.assertEqual(bm_client.node.update.mock_calls, [
mock.call('ABCDEFGH', [{
'op': 'add', 'value': 'boot_option:local,existing:cap',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
mock.call('IJKLMNOP', [{
'op': 'add', 'value': 'boot_option:local',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
mock.call('QRSTUVWX', [{
'op': 'add', 'value': 'boot_option:remote',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
mock.call('YZABCDEF', [{
'op': 'add', 'value': 'boot_option:local',
'path': '/properties/capabilities'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_ramdisk'
}, {
'op': 'add', 'value': 'IDIDID',
'path': '/driver_info/deploy_kernel'
}]),
])

@ -409,6 +409,17 @@ class ConfigureBaremetalBoot(command.Command):
node.uuid)
raise exceptions.Timeout(msg)
# Get the full node info
node_detail = bm_client.node.get(node.uuid)
capabilities = node_detail.properties.get('capabilities', None)
# Only update capabilities to add boot_option if it doesn't exist.
if capabilities:
if 'boot_option' not in capabilities:
capabilities = "boot_option:local,%s" % capabilities
else:
capabilities = "boot_option:local"
self.log.debug("Configuring boot for Node {0}".format(
node.uuid))
@ -416,7 +427,7 @@ class ConfigureBaremetalBoot(command.Command):
{
'op': 'add',
'path': '/properties/capabilities',
'value': 'boot_option:local',
'value': capabilities,
},
{
'op': 'add',