driver_internal_info in provision notifications

Adds the node's driver_internal_info to the
baremetal.node.provision_set.* notifications. The
driver_internal_info includes useful information
such as deploy and clean steps.

Change-Id: I98784f72e6f93cbc602753ef2da0dbef5ad2c9cf
Story: #2008054
This commit is contained in:
Ruby Loo 2020-08-25 18:11:04 +00:00
parent a2ccff668e
commit 3945fa4c2b
6 changed files with 103 additions and 8 deletions

View File

@ -916,13 +916,16 @@ class NodeSetProvisionStatePayload(NodePayload):
# Version 1.13: Parent NodePayload version 1.13
# Version 1.14: Parent NodePayload version 1.14
# Version 1.15: Parent NodePayload version 1.15
VERSION = '1.15'
# Version 1.16: add driver_internal_info
VERSION = '1.16'
SCHEMA = dict(NodePayload.SCHEMA,
**{'instance_info': ('node', 'instance_info')})
**{'instance_info': ('node', 'instance_info'),
'driver_internal_info': ('node', 'driver_internal_info')})
fields = {
'instance_info': object_fields.FlexibleDictField(nullable=True),
'driver_internal_info': object_fields.FlexibleDictField(nullable=True),
'event': object_fields.StringField(nullable=True),
'previous_provision_state': object_fields.StringField(nullable=True),
'previous_target_provision_state':

View File

@ -188,11 +188,13 @@ class NotificationPublisher(base.IronicObject):
def mask_secrets(payload):
"""Remove secrets from payload object."""
mask = '******'
dict_fields = ['instance_info', 'driver_info', 'driver_internal_info']
for f in dict_fields:
if hasattr(payload, f):
masked = strutils.mask_dict_password(getattr(payload, f), mask)
setattr(payload, f, masked)
if hasattr(payload, 'instance_info'):
payload.instance_info = strutils.mask_dict_password(
payload.instance_info, mask)
if 'image_url' in payload.instance_info:
payload.instance_info['image_url'] = mask
if hasattr(payload, 'driver_info'):
payload.driver_info = strutils.mask_dict_password(
payload.driver_info, mask)

View File

@ -1282,6 +1282,8 @@ class TestNodePayloads(db_base.DbTestCase):
'DEPLOYING', 'DEPLOY')
self._test_node_payload(payload)
self.assertEqual(self.node.instance_info, payload.instance_info)
self.assertEqual(self.node.driver_internal_info,
payload.driver_internal_info)
self.assertEqual('DEPLOY', payload.event)
self.assertEqual('AVAILABLE', payload.previous_provision_state)
self.assertEqual('DEPLOYING', payload.previous_target_provision_state)

View File

@ -36,6 +36,16 @@ class TestNotificationBase(test_base.TestCase):
'fake_field_1': fields.StringField(nullable=True),
}
@base.IronicObjectRegistry.register_if(False)
class TestObjectMaskSecrets(base.IronicObject):
VERSION = '1.0'
fields = {
'instance_info': fields.FlexibleDictField(nullable=True),
'driver_info': fields.FlexibleDictField(nullable=True),
'driver_internal_info': fields.FlexibleDictField(nullable=True),
'some_dict': fields.FlexibleDictField(nullable=True),
}
@base.IronicObjectRegistry.register_if(False)
class TestNotificationPayload(notification.NotificationPayloadBase):
VERSION = '1.0'
@ -61,6 +71,25 @@ class TestNotificationBase(test_base.TestCase):
'fake_field': fields.StringField()
}
@base.IronicObjectRegistry.register_if(False)
class TestNotificationPayloadMaskSecrets(
notification.NotificationPayloadBase):
VERSION = '1.0'
SCHEMA = {
'instance_info': ('test_obj', 'instance_info'),
'driver_info': ('test_obj', 'driver_info'),
'driver_internal_info': ('test_obj', 'driver_internal_info'),
'some_dict': ('test_obj', 'some_dict'),
}
fields = {
'instance_info': fields.FlexibleDictField(nullable=True),
'driver_info': fields.FlexibleDictField(nullable=True),
'driver_internal_info': fields.FlexibleDictField(nullable=True),
'some_dict': fields.FlexibleDictField(nullable=True),
}
@base.IronicObjectRegistry.register_if(False)
class TestNotification(notification.NotificationBase):
VERSION = '1.0'
@ -281,3 +310,57 @@ class TestNotificationBase(test_base.TestCase):
event_type = notification.EventType(
object='test_object', action='test', status='start')
self.assertRaises(ValueError, make_status_invalid)
def test_mask_secrets_not_affected(self):
payload = self.TestNotificationPayload(an_extra_field='extra',
an_optional_field=1)
payload.populate_schema(test_obj=self.fake_obj)
notification.mask_secrets(payload)
self.assertEqual('extra', payload.an_extra_field)
self.assertEqual(1, payload.an_optional_field)
self.assertEqual(self.fake_obj.fake_field_1, payload.fake_field_a)
self.assertEqual(self.fake_obj.fake_field_2, payload.fake_field_b)
def test_mask_secrets_no_secrets(self):
instance_info = {'inst1': 'v1'}
driver_info = {'driver_i1': 'd1'}
driver_internal_info = {'driver_int1': 'dii1'}
some_dict = {'key1': 'v1'}
test_obj = self.TestObjectMaskSecrets(
instance_info=instance_info,
driver_info=driver_info,
driver_internal_info=driver_internal_info,
some_dict=some_dict)
payload = self.TestNotificationPayloadMaskSecrets()
payload.populate_schema(test_obj=test_obj)
notification.mask_secrets(payload)
self.assertEqual(test_obj.instance_info, payload.instance_info)
self.assertEqual(test_obj.driver_info, payload.driver_info)
self.assertEqual(test_obj.driver_internal_info,
payload.driver_internal_info)
self.assertEqual(test_obj.some_dict, payload.some_dict)
def test_mask_secrets_has_secrets(self):
instance_info = {'configdrive': 'somestuffhere',
'image_url': 'http://image_to_fetch'}
driver_info = {'password': 'some password'}
driver_internal_info = {'agent_secret_token': '123532234145'}
some_dict = {'password': 'another password'}
test_obj = self.TestObjectMaskSecrets(
instance_info=instance_info,
driver_info=driver_info,
driver_internal_info=driver_internal_info,
some_dict=some_dict)
payload = self.TestNotificationPayloadMaskSecrets()
payload.populate_schema(test_obj=test_obj)
notification.mask_secrets(payload)
self.assertNotEqual(test_obj.instance_info, payload.instance_info)
self.assertEqual('******', payload.instance_info['configdrive'])
self.assertEqual('******', payload.instance_info['image_url'])
self.assertNotEqual(test_obj.driver_info, payload.driver_info)
self.assertEqual('******', payload.driver_info['password'])
self.assertNotEqual(test_obj.driver_internal_info,
payload.driver_internal_info)
self.assertEqual('******',
payload.driver_internal_info['agent_secret_token'])
self.assertEqual(test_obj.some_dict, payload.some_dict)

View File

@ -692,7 +692,7 @@ expected_object_fingerprints = {
'NodeCorrectedPowerStatePayload': '1.15-59a224a9191cdc9f1acc2e0dcd2d3adb',
'NodeSetProvisionStateNotification':
'1.0-59acc533c11d306f149846f922739c15',
'NodeSetProvisionStatePayload': '1.15-488a3d62a0643d17e288ecf89ed5bbb4',
'NodeSetProvisionStatePayload': '1.16-c5a8eea43c514baf721fc61ce5d9d5a4',
'VolumeConnector': '1.0-3e0252c0ab6e6b9d158d09238a577d97',
'VolumeTarget': '1.0-0b10d663d8dae675900b2c7548f76f5e',
'ChassisCRUDNotification': '1.0-59acc533c11d306f149846f922739c15',

View File

@ -0,0 +1,5 @@
---
features:
- |
Adds ``driver_internal_info`` field to the node-related notification
``baremetal.node.provision_set.*``, new payload version 1.16.