Supports specifying profile explicitly in instackenv.json
One day Nova will deprecate capabilities, and we'll have to use something else for profiles. As a preparational steps, start accepting profile as a separate instackenv.json field, thus decoupling it from the underlying implementation. Partial-Bug: #1793134 Change-Id: Ife97a0955a480bcc41b3453d58ef7fe6488b476c
This commit is contained in:
parent
2c225f1f2a
commit
e3a410f699
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Node's profile can now be specified as a separate ``profile`` field in
|
||||
the ``instackenv.json`` instead of inside capabilities.
|
||||
deprecations:
|
||||
- |
|
||||
Specifying profile in capabilities when enrolling nodes is deprecated.
|
||||
Please use the new ``profile`` field instead.
|
|
@ -467,6 +467,32 @@ class NodesTest(base.TestCase):
|
|||
ironic.node.create.assert_has_calls([pxe_node, mock.ANY])
|
||||
ironic.port.create.assert_has_calls([port_call])
|
||||
|
||||
def test_register_all_nodes_with_profile(self):
|
||||
node_list = [self._get_node()]
|
||||
node_list[0]['root_device'] = {"serial": "abcdef"}
|
||||
node_list[0]['profile'] = "compute"
|
||||
node_properties = {"cpus": "1",
|
||||
"memory_mb": "2048",
|
||||
"local_gb": "30",
|
||||
"cpu_arch": "amd64",
|
||||
"capabilities": "num_nics:6,profile:compute",
|
||||
"root_device": {"serial": "abcdef"}}
|
||||
ironic = mock.MagicMock()
|
||||
nodes.register_all_nodes(node_list, client=ironic)
|
||||
pxe_node_driver_info = {"ipmi_address": "foo.bar",
|
||||
"ipmi_username": "test",
|
||||
"ipmi_password": "random"}
|
||||
pxe_node = mock.call(driver="ipmi",
|
||||
name='node1',
|
||||
driver_info=pxe_node_driver_info,
|
||||
resource_class='baremetal',
|
||||
properties=node_properties)
|
||||
port_call = mock.call(node_uuid=ironic.node.create.return_value.uuid,
|
||||
address='aaa', physical_network='ctlplane',
|
||||
local_link_connection=None)
|
||||
ironic.node.create.assert_has_calls([pxe_node, mock.ANY])
|
||||
ironic.port.create.assert_has_calls([port_call])
|
||||
|
||||
def test_register_all_nodes_with_interfaces(self):
|
||||
interfaces = {'boot_interface': 'pxe',
|
||||
'console_interface': 'ipmitool-socat',
|
||||
|
@ -596,6 +622,53 @@ class NodesTest(base.TestCase):
|
|||
nodes._update_or_register_ironic_node(node, node_map, client=ironic)
|
||||
ironic.node.update.assert_called_once_with(1, mock.ANY)
|
||||
|
||||
def test_register_update_profile(self):
|
||||
interfaces = {'boot_interface': 'pxe',
|
||||
'console_interface': 'ipmitool-socat',
|
||||
'deploy_interface': 'direct',
|
||||
'inspect_interface': 'inspector',
|
||||
'management_interface': 'ipmitool',
|
||||
'network_interface': 'neutron',
|
||||
'power_interface': 'ipmitool',
|
||||
'raid_interface': 'agent',
|
||||
'rescue_interface': 'agent',
|
||||
'storage_interface': 'cinder',
|
||||
'vendor_interface': 'ipmitool'}
|
||||
|
||||
node = self._get_node()
|
||||
node.update(interfaces)
|
||||
node['root_device'] = {'serial': 'abcdef'}
|
||||
node['profile'] = 'compute'
|
||||
ironic = mock.MagicMock()
|
||||
node_map = {'mac': {'aaa': 1}}
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
update_patch = [
|
||||
{'path': '/name', 'value': 'node1'},
|
||||
{'path': '/driver_info/ipmi_password', 'value': 'random'},
|
||||
{'path': '/driver_info/ipmi_address', 'value': 'foo.bar'},
|
||||
{'path': '/properties/memory_mb', 'value': '2048'},
|
||||
{'path': '/properties/local_gb', 'value': '30'},
|
||||
{'path': '/properties/cpu_arch', 'value': 'amd64'},
|
||||
{'path': '/properties/cpus', 'value': '1'},
|
||||
{'path': '/properties/capabilities',
|
||||
'value': 'num_nics:6,profile:compute'},
|
||||
{'path': '/properties/root_device',
|
||||
'value': {'serial': 'abcdef'}},
|
||||
{'path': '/driver_info/ipmi_username', 'value': 'test'}]
|
||||
for iface, value in interfaces.items():
|
||||
update_patch.append({'path': '/%s' % iface, 'value': value})
|
||||
for key in update_patch:
|
||||
key['op'] = 'add'
|
||||
self.assertThat(update_patch,
|
||||
matchers.MatchesSetwise(*(map(matchers.Equals,
|
||||
args[1]))))
|
||||
return mock.Mock(uuid='uuid1')
|
||||
|
||||
ironic.node.update.side_effect = side_effect
|
||||
nodes._update_or_register_ironic_node(node, node_map, client=ironic)
|
||||
ironic.node.update.assert_called_once_with(1, mock.ANY)
|
||||
|
||||
def test_register_update_with_images(self):
|
||||
node = self._get_node()
|
||||
node['kernel_id'] = 'image-k'
|
||||
|
|
|
@ -389,10 +389,15 @@ def register_ironic_node(node, client):
|
|||
extra = dict(tripleo_platform=platform)
|
||||
|
||||
if 'capabilities' in node:
|
||||
caps = node['capabilities']
|
||||
if isinstance(caps, dict):
|
||||
caps = dict_to_capabilities(caps)
|
||||
properties.update({"capabilities": six.text_type(caps)})
|
||||
caps = capabilities_to_dict(node['capabilities'])
|
||||
else:
|
||||
caps = {}
|
||||
|
||||
if 'profile' in node:
|
||||
caps['profile'] = node['profile']
|
||||
|
||||
if caps:
|
||||
properties["capabilities"] = dict_to_capabilities(caps)
|
||||
|
||||
driver = node['pm_type']
|
||||
if handler.hardware_type and handler.hardware_type != driver:
|
||||
|
@ -516,8 +521,15 @@ def _update_or_register_ironic_node(node, node_map, client):
|
|||
patched[path] = value
|
||||
|
||||
if 'capabilities' in node:
|
||||
patched['/properties/capabilities'] = dict_to_capabilities(
|
||||
node.pop('capabilities'))
|
||||
caps = capabilities_to_dict(node.pop('capabilities'))
|
||||
else:
|
||||
caps = {}
|
||||
|
||||
if 'profile' in node:
|
||||
caps['profile'] = node.pop('profile')
|
||||
|
||||
if caps:
|
||||
patched['/properties/capabilities'] = dict_to_capabilities(caps)
|
||||
|
||||
driver_info = handler.convert(node)
|
||||
for key, value in driver_info.items():
|
||||
|
|
Loading…
Reference in New Issue