From 973dd160b3eceef4af76409f4d82698545fd3edd Mon Sep 17 00:00:00 2001 From: Sam Betts Date: Fri, 18 Sep 2015 13:55:59 +0100 Subject: [PATCH] Convert eDeploy data so that rules can process it eDeploy's return format is a list of lists, in order to use it with introspection rules we must convert it to dictionary format. This patch detects if the data is in eDeploy's format and will convert it storing the new data in introspection_data['extra']. introspection_data['data'] is assumed unusable by introspection rules and will always be removed from introspection_data after the data is stored in swift. Change-Id: I25c7ef1f3d3122b80ea98e4d0e64ea20e2eec618 Closes-Bug: #1495649 --- ironic_inspector/plugins/extra_hardware.py | 42 +++++++++++++++++-- .../test/test_plugins_extra_hardware.py | 38 ++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/ironic_inspector/plugins/extra_hardware.py b/ironic_inspector/plugins/extra_hardware.py index 4cd30b2ba..fa5dd2f20 100644 --- a/ironic_inspector/plugins/extra_hardware.py +++ b/ironic_inspector/plugins/extra_hardware.py @@ -29,8 +29,8 @@ from ironic_inspector.plugins import base CONF = cfg.CONF - LOG = log.getLogger('ironic_inspector.plugins.extra_hardware') +EDEPLOY_ITEM_SIZE = 4 class ExtraHardwareHook(base.ProcessingHook): @@ -54,10 +54,46 @@ class ExtraHardwareHook(base.ProcessingHook): LOG.warning(_LW('No extra hardware information was received from ' 'the ramdisk')) return + data = introspection_data['data'] name = 'extra_hardware-%s' % node_info.uuid - self._store_extra_hardware(name, - json.dumps(introspection_data['data'])) + self._store_extra_hardware(name, json.dumps(data)) + + # NOTE(sambetts) If data is edeploy format, convert to dicts for rules + # processing, store converted data in introspection_data['extra']. + # Delete introspection_data['data'], it is assumed unusable + # by rules. + if self._is_edeploy_data(data): + LOG.debug('Extra hardware data is in eDeploy format, ' + 'converting to usable format.') + introspection_data['extra'] = self._convert_edeploy_data(data) + else: + LOG.warning(_LW('Extra hardware data was not in a recognised ' + 'format (eDeploy), and will not be forwarded to ' + 'introspection rules.')) + + LOG.debug('Deleting \"data\" key from introspection data as it is ' + 'assumed unusable by introspection rules. Raw data is ' + 'stored in swift.') + del introspection_data['data'] node_info.patch([{'op': 'add', 'path': '/extra/hardware_swift_object', 'value': name}]) + + def _is_edeploy_data(self, data): + return all(isinstance(item, list) and len(item) == EDEPLOY_ITEM_SIZE + for item in data) + + def _convert_edeploy_data(self, data): + converted = {} + for item in data: + converted_0 = converted.setdefault(item[0], {}) + converted_1 = converted_0.setdefault(item[1], {}) + + try: + item[3] = int(item[3]) + except ValueError: + pass + + converted_1[item[2]] = item[3] + return converted diff --git a/ironic_inspector/test/test_plugins_extra_hardware.py b/ironic_inspector/test/test_plugins_extra_hardware.py index 09a6789c7..84c44371b 100644 --- a/ironic_inspector/test/test_plugins_extra_hardware.py +++ b/ironic_inspector/test/test_plugins_extra_hardware.py @@ -30,17 +30,53 @@ class TestExtraHardware(test_base.NodeTest): 'data': [['memory', 'total', 'size', '4294967296'], ['cpu', 'physical', 'number', '1'], ['cpu', 'logical', 'number', '1']]} + data = json.dumps(introspection_data['data']) self.hook.before_processing(introspection_data) self.hook.before_update(introspection_data, self.node_info) swift_conn = swift_mock.return_value name = 'extra_hardware-%s' % self.uuid - data = json.dumps(introspection_data['data']) swift_conn.create_object.assert_called_once_with(name, data) patch_mock.assert_called_once_with( [{'op': 'add', 'path': '/extra/hardware_swift_object', 'value': name}]) + expected = { + 'memory': { + 'total': { + 'size': 4294967296 + } + }, + 'cpu': { + 'physical': { + 'number': 1 + }, + 'logical': { + 'number': 1 + }, + } + } + + self.assertEqual(expected, introspection_data['extra']) + + def test_data_not_in_edeploy_format(self, patch_mock, swift_mock): + introspection_data = { + 'data': [['memory', 'total', 'size', '4294967296'], + ['cpu', 'physical', 'number', '1'], + {'interface': 'eth1'}]} + data = json.dumps(introspection_data['data']) + self.hook.before_processing(introspection_data) + self.hook.before_update(introspection_data, self.node_info) + + swift_conn = swift_mock.return_value + name = 'extra_hardware-%s' % self.uuid + swift_conn.create_object.assert_called_once_with(name, data) + patch_mock.assert_called_once_with( + [{'op': 'add', 'path': '/extra/hardware_swift_object', + 'value': name}]) + + self.assertFalse('data' in introspection_data) + def test_no_data_recieved(self, patch_mock, swift_mock): introspection_data = {'cats': 'meow'} swift_conn = swift_mock.return_value