From 1d7b2b8d3d19919d3e3e68b8021f5bf7dd9e7ad9 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 22 Jun 2015 09:15:48 -0400 Subject: [PATCH] register-nodes: add support for node capabilites This patch makes it possible to configure "capabilities" when registering nodes in the Ironic API. The ability to register arbitrary capabilities makes it possible to more easily deploy on heterogeneous sets of bare metal where you want to control which roles run on which hardware (by using the compute capabilities filter in Nova). Previously it was possible to add these capabilities manually using 'ironic node-update add properties...'. Using the CLI works fine for ad-hoc settings but it makes sense to allow users to easily assign and manage capabilites when nodes are created (or updated) with register-nodes JSON files as well. Change-Id: Iffd0274dadaf82a8913baa1c9e06e8478716ed6d --- os_cloud_config/nodes.py | 7 +++++++ os_cloud_config/tests/test_nodes.py | 15 +++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/os_cloud_config/nodes.py b/os_cloud_config/nodes.py index e43a0ba..e53c939 100644 --- a/os_cloud_config/nodes.py +++ b/os_cloud_config/nodes.py @@ -112,6 +112,10 @@ def register_ironic_node(service_host, node, client=None, blocking=True): "cpu_arch": node["arch"]} driver_info = _extract_driver_info(node) + if 'capabilities' in node: + properties.update({"capabilities": + six.text_type(node.get('capabilities'))}) + create_map = {"driver": node["pm_type"], "properties": properties, "driver_info": driver_info} @@ -230,6 +234,9 @@ def _update_or_register_ironic_node(service_host, node, node_map, client=None, if "name" in node: massage_map.update({'name': '/name'}) + if "capabilities" in node: + massage_map.update({'capabilities': '/properties/capabilities'}) + if node_uuid: ironic_node = client.node.get(node_uuid) else: diff --git a/os_cloud_config/tests/test_nodes.py b/os_cloud_config/tests/test_nodes.py index 1cca96e..f4bb237 100644 --- a/os_cloud_config/tests/test_nodes.py +++ b/os_cloud_config/tests/test_nodes.py @@ -29,7 +29,8 @@ class NodesTest(base.TestCase): def _get_node(self): return {'cpu': '1', 'memory': '2048', 'disk': '30', 'arch': 'amd64', 'mac': ['aaa'], 'pm_addr': 'foo.bar', 'pm_user': 'test', - 'pm_password': 'random', 'pm_type': 'pxe_ssh', 'name': 'node1'} + 'pm_password': 'random', 'pm_type': 'pxe_ssh', 'name': 'node1', + 'capabilities': 'num_nics:6'} @mock.patch('os_cloud_config.nodes.using_ironic', return_value=False) def test_register_all_nodes_nova_bm(self, ironic_mock): @@ -218,7 +219,8 @@ class NodesTest(base.TestCase): node_properties = {"cpus": "1", "memory_mb": "2048", "local_gb": "30", - "cpu_arch": "amd64"} + "cpu_arch": "amd64", + "capabilities": "num_nics:6"} ironic = mock.MagicMock() nodes.register_all_nodes('servicehost', node_list, client=ironic) pxe_node_driver_info = {"ssh_address": "foo.bar", @@ -243,7 +245,8 @@ class NodesTest(base.TestCase): node_properties = {"cpus": "1", "memory_mb": "2048", "local_gb": "30", - "cpu_arch": "amd64"} + "cpu_arch": "amd64", + "capabilities": "num_nics:6"} ironic = mock.MagicMock() glance = mock.MagicMock() image = collections.namedtuple('image', ['id']) @@ -307,6 +310,7 @@ class NodesTest(base.TestCase): {'path': '/properties/local_gb', 'value': '30'}, {'path': '/properties/cpu_arch', 'value': 'amd64'}, {'path': '/properties/cpus', 'value': '1'}, + {'path': '/properties/capabilities', 'value': 'num_nics:6'}, {'path': '/driver_info/ssh_username', 'value': 'test'}] for key in update_patch: key['op'] = 'replace' @@ -354,6 +358,7 @@ class NodesTest(base.TestCase): {'path': '/properties/local_gb', 'value': '30'}, {'path': '/properties/cpu_arch', 'value': 'amd64'}, {'path': '/properties/cpus', 'value': '1'}, + {'path': '/properties/capabilities', 'value': 'num_nics:6'}, {'path': '/driver_info/ssh_username', 'value': 'test'}] for key in update_patch: key['op'] = 'replace' @@ -381,7 +386,8 @@ class NodesTest(base.TestCase): node_properties = {"cpus": "1", "memory_mb": "2048", "local_gb": "30", - "cpu_arch": "amd64"} + "cpu_arch": "amd64", + "capabilities": "num_nics:6"} node = self._get_node() node['cpu'] = 1 node['memory'] = 2048 @@ -410,6 +416,7 @@ class NodesTest(base.TestCase): {'path': '/properties/local_gb', 'value': '30'}, {'path': '/properties/cpu_arch', 'value': 'amd64'}, {'path': '/properties/cpus', 'value': '1'}, + {'path': '/properties/capabilities', 'value': 'num_nics:6'}, {'path': '/driver_info/ssh_username', 'value': 'test'}] for key in update_patch: key['op'] = 'replace'