Skip to content

OpenStack volume notifications fail with audience: tenant due to missing initiator in with_notification calls #23682

@paolo21-source

Description

@paolo21-source

ISSUE

Environment

  • ManageIQ version: radjabov
  • OpenStack provider: Configured with AMQP/Cinder
  • Affected operations: All volume operations (create, update, delete, backup)

Problem Summary
When creating CloudVolumes through ManageIQ UI/API, notifications are only visible with audience: global. With audience: tenant or audience: user, notifications are created in the database but have zero recipients, making them invisible to users.
Root cause: The with_notification wrapper in the OpenStack provider gem does not pass :initiator (or :subject) parameters, resulting in Notification.create(subject: nil, initiator: nil).

Expected Behavior
Volume operation notifications should work correctly with all audience types:

  • global: All users receive notifications
  • tenant: Users in the tenant receive notifications
  • user: The initiating user receives notifications

Actual Behavior
With audience: global

ruby
Notification created with nil values
Notification.create(subject: nil, initiator: nil)

subscriber_ids for global audience
User.pluck(:id) # Returns all users [1,2,3...] regardless of nil parameters

Result: Notification visible to all users (works by accident)
With audience: tenant

ruby
Notification created with nil values
Notification.create(subject: nil, initiator: nil)

subscriber_ids for tenant audience
nil.try(:tenant).try(:user_ids) # Returns []

Result: Notification created but zero recipients (invisible!)
With audience: user

ruby
Notification created with nil values
Notification.create(subject: nil, initiator: nil)

subscriber_ids for user audience
[nil.id] # Error or []

Result: Notification fails or has zero recipients

Technical Analysis
Current Code (manageiq-providers-openstack)
File: app/models/manageiq/providers/openstack/storage_manager/cinder_manager/cloud_volume.rb

ruby
def raw_create_volume(ext_management_system, options)

...

with_notification(:cloud_volume_create,
:options => {:volume_name => options[:name]}) do
# Create volume on OpenStack
end

...

end
Problem: Does not pass :initiator or :subject to with_notification.

File: app/models/manageiq/providers/openstack/helper_methods.rb

ruby
def with_notification(type, options: {})
Extract named_options (subject, initiator, cause)
named_options = options.extract!(:subject, :initiator, :cause)

...

Creates notification with extracted parameters
Notification.create(:type => "#{type}_success".to_sym,
:options => success_options,
**named_options) # subject: nil, initiator: nil
end
Problem: Correctly extracts parameters, but they're never provided by calling code.

How subscriber_ids Works (manageiq core)
File: app/models/notification_type.rb

ruby
def subscriber_ids(subject, initiator)
case audience
when AUDIENCE_GLOBAL
User.pluck(:id) # Returns ALL users, ignores parameters

when AUDIENCE_USER
[initiator.id] # Requires initiator!

when AUDIENCE_TENANT
if subject.respond_to?(:tenant)
subject.tenant # Requires subject!
elsif initiator.kind_of?(User)
initiator.current_tenant # Or requires initiator!
end.try(:user_ids).try(:uniq)

end || []
end
Result:

  • global works because it doesn't check parameters
  • tenant and user fail because parameters are nil

Database Evidence
Query showing notifications created without recipients:

ruby
With audience: tenant
notification = Notification.where(notification_type: NotificationType.find_by(name: 'cloud_volume_create_success')).last

notification.subject # => nil
notification.initiator # => nil
notification.recipients # => [] (empty!)
notification.notification_recipients.count # => 0
The notification exists in the database but is invisible because notification_recipients table has zero entries.

Affected Operations
All volume operations in the OpenStack provider have this issue:

  1. Volume Create: with_notification(:cloud_volume_create, :options => {:volume_name => options[:name]})
  2. Volume Update: with_notification(:cloud_volume_update, :options => {:subject => self})
  3. Volume Delete: with_notification(:cloud_volume_delete, :options => {:subject => self})
  4. Backup Create: with_notification(:cloud_volume_backup_create, :options => {:subject => self, :backup_name => options[:name]})
  5. Backup Delete: Similar pattern
  6. Snapshot operations: Similar pattern
    Note: Delete and Update operations pass :subject => self, but still missing :initiator.

Proposed Solution
Option 1: Pass initiator in volume operations
In cloud_volume.rb:

ruby
def raw_create_volume(ext_management_system, options)
cloud_tenant = find_destination_cloud_tenant(ext_management_system, options)

Find initiator from the cloud_tenant
initiator = cloud_tenant&.source_tenant&.users&.first || User.current_user

with_notification(:cloud_volume_create,
:options => {:volume_name => options[:name]},
:initiator => initiator) do # ← ADD THIS
ext_management_system.with_provider_connection(cinder_connection_options(cloud_tenant)) do |service|
volume = service.volumes.new(options)
volume.save
end
end

...

end
Apply similar changes to all volume operations (update, delete, backup, snapshot).
Option 2: Enhanced with_notification helper
Modify helper_methods.rb to automatically determine initiator:

ruby
def with_notification(type, options: {})
If no initiator provided, try to determine it
if options[:initiator].nil?
options[:initiator] = User.current_user
end

Rest of the method...
end
Option 3: Use thread-local User.current_user in subscriber_ids
Modify core ManageIQ notification_type.rb to fallback to current user:

ruby
def subscriber_ids(subject, initiator)
initiator ||= User.current_user # Fallback

case audience

...

end
end

We've identified several potential approaches to fix this issue, but we'd like to hear from the maintainers about the preferred solution

Do you have any?

Thanks

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions