Bug 2075673

Summary: Attempt to disable a Red Hat Repository fails with error "Cannot delete record because of dependent library_instances_inverse" if the repository is part of any CV versions in Satellite 6.10
Product: Red Hat Satellite Reporter: Sayan Das <saydas>
Component: RepositoriesAssignee: satellite6-bugs <satellite6-bugs>
Status: CLOSED ERRATA QA Contact: Cole Higgins <chiggins>
Severity: high Docs Contact:
Priority: high    
Version: 6.10.4CC: ahumbe, dhjoshi, hyu, iballou, jpasqual, juwatts, osousa, rcavalca, sajha, tasander
Target Milestone: 6.11.1Keywords: PrioBumpGSS, Triaged
Target Release: Unused   
Hardware: All   
OS: All   
Whiteboard:
Fixed In Version: tfm-rubygem-katello-4.3.0.43-1 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
: 2103106 (view as bug list) Environment:
Last Closed: 2022-07-27 17:27:09 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Sayan Das 2022-04-14 20:14:41 UTC
Description of problem:

If an RH repository is part if one or more CV versions, then an attempt to disable the same should actually not trigger any deletion but show the message "Repository cannot be deleted since it has already been included in a published Content View".

The standard guideline here is that follow https://access.redhat.com/solutions/3180551 to identify the affected CV versions, remove them and then disable the repo.

But in certain customer environments of Satellite 6.10, That message never appears but instead, the deletion of the repo gets started and after 70% progress the task will go to Paused state with the error:
~~
Cannot delete record because of dependent library_instances_inverse
~~



Version-Release number of selected component (if applicable):

Red Hat Satellite 6.10.4


How reproducible:

In customer environment 


Steps to Reproduce:
1.
2.
3.

Actual results:

No such messages like "Repository cannot be deleted since it has already been included in a published Content View" neither in UI nor in the tasl. 

Repo disable task in paused state with error "Cannot delete record because of dependent library_instances_inverse"


2022-04-13T14:32:06 [I|bac|319bca91] Task {label: Actions::Katello::RepositorySet::DisableRepository, id: bd4b4830-a2d7-4873-b82b-08930303d0d5, execution_plan_id: 651c0ff7-dcd2-43d6-bd46-d0efeac1d261} state changed: running 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on pulp_id 344d38ae-0cf2-40e8-a4ba-82dad873005e
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on library_instance_id 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on content_view_version_id 1
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on relative_path Crown_Equipment_Corporation/Library/content/dist/rhel/server/7/7Server/x86_64/ansible/2.6/os
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on environment_id 1
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on saved_checksum_type 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on distribution_version 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on distribution_arch 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on distribution_bootable 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on distribution_family 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on distribution_variant 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on container_repository_name 
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on root_id 40
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on remote_href /pulp/api/v3/remotes/rpm/rpm/a1ee81ac-ef79-4f9e-9fcf-1fae9d28c386/
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on publication_href /pulp/api/v3/publications/rpm/rpm/657df4a7-3ac8-48b0-96ca-db109912ece2/
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on version_href /pulp/api/v3/repositories/rpm/rpm/a2345c38-2b09-4a96-bf87-692f432e6d07/versions/1/
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on last_contents_changed 1969-12-31 19:00:00 -0500
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on last_applicability_regen 1969-12-31 19:00:00 -0500
2022-04-13T14:32:07 [I|aud|319bca91] Katello::Repository (258) destroy event on last_indexed 1969-12-31 19:00:00 -0500
2022-04-13T14:32:07 [E|bac|319bca91] Cannot delete record because of dependent library_instances_inverse (ActiveRecord::DeleteRestrictionError)
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/associations/has_many_association.rb:16:in `handle_dependency'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/associations/builder/association.rb:129:in `block in add_destroy_callbacks'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:428:in `instance_exec'

..
..
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/transactions.rb:212:in `transaction'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/transactions.rb:366:in `with_transaction_returning_status'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/transactions.rb:310:in `destroy'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/models/katello/model.rb:23:in `destroy!'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/katello/repository/destroy.rb:67:in `delete_record'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/katello/repository/destroy.rb:41:in `finalize'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/dynflow-1.4.9/lib/dynflow/action.rb:594:in `block (2 levels) in execute_finalize'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/dynflow-1.4.9/lib/dynflow/middleware/stack.rb:27:in `pass'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/dynflow-1.4.9/lib/dynflow/middleware.rb:19:in `pass'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/middleware/remote_action.rb:20:in `block in finalize'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/middleware/remote_action.rb:40:in `block in as_remote_user'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/models/katello/concerns/user_extensions.rb:21:in `cp_config'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/middleware/remote_action.rb:27:in `as_cp_user'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/middleware/remote_action.rb:39:in `as_remote_user'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/middleware/remote_action.rb:20:in `finalize'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/dynflow-1.4.9/lib/dynflow/middleware/stack.rb:23:in `call'
 319bca91 | /opt/theforeman/tfm/root/usr/share/gems/gems/dynflow-1.4.9/lib/dynflow/middleware/stack.rb:27:in `pass'


Expected results:

Repo disable task should show "Repository cannot be deleted since it has already been included in a published Content View" and should not initiate the plan for deletion. 


Additional info:

I was able to reproduce the behavior but not the error "Cannot delete record because of dependent library_instances_inverse".

The behavior can only be reproduced by commenting out "check_destroyable!(repository)" from /opt/theforeman/tfm/root/usr/share/gems/gems/katello-4.1.1.52/app/lib/actions/katello/repository/destroy.rb , restart of satellite services and then try to disable the repo from Content --> Red Hat Repositories page.

Even though the behavior remains the same i.e. The plan executes till 70% and then the task goes into the paused state, The error message is not the same. Instead, i can only see "Repository cannot be deleted since it has already been included in a published Content View".

Anyways, this is really dangerous. The expectation is that if a repo is part of any CV, then trying to disable the repo from the Content --> Red Hat Repositories page, should not execute any deletion plan but simply show the message from https://access.redhat.com/solutions/3180551. But if the plan is getting executed without showing this error, then we have a bug problem gere.

Comment 11 Hao Chang Yu 2022-06-16 05:06:39 UTC
I am able to reproduce it with simple steps below:

1) Enable a repository and sync it.
2) Create a content view and add the repository to it, and then publish the first version.
3) Remove the repository from the content view.
4) Disable the repository.

Actual:
Id: 1fc34c83-a653-41c9-9789-6e849e4a54c5
Label: Actions::Katello::RepositorySet::DisableRepository
Status: paused Resume
Result: error
Started at: 2022-06-16 04:52:27 UTC

In Finalize tab:
10: Actions::Katello::Repository::Destroy (error) [ 0.11s / 0.11s ] Skip
Queue: default

Started at: 2022-06-16 04:52:43 UTC
Ended at: 2022-06-16 04:52:44 UTC
Real time: 0.11s
Execution time (excluding suspended state): 0.11s
Input:
---
repository:
  id: 285
  name: Red Hat Satellite Tools 6.10 for RHEL 7 Desktop RPMs x86_64
  label: Red_Hat_Satellite_Tools_6_10_for_RHEL_7_Desktop_RPMs_x86_64
  <snip>

Output:
--- {}
Error:
ActiveRecord::DeleteRestrictionError
Cannot delete record because of dependent library_instances_inverse
---
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/associations/has_many_association.rb:16:in
  `handle_dependency'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/associations/builder/association.rb:129:in
  `block in add_destroy_callbacks'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:428:in
  `instance_exec'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:428:in
  `block in make_lambda'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:200:in
  `block (2 levels) in halting'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:605:in
  `block (2 levels) in default_terminator'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:604:in
  `catch'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:604:in
  `block in default_terminator'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:201:in
  `block in halting'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:513:in
  `block in invoke_before'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:513:in
  `each'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:513:in
  `invoke_before'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:134:in
  `run_callbacks'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activesupport-6.0.3.7/lib/active_support/callbacks.rb:825:in
  `_run_destroy_callbacks'"
- "/opt/theforeman/tfm/root/usr/share/gems/gems/activerecord-6.0.3.7/lib/active_record/callbacks.rb:309:in
  `destroy'"
<snip>


Expected:
Should give "Repository cannot be deleted since it has already been included in a published Content View" message and don't run "Actions::Katello::RepositorySet::DisableRepository" task.



Demonstrate in foreman-rake console
---------------------------------------
foreman-rake console
irb(main):050:0> repo = Katello::Repository.find(285)
=> #<Katello::Repository id: 285, pulp_id: "df009c0e-2352-40c1-b0e8-788d046cb99d", library_instance_id: nil, content_view_version_i...
irb(main):051:0> repo.library_instances_inverse.map(&:relative_path)
=> ["redhat/content_views/cv_clone_test_1/1.0/content/dist/rhel/client/7/7Client/x86_64/sat-tools/6.10/os", "redhat/Library/cv_clone_test_1/content/dist/rhel/client/7/7Client/x86_64/sat-tools/6.10/os"]
irb(main):052:0> repo.destroy
Traceback (most recent call last):
        2: from lib/tasks/console.rake:5:in `block in <top (required)>'
        1: from (irb):52
ActiveRecord::DeleteRestrictionError (Cannot delete record because of dependent library_instances_inverse)
exit
---------------------------------------

Comment 12 Sayan Das 2022-06-16 05:15:39 UTC
@hyu ,

At step 3:

3) Remove the repository from the content view.

We simply remove the repo but don't republish the CV right and that is what triggers the error during disable the action of the repo?


This means whichever user faced this issue with a repo, At some point, they must have removed the affected repo from CV but a republish of CV was not done but straightaway it was attempted to disable the repo ?


-- Sayan

Comment 13 Hao Chang Yu 2022-06-16 05:22:37 UTC
This is the issue. The "self.content_views.generated_for_none.exists?" is false, so the "deletable?" method will return true even the "self.promoted?" is true.
----------------------------------
module Katello
  module Authorization::Repository
    extend ActiveSupport::Concern

    delegate :editable?, to: :product

    def deletable?
      product.editable? && (!promoted? || !self.content_views.generated_for_none.exists?)  <============
    end

    def redhat_deletable?
      (!self.promoted? || !self.content_views.generated_for_none.exists?) && self.product.editable?  <============
    end
----------------------------------


Code in Satellite 6.9
----------------------------------
module Katello
  module Authorization::Repository
    extend ActiveSupport::Concern

    delegate :editable?, to: :product

    def deletable?
      product.editable? && !promoted?
    end

    def redhat_deletable?
      !self.promoted? && self.product.editable?
    end
----------------------------------

Comment 14 Hao Chang Yu 2022-06-16 05:25:01 UTC
(In reply to Sayan Das from comment #12)
> @hyu ,
> 
> At step 3:
> 
> 3) Remove the repository from the content view.
> 
> We simply remove the repo but don't republish the CV right and that is what
> triggers the error during disable the action of the repo?
> 
> 

I think this doesn't matter as long as you don't delete the first published version which is still associating with the repo.

Comment 15 Samir Jha 2022-06-16 16:32:38 UTC
Created redmine issue https://projects.theforeman.org/issues/35073 from this bug

Comment 16 Bryan Kearney 2022-06-24 20:04:33 UTC
Moving this bug to POST for triage into Satellite since the upstream issue https://projects.theforeman.org/issues/35073 has been resolved.

Comment 17 Taft Sanders 2022-06-29 15:22:15 UTC
*** Bug 2102260 has been marked as a duplicate of this bug. ***

Comment 24 errata-xmlrpc 2022-07-27 17:27:09 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (Satellite 6.11.1 Async Bug Fix Update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2022:5742