From 551fd9d75aea05aabf8a7a86991fb9bb0a38a4bd Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Mon, 8 Jan 2018 17:34:50 +0000 Subject: [PATCH] Implement get_traits() for the ironic virt driver Implement the get_traits() method for the ironic virt driver. This allows ironic nodes with traits set to have those traits registered with the approriate resource provider in the placement API. The ironic client version has been bumped to 1.37 in order to query nodes' traits. blueprint ironic-driver-traits Change-Id: I4065b61edff8bfd66a163c9ccf19833316fdca8e Depends-On: https://review.openstack.org/538066 --- .../unit/virt/ironic/test_client_wrapper.py | 10 ++++----- nova/tests/unit/virt/ironic/test_driver.py | 21 +++++++++++++++++++ nova/tests/unit/virt/ironic/utils.py | 1 + nova/virt/ironic/client_wrapper.py | 2 +- nova/virt/ironic/driver.py | 11 +++++++++- test-requirements.txt | 2 +- 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/nova/tests/unit/virt/ironic/test_client_wrapper.py b/nova/tests/unit/virt/ironic/test_client_wrapper.py index 3b9a884ede82..c6f66d982ee9 100644 --- a/nova/tests/unit/virt/ironic/test_client_wrapper.py +++ b/nova/tests/unit/virt/ironic/test_client_wrapper.py @@ -81,12 +81,12 @@ class IronicClientWrapperTestCase(test.NoDBTestCase): # nova.utils.get_ksa_adapter().get_endpoint() self.get_ksa_adapter.assert_called_once_with( 'baremetal', ksa_auth=self.get_auth_plugin.return_value, - ksa_session='session', min_version=(1, 35), + ksa_session='session', min_version=(1, 37), max_version=(1, ksa_disc.LATEST)) expected = {'session': 'session', 'max_retries': CONF.ironic.api_max_retries, 'retry_interval': CONF.ironic.api_retry_interval, - 'os_ironic_api_version': '1.35', + 'os_ironic_api_version': '1.37', 'ironic_url': self.get_ksa_adapter.return_value.get_endpoint.return_value} mock_ir_cli.assert_called_once_with(1, **expected) @@ -106,13 +106,13 @@ class IronicClientWrapperTestCase(test.NoDBTestCase): # nova.utils.get_endpoint_data self.get_ksa_adapter.assert_called_once_with( 'baremetal', ksa_auth=self.get_auth_plugin.return_value, - ksa_session='session', min_version=(1, 35), + ksa_session='session', min_version=(1, 37), max_version=(1, ksa_disc.LATEST)) # When get_endpoint_data raises any ServiceNotFound, None is returned. expected = {'session': 'session', 'max_retries': CONF.ironic.api_max_retries, 'retry_interval': CONF.ironic.api_retry_interval, - 'os_ironic_api_version': '1.35', + 'os_ironic_api_version': '1.37', 'ironic_url': None} mock_ir_cli.assert_called_once_with(1, **expected) @@ -130,7 +130,7 @@ class IronicClientWrapperTestCase(test.NoDBTestCase): expected = {'session': 'session', 'max_retries': CONF.ironic.api_max_retries, 'retry_interval': CONF.ironic.api_retry_interval, - 'os_ironic_api_version': '1.35', + 'os_ironic_api_version': '1.37', 'ironic_url': endpoint} mock_ir_cli.assert_called_once_with(1, **expected) diff --git a/nova/tests/unit/virt/ironic/test_driver.py b/nova/tests/unit/virt/ironic/test_driver.py index cbaff6ed0115..dadc6b8c759e 100644 --- a/nova/tests/unit/virt/ironic/test_driver.py +++ b/nova/tests/unit/virt/ironic/test_driver.py @@ -953,6 +953,27 @@ class IronicDriverTestCase(test.NoDBTestCase): mock_res_unavail.assert_called_once_with(mock_nfc.return_value) self.assertEqual({}, result) + @mock.patch.object(ironic_driver.IronicDriver, '_node_from_cache') + def test_get_traits_no_traits(self, mock_nfc): + """Ensure that when the node has no traits, we return no traits.""" + node = ironic_utils.get_test_node() + mock_nfc.return_value = node + result = self.driver.get_traits(node.uuid) + + mock_nfc.assert_called_once_with(node.uuid) + self.assertEqual([], result) + + @mock.patch.object(ironic_driver.IronicDriver, '_node_from_cache') + def test_get_traits_with_traits(self, mock_nfc): + """Ensure that when the node has traits, we return the traits.""" + node = ironic_utils.get_test_node(traits=['trait1', 'trait2']) + mock_nfc.return_value = node + result = self.driver.get_traits(node.uuid) + + expected = ['trait1', 'trait2'] + mock_nfc.assert_called_once_with(node.uuid) + self.assertEqual(expected, result) + @mock.patch.object(FAKE_CLIENT.node, 'get') @mock.patch.object(FAKE_CLIENT.node, 'list') @mock.patch.object(objects.InstanceList, 'get_uuids_by_host') diff --git a/nova/tests/unit/virt/ironic/utils.py b/nova/tests/unit/virt/ironic/utils.py index 733dc43568aa..d34de55b66fe 100644 --- a/nova/tests/unit/virt/ironic/utils.py +++ b/nova/tests/unit/virt/ironic/utils.py @@ -48,6 +48,7 @@ def get_test_node(**kw): 'maintenance': kw.get('maintenance', False), 'network_interface': kw.get('network_interface'), 'resource_class': kw.get('resource_class'), + 'traits': kw.get('traits', []), 'extra': kw.get('extra', {}), 'updated_at': kw.get('created_at'), 'created_at': kw.get('updated_at')})() diff --git a/nova/virt/ironic/client_wrapper.py b/nova/virt/ironic/client_wrapper.py index 4190df658a59..3f767af0e05b 100644 --- a/nova/virt/ironic/client_wrapper.py +++ b/nova/virt/ironic/client_wrapper.py @@ -32,7 +32,7 @@ ironic = None IRONIC_GROUP = nova.conf.ironic.ironic_group # The API version required by the Ironic driver -IRONIC_API_VERSION = (1, 35) +IRONIC_API_VERSION = (1, 37) class IronicClientWrapper(object): diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index 04bbb6764be7..5b25678f0878 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -76,7 +76,7 @@ _UNPROVISION_STATES = (ironic_states.ACTIVE, ironic_states.DEPLOYFAIL, _NODE_FIELDS = ('uuid', 'power_state', 'target_power_state', 'provision_state', 'target_provision_state', 'last_error', 'maintenance', - 'properties', 'instance_uuid') + 'properties', 'instance_uuid', 'traits') # Console state checking interval in seconds _CONSOLE_STATE_CHECKING_INTERVAL = 1 @@ -813,6 +813,15 @@ class IronicDriver(virt_driver.ComputeDriver): return result + def get_traits(self, nodename): + """Get the traits for a given node. + + :param nodename: the UUID of the node. + :returns: an iterable of traits for the supplied node. + """ + node = self._node_from_cache(nodename) + return list(node.traits) + def get_available_resource(self, nodename): """Retrieve resource information. diff --git a/test-requirements.txt b/test-requirements.txt index 54a9bd2baf0a..8241ab26bfae 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -11,7 +11,7 @@ mox3>=0.20.0 # Apache-2.0 psycopg2>=2.6.2 # LGPL/ZPL PyMySQL>=0.7.6 # MIT License python-barbicanclient!=4.5.0,!=4.5.1,>=4.0.0 # Apache-2.0 -python-ironicclient>=1.14.0 # Apache-2.0 +python-ironicclient>=2.2.0 # Apache-2.0 requests-mock>=1.1.0 # Apache-2.0 sphinx!=1.6.6,>=1.6.2 # BSD sphinxcontrib-actdiag>=0.8.5 # BSD