diff --git a/ironic/api/controllers/v1/node.py b/ironic/api/controllers/v1/node.py index 5cb2ccce98..4ccc07e146 100644 --- a/ironic/api/controllers/v1/node.py +++ b/ironic/api/controllers/v1/node.py @@ -635,7 +635,9 @@ class Node(base.APIBase): return self._chassis_uuid def _set_chassis_uuid(self, value): - if value and self._chassis_uuid != value: + if value in (wtypes.Unset, None): + self._chassis_uuid = value + elif self._chassis_uuid != value: try: chassis = objects.Chassis.get(pecan.request.context, value) self._chassis_uuid = chassis.uuid @@ -648,8 +650,6 @@ class Node(base.APIBase): # response for a POST request to create a Port e.code = http_client.BAD_REQUEST raise - elif value == wtypes.Unset: - self._chassis_uuid = wtypes.Unset uuid = types.uuid """Unique UUID for this node""" diff --git a/ironic/tests/unit/api/v1/test_nodes.py b/ironic/tests/unit/api/v1/test_nodes.py index 4d3078df32..9de3e186eb 100644 --- a/ironic/tests/unit/api/v1/test_nodes.py +++ b/ironic/tests/unit/api/v1/test_nodes.py @@ -1662,9 +1662,12 @@ class TestPost(test_api_base.BaseApiTest): self.addCleanup(p.stop) @mock.patch.object(timeutils, 'utcnow') - def _test_create_node(self, mock_utcnow, headers=None, **kwargs): + def _test_create_node(self, mock_utcnow, headers=None, + remove_chassis_uuid=False, **kwargs): headers = headers or {} ndict = test_api_utils.post_get_test_node(**kwargs) + if remove_chassis_uuid: + del ndict['chassis_uuid'] test_time = datetime.datetime(2000, 1, 1, 0, 0) mock_utcnow.return_value = test_time response = self.post_json('/nodes', ndict, @@ -1687,6 +1690,20 @@ class TestPost(test_api_base.BaseApiTest): def test_create_node(self): self._test_create_node() + def test_create_node_chassis_uuid_always_in_response(self): + result = self._test_create_node(chassis_uuid=None) + self.assertEqual(None, result['chassis_uuid']) + result = self._test_create_node(uuid=uuidutils.generate_uuid(), + remove_chassis_uuid=True) + self.assertEqual(None, result['chassis_uuid']) + + def test_create_node_invalid_chassis(self): + ndict = test_api_utils.post_get_test_node(chassis_uuid=0) + response = self.post_json('/nodes', ndict, expect_errors=True) + self.assertEqual(http_client.BAD_REQUEST, response.status_int) + self.assertEqual('application/json', response.content_type) + self.assertTrue(response.json['error_message']) + def test_create_node_explicit_network_interface(self): headers = {api_base.Version.string: '1.20'} result = self._test_create_node(headers=headers, diff --git a/releasenotes/notes/always-return-chassis-uuid-4eecbc8da2170cb1.yaml b/releasenotes/notes/always-return-chassis-uuid-4eecbc8da2170cb1.yaml new file mode 100644 index 0000000000..4255d2800f --- /dev/null +++ b/releasenotes/notes/always-return-chassis-uuid-4eecbc8da2170cb1.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - Fixed an issue of not returning ``chassis_uuid`` field of a node in API + responses if it does not belong to a chassis. It should be always returned, + either set to None, or to a corresponding chassis UUID.