From 9c45a284d08bbe68dedc33c8cb85d8b60b0a46ec Mon Sep 17 00:00:00 2001 From: Hironori Shiina Date: Mon, 5 Jun 2017 10:28:32 +0900 Subject: [PATCH] Change volume metadata not to use nested dicts Ironic sets metadata to a volume when attaching and detaching. However, Cinder doesn't accept metadata which consists of nested dictionaries. This patch fixes the issue by passing metadata as string without nested dictionaries. Change-Id: Ibe0a752a923ff52526a7e04374e61c14f6c4f0b0 Partial-Bug: #1559691 --- ironic/common/cinder.py | 8 ++++---- ironic/tests/unit/common/test_cinder.py | 24 ++++++++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/ironic/common/cinder.py b/ironic/common/cinder.py index bc20b1e33b..72b8e34343 100644 --- a/ironic/common/cinder.py +++ b/ironic/common/cinder.py @@ -13,6 +13,7 @@ # under the License. import datetime +import json from cinderclient import exceptions as cinder_exceptions from cinderclient.v3 import client as client @@ -120,11 +121,10 @@ def _create_metadata_dictionary(node, action): :returns: Metadata dictionary for volume. """ label = "ironic_node_%s" % node.uuid - return { - label: { - 'instance_uuid': node.instance_uuid or node.uuid, + data = {'instance_uuid': node.instance_uuid or node.uuid, 'last_seen': datetime.datetime.utcnow().isoformat(), - 'last_action': action}} + 'last_action': action} + return {label: json.dumps(data)} def _init_client(task): diff --git a/ironic/tests/unit/common/test_cinder.py b/ironic/tests/unit/common/test_cinder.py index d20bbd5fc4..ba598aaa63 100644 --- a/ironic/tests/unit/common/test_cinder.py +++ b/ironic/tests/unit/common/test_cinder.py @@ -11,6 +11,8 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime +import json from cinderclient import exceptions as cinder_exceptions import cinderclient.v3 as cinderclient @@ -152,20 +154,22 @@ class TestCinderUtils(db_base.DbTestCase): self.assertIsNone(cinder._get_attachment_id(self.node, unattached)) self.assertIsNone(cinder._get_attachment_id(self.node, no_attachment)) - def test__create_metadata_dictionary(self): + @mock.patch.object(datetime, 'datetime') + def test__create_metadata_dictionary(self, mock_datetime): + fake_time = '2017-06-05T00:33:26.574676' + mock_utcnow = mock.Mock() + mock_datetime.utcnow.return_value = mock_utcnow + mock_utcnow.isoformat.return_value = fake_time expected_key = ("ironic_node_%s" % self.node.uuid) - expected = { - expected_key: { - 'instance_uuid': self.node.instance_uuid, - 'last_seen': 'faked-time', - 'last_action': 'meow' - } + expected_data = { + 'instance_uuid': self.node.instance_uuid, + 'last_seen': fake_time, + 'last_action': 'meow' } result = cinder._create_metadata_dictionary(self.node, 'meow') - self.assertIsInstance(result[expected_key]['last_seen'], str) - result[expected_key]['last_seen'] = 'faked-time' - self.assertEqual(expected, result) + data = json.loads(result[expected_key]) + self.assertEqual(expected_data, data) @mock.patch.object(cinder, '_get_cinder_session', autospec=True)