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