def test_node_notification_mask_secrets(self): test_info = {'password': '******', 'some_value': 'fake-value'} node = obj_utils.get_test_node(self.context, driver_info=test_info) notification.mask_secrets(node) self.assertEqual('******', node.driver_info['password']) self.assertEqual('fake-value', node.driver_info['some_value'])
def test_mask_secrets_has_secrets(self): instance_info = { 'configdrive': 'somestuffhere', 'image_url': 'http://image_to_fetch' } driver_info = {'password': '******'} driver_internal_info = {'agent_secret_token': '123532234145'} some_dict = {'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)
def test_mask_secrets(self): test_info = {'configdrive': 'fake_drive', 'image_url': 'fake-url', 'some_value': 'fake-value'} node = obj_utils.get_test_node(self.context, instance_info=test_info) notification.mask_secrets(node) self.assertEqual('******', node.instance_info['configdrive']) self.assertEqual('******', node.instance_info['image_url']) self.assertEqual('fake-value', node.instance_info['some_value'])
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 _emit_conductor_node_notification(task, notification_method, payload_method, action, level, status, **kwargs): """Helper for emitting a conductor notification about a node. :param task: a TaskManager instance. :param notification_method: Constructor for the notification itself. :param payload_method: Constructor for the notification payload. Node should be first argument of the method. :param action: Action string to go in the EventType. :param level: Notification level. One of `ironic.objects.fields.NotificationLevel.ALL` :param status: Status to go in the EventType. One of `ironic.objects.fields.NotificationStatus.ALL` :param **kwargs: kwargs to use when creating the notification payload. Passed to the payload_method. """ try: # Prepare our exception message just in case exception_values = { "node": task.node.uuid, "action": action, "status": status, "level": level, "notification_method": notification_method.__name__, "payload_method": payload_method.__name__ } exception_message = (_("Failed to send baremetal.node." "%(action)s.%(status)s notification for node " "%(node)s with level %(level)s, " "notification_method %(notification_method)s, " "payload_method %(payload_method)s, error " "%(error)s")) payload = payload_method(task.node, **kwargs) notification.mask_secrets(payload) notification_method(publisher=notification.NotificationPublisher( service='ironic-conductor', host=CONF.host), event_type=notification.EventType(object='node', action=action, status=status), level=level, payload=payload).emit(task.context) except (exception.NotificationSchemaObjectError, exception.NotificationSchemaKeyError, exception.NotificationPayloadError, oslo_msg_exc.MessageDeliveryFailure, oslo_vo_exc.VersionedObjectsException) as e: exception_values['error'] = e LOG.warning(exception_message, exception_values) except Exception as e: # NOTE(mariojv) For unknown exceptions, also log the traceback. exception_values['error'] = e LOG.exception(exception_message, exception_values)
def _emit_conductor_node_notification(task, notification_method, payload_method, action, level, status, **kwargs): """Helper for emitting a conductor notification about a node. :param task: a TaskManager instance. :param notification_method: Constructor for the notification itself. :param payload_method: Constructor for the notification payload. Node should be first argument of the method. :param action: Action string to go in the EventType. :param level: Notification level. One of `ironic.objects.fields.NotificationLevel.ALL` :param status: Status to go in the EventType. One of `ironic.objects.fields.NotificationStatus.ALL` :param **kwargs: kwargs to use when creating the notification payload. Passed to the payload_method. """ try: # Prepare our exception message just in case exception_values = {"node": task.node.uuid, "action": action, "status": status, "level": level, "notification_method": notification_method.__name__, "payload_method": payload_method.__name__} exception_message = (_("Failed to send baremetal.node." "%(action)s.%(status)s notification for node " "%(node)s with level %(level)s, " "notification_method %(notification_method)s, " "payload_method %(payload_method)s, error " "%(error)s")) payload = payload_method(task.node, **kwargs) notification.mask_secrets(payload) notification_method( publisher=notification.NotificationPublisher( service='ironic-conductor', host=CONF.host), event_type=notification.EventType( object='node', action=action, status=status), level=level, payload=payload).emit(task.context) except (exception.NotificationSchemaObjectError, exception.NotificationSchemaKeyError, exception.NotificationPayloadError, oslo_msg_exc.MessageDeliveryFailure, oslo_vo_exc.VersionedObjectsException) as e: exception_values['error'] = e LOG.warning(exception_message, exception_values) except Exception as e: # NOTE(mariojv) For unknown exceptions, also log the traceback. exception_values['error'] = e LOG.exception(exception_message, exception_values)
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 _emit_api_notification(context, obj, action, level, status, **kwargs): """Helper for emitting API notifications. :param context: request context. :param obj: resource rpc object. :param action: Action string to go in the EventType. :param level: Notification level. One of `ironic.objects.fields.NotificationLevel.ALL` :param status: Status to go in the EventType. One of `ironic.objects.fields.NotificationStatus.ALL` :param kwargs: kwargs to use when creating the notification payload. """ resource = obj.__class__.__name__.lower() extra_args = kwargs try: try: if action == 'maintenance_set': notification_method = node_objects.NodeMaintenanceNotification payload_method = node_objects.NodePayload elif resource not in CRUD_NOTIFY_OBJ: notification_name = payload_name = _("is not defined") raise KeyError(_("Unsupported resource: %s") % resource) else: notification_method, payload_method = CRUD_NOTIFY_OBJ[resource] notification_name = notification_method.__name__ payload_name = payload_method.__name__ finally: # Prepare our exception message just in case exception_values = { "resource": resource, "uuid": obj.uuid, "action": action, "status": status, "level": level, "notification_method": notification_name, "payload_method": payload_name } exception_message = (_("Failed to send baremetal.%(resource)s." "%(action)s.%(status)s notification for " "%(resource)s %(uuid)s with level " "%(level)s, notification method " "%(notification_method)s, payload method " "%(payload_method)s, error %(error)s")) payload = payload_method(obj, **extra_args) if resource == 'node': notification.mask_secrets(payload) notification_method(publisher=notification.NotificationPublisher( service='ironic-api', host=CONF.host), event_type=notification.EventType(object=resource, action=action, status=status), level=level, payload=payload).emit(context) except (exception.NotificationSchemaObjectError, exception.NotificationSchemaKeyError, exception.NotificationPayloadError, oslo_msg_exc.MessageDeliveryFailure, oslo_vo_exc.VersionedObjectsException) as e: exception_values['error'] = e LOG.warning(exception_message, exception_values) except Exception as e: exception_values['error'] = e LOG.exception(exception_message, exception_values)
def _emit_api_notification(context, obj, action, level, status, **kwargs): """Helper for emitting API notifications. :param context: request context. :param obj: resource rpc object. :param action: Action string to go in the EventType. :param level: Notification level. One of `ironic.objects.fields.NotificationLevel.ALL` :param status: Status to go in the EventType. One of `ironic.objects.fields.NotificationStatus.ALL` :param kwargs: kwargs to use when creating the notification payload. """ resource = obj.__class__.__name__.lower() # value wsme.Unset can be passed from API representation of resource extra_args = {k: (v if v != wtypes.Unset else None) for k, v in kwargs.items()} try: try: if action == 'maintenance_set': notification_method = node_objects.NodeMaintenanceNotification payload_method = node_objects.NodePayload elif resource not in CRUD_NOTIFY_OBJ: notification_name = payload_name = _("is not defined") raise KeyError(_("Unsupported resource: %s") % resource) else: notification_method, payload_method = CRUD_NOTIFY_OBJ[resource] notification_name = notification_method.__name__ payload_name = payload_method.__name__ finally: # Prepare our exception message just in case exception_values = {"resource": resource, "uuid": obj.uuid, "action": action, "status": status, "level": level, "notification_method": notification_name, "payload_method": payload_name} exception_message = (_("Failed to send baremetal.%(resource)s." "%(action)s.%(status)s notification for " "%(resource)s %(uuid)s with level " "%(level)s, notification method " "%(notification_method)s, payload method " "%(payload_method)s, error %(error)s")) payload = payload_method(obj, **extra_args) if resource == 'node': notification.mask_secrets(payload) notification_method( publisher=notification.NotificationPublisher( service='ironic-api', host=CONF.host), event_type=notification.EventType( object=resource, action=action, status=status), level=level, payload=payload).emit(context) except (exception.NotificationSchemaObjectError, exception.NotificationSchemaKeyError, exception.NotificationPayloadError, oslo_msg_exc.MessageDeliveryFailure, oslo_vo_exc.VersionedObjectsException) as e: exception_values['error'] = e LOG.warning(exception_message, exception_values) except Exception as e: exception_values['error'] = e LOG.exception(exception_message, exception_values)