-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Switches FileDistribution
use Distribution
#481
Switches FileDistribution
use Distribution
#481
Conversation
WARNING!!! This PR is not attached to an issue. In most cases this is not advisable. Please see our PR docs for more information about how to attach this PR to an issue. |
An example of a Distribution with an object label before migration:
An example (different pk because different run, but it would have been the same if the same...):
|
Before and after show the same API output:
|
FileDistribution
use Distribution
.
FileDistribution
use Distribution
.FileDistribution
use Distribution
pks_to_delete.append(old_file_distribution.pulp_id) | ||
|
||
|
||
def delete_remaining_old_master_model_entries(apps, schema_editor): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't this just be done in a normal way, e.g. BaseDistribution.objects.filter(pk__in=pks_to_delete).delete()
And what is the benefit to using two separate migration steps rather than doing the deletion at the end of the first step?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried several ways, and as far as I can tell it cannot.
There is some kind of a bug in the migration system here. I have to use BaseDistribution directly because if I used FileDistribution I'll also be deleting the detail table. So if you run code like this:
def delete_remaining_old_master_model_entries(apps, schema_editor):
BaseDistribution = apps.get_model('core', 'BaseDistribution')
BaseDistribution.objects.filter(pk__in=pks_to_delete).delete()
You get this error:
Applying file.0009_move_data_to_new_master_distribution_model...Traceback (most recent call last):
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedColumn: column file_filedistribution.basedistribution_ptr_id does not exist
LINE 1: DELETE FROM "file_filedistribution" WHERE "file_filedistribu...
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/pulp/bin/pulpcore-manager", line 33, in <module>
sys.exit(load_entry_point('pulpcore', 'console_scripts', 'pulpcore-manager')())
File "/home/vagrant/devel/pulpcore/pulpcore/app/manage.py", line 11, in manage
execute_from_command_line(sys.argv)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
utility.execute()
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/base.py", line 323, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/base.py", line 364, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/commands/migrate.py", line 232, in handle
post_migrate_state = executor.migrate(
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/executor.py", line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
state = migration.apply(state, schema_editor)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/migration.py", line 124, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/operations/special.py", line 190, in database_forwards
self.code(from_state.apps, schema_editor)
File "/home/vagrant/devel/pulp_file/pulp_file/app/migrations/0009_move_data_to_new_master_distribution_model.py", line 34, in delete_remaining_old_master_model_entries
BaseDistribution.objects.filter(pk__in=pks_to_delete).delete()
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/models/query.py", line 711, in delete
deleted, _rows_count = collector.delete()
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/models/deletion.py", line 294, in delete
count = qs._raw_delete(using=self.using)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/models/query.py", line 725, in _raw_delete
return sql.DeleteQuery(self.model).delete_qs(self, using)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/models/sql/subqueries.py", line 75, in delete_qs
cursor = self.get_compiler(using).execute_sql(CURSOR)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/models/sql/compiler.py", line 1142, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: column file_filedistribution.basedistribution_ptr_id does not exist
LINE 1: DELETE FROM "file_filedistribution" WHERE "file_filedistribu...
You can however do this without error, but I believe we can't do this because if this plugin is installed in a much later pulpcore release this won't even be importable.
def delete_remaining_old_master_model_entries(apps, schema_editor):
from pulpcore.app.models import BaseDistribution
BaseDistribution.objects.filter(pk__in=pks_to_delete).delete()
I believe this is a problem only during migration because once migrations are finished running I can go into a shell and run:
from django.apps import apps
BaseDistribution = apps.get_model('core', 'BaseDistribution')
BaseDistribution.objects.all().delete()
I have a good setup to test any idea, but I don't have any others. Any suggestions welcome. Oh one other idea is: Don't worry about deleting the BaseDistribution at all and eventually the pulpcore migration that removes BaseDistribution will delete the table.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a good setup to test any idea, but I don't have any others. Any suggestions welcome. Oh one other idea is: Don't worry about deleting the BaseDistribution at all and eventually the pulpcore migration that removes BaseDistribution will delete the table.
Honestly this sounds good to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been running into problems with stray BaseContent entries while experimenting with uninstalling plugins.
I don't know what exactly the problem was, but it sounds like not such a good idea to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're deleting the entire table then I don't think we'd have that problem. BaseContent
is still around
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just saying i had strange problems with Content. I don't know if they extend to Distributions. But we don't want to delete the whole table right away. It will exist for at least one release cycle after this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
view_name_pattern=r"publications(-.*/.*)?-detail", | ||
queryset=models.Publication.objects.exclude(complete=False), | ||
allow_null=True, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the intention that plugins would just copy this code rather than inheriting? It's a reasonable position and I'm fine with it, just checking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I want to switch this to having Pulpcore provide mixins to avoid the copying. I'm going to do that now.
I had a moment of pause with this idea thinking 'oh no am I recreating the very problem we are tyring to solve'? I realize, no it's not recreating the same problem because these cross-package imports wouldn't automatically be defining fields that unavoidable are created at the db level. In fact, they're just serializer fields.
def delete_remaining_old_master_model_entries(apps, schema_editor): | ||
with connection.cursor() as cursor: | ||
for pk in pks_to_delete: | ||
cursor.execute("DELETE from core_basedistribution WHERE pulp_id = %s", [pk]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you run that delete statement in the same transaction that moves the single distribution?
It sounds cleaner to me than collecting those id's in a global variable.
Also it's more resilient to oom in the migration. (Thinking of a lot of distributions here.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this, but it didn't work. I applied the following diff:
diff --git a/pulp_file/app/migrations/0009_move_data_to_new_master_distribution_model.py b/pulp_file/app/migrations/0009_move_data_to_new_master_distribution_model.py
index 9f714d5..24d6485 100644
--- a/pulp_file/app/migrations/0009_move_data_to_new_master_distribution_model.py
+++ b/pulp_file/app/migrations/0009_move_data_to_new_master_distribution_model.py
@@ -26,13 +26,19 @@ def migrate_data_from_old_master_model_to_new_master_model(apps, schema_editor):
new_master_model_entry.save()
old_file_distribution.distribution_ptr = new_master_model_entry
old_file_distribution.save()
- pks_to_delete.append(old_file_distribution.pulp_id)
+ # pks_to_delete.append(old_file_distribution.pulp_id)
+ with connection.cursor() as cursor:
+ cursor.execute(
+ "DELETE from core_basedistribution WHERE pulp_id = %s",
+ [old_file_distribution.pulp_id]
+ )
def delete_remaining_old_master_model_entries(apps, schema_editor):
- with connection.cursor() as cursor:
- for pk in pks_to_delete:
- cursor.execute("DELETE from core_basedistribution WHERE pulp_id = %s", [pk])
+ print('qqq')
+ # with connection.cursor() as cursor:
+ # for pk in pks_to_delete:
+ # cursor.execute("DELETE from core_basedistribution WHERE pulp_id = %s", [pk])
And at migration time I get this error:
psycopg2.errors.ForeignKeyViolation: update or delete on table "core_basedistribution" violates foreign key constraint "file_filedistributio_basedistribution_ptr_ba2e0c52_fk_core_base" on table "file_filedistribution"
DETAIL: Key (pulp_id)=(ffd35cf3-19e0-46d3-b45b-9e437cd76913) is still referenced from table "file_filedistribution".
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/usr/local/lib/pulp/bin/pulpcore-manager", line 33, in <module>
sys.exit(load_entry_point('pulpcore', 'console_scripts', 'pulpcore-manager')())
File "/home/vagrant/devel/pulpcore/pulpcore/app/manage.py", line 11, in manage
execute_from_command_line(sys.argv)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
utility.execute()
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/__init__.py", line 375, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/base.py", line 323, in run_from_argv
self.execute(*args, **cmd_options)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/base.py", line 364, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/base.py", line 83, in wrapped
res = handle_func(*args, **kwargs)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/core/management/commands/migrate.py", line 232, in handle
post_migrate_state = executor.migrate(
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/executor.py", line 117, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
state = migration.apply(state, schema_editor)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/migration.py", line 124, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/migrations/operations/fields.py", line 178, in database_forwards
schema_editor.remove_field(from_model, from_model._meta.get_field(self.name))
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/base/schema.py", line 481, in remove_field
self.execute(self._delete_fk_sql(model, fk_name))
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/base/schema.py", line 137, in execute
cursor.execute(sql, params)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/usr/local/lib/pulp/lib64/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: update or delete on table "core_basedistribution" violates foreign key constraint "file_filedistributio_basedistribution_ptr_ba2e0c52_fk_core_base" on table "file_filedistribution"
DETAIL: Key (pulp_id)=(ffd35cf3-19e0-46d3-b45b-9e437cd76913) is still referenced from table "file_filedistribution".
to='core.Distribution'), | ||
preserve_default=False, | ||
), | ||
migrations.RunPython(migrate_data_from_old_master_model_to_new_master_model), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know, this is asking a lot, but please provide a backwards migration.
pulpcore==3.12 introduces a new MasterModel named `Distribution` designed to replace the `BaseDistribution` MasterModel. This PR switches the `FileDistribution` to use `Distribution`. It also ships a migration which moves the data from the `BaseDistribution` table to the `Distribution` field. Required PR: pulp/pulpcore#1198 closes #8387
Well this is unfortunate. github won't let me force push my new ref because it says
So now we're going to have to use this PR instead... #482 |
Ok now this PR seems to allow me to force push (after deleting my fork and recreating it). #484 |
I'm leaving comments here still because there was such good substantive discussion here. I'll reply to comments in either place though, whatever works for reviewers. |
pulpcore==3.12 introduces a new MasterModel named
Distribution
designed to replace the
BaseDistribution
MasterModel. This PR switchesthe
FileDistribution
to useDistribution
. It also ships a migrationwhich moves the data from the
BaseDistribution
table to theDistribution
field.Required PR: pulp/pulpcore#1198
closes #8387