Bug #9891
possible mauvaise création de django_content_types à la création d'un tenant
0%
Description
combo:~# /etc/init.d/combo restart [....] Restarting Portal Management System: combo[info] Applying migrations (migrate_schemas)... === Running migrate for schema public Operations to perform: Synchronize unmigrated apps: multitenant, ckeditor, cmsplugin_blurp Apply all migrations: wcs, mellon, dataviz, family, sessions, admin, auth, contenttypes, momo, common, data, lingo Synchronizing apps without migrations: Creating tables... Installing custom SQL... Installing indexes... Running migrations: No migrations to apply. === Running migrate for schema portail_agent_alfortville_fr Operations to perform: Synchronize unmigrated apps: multitenant, ckeditor, cmsplugin_blurp Apply all migrations: wcs, mellon, dataviz, family, sessions, admin, auth, contenttypes, momo, common, data, lingo Synchronizing apps without migrations: Creating tables... Installing custom SQL... Installing indexes... Running migrations: No migrations to apply. Traceback (most recent call last): File "/usr/lib/combo/manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 385, in execute_from_command_line utility.execute() File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 377, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/usr/lib/python2.7/dist-packages/hobo/multitenant/management/commands/migrate_schemas.py", line 25, in run_from_argv super(MigrateSchemasCommand, self).run_from_argv(argv) File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 288, in run_from_argv self.execute(*args, **options.__dict__) File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 338, in execute output = self.handle(*args, **options) File "/usr/lib/python2.7/dist-packages/hobo/multitenant/management/commands/migrate_schemas.py", line 42, in handle self.run_migrations(tenant.schema_name, settings.TENANT_APPS) File "/usr/lib/python2.7/dist-packages/hobo/multitenant/management/commands/migrate_schemas.py", line 58, in run_migrations command.execute(*self.args, **defaults) File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 338, in execute output = self.handle(*args, **options) File "/usr/lib/python2.7/dist-packages/django/core/management/commands/migrate.py", line 165, in handle emit_post_migrate_signal(created_models, self.verbosity, self.interactive, connection.alias) File "/usr/lib/python2.7/dist-packages/django/core/management/sql.py", line 268, in emit_post_migrate_signal using=db) File "/usr/lib/python2.7/dist-packages/django/dispatch/dispatcher.py", line 198, in send response = receiver(signal=self, sender=sender, **named) File "/usr/lib/python2.7/dist-packages/django/contrib/auth/management/__init__.py", line 114, in create_permissions Permission.objects.using(using).bulk_create(perms) File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 409, in bulk_create self._batched_insert(objs_without_pk, fields, batch_size) File "/usr/lib/python2.7/dist-packages/django/db/transaction.py", line 339, in __exit__ connection.commit() File "/usr/lib/python2.7/dist-packages/django/db/backends/__init__.py", line 176, in commit self._commit() File "/usr/lib/python2.7/dist-packages/django/db/backends/__init__.py", line 145, in _commit return self.connection.commit() File "/usr/lib/python2.7/dist-packages/django/db/utils.py", line 94, in __exit__ six.reraise(dj_exc_type, dj_exc_value, traceback) File "/usr/lib/python2.7/dist-packages/django/db/backends/__init__.py", line 145, in _commit return self.connection.commit() django.db.utils.IntegrityError: ERREUR: une instruction insert ou update sur la table « auth_permission » viole la contrainte de clé étrangère « auth_content_type_id_508cf46651277a81_fk_django_content_type_id » DETAIL: La clé (content_type_id)=(16) n'est pas présente dans la table « django_content_type ». [info] done. [info] Collect static files (collectstatic)... 0 static files copied to '/var/lib/combo/collectstatic', 1044 unmodified. [info] done. . ok
Fichiers
Demandes liées
Historique
Mis à jour par Frédéric Péters il y a environ 8 ans
Lors du déploiement.
Traceback (most recent call last): File "/usr/lib/combo/manage.py", line 10, in <module> execute_from_command_line(sys.argv) File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 385, in execute_from_command_line utility.execute() File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 377, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 295, in run_from_argv stderr.write('%s: %s' % (e.__class__.__name__, e)) UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 79: ordinal not in range(128) [2016-02-06 10:23:27,338: INFO/MainProcess] Task hobo-deploy[33a36fcc-b1ab-49bd-aab9-acf88e24d7a6] succeeded in 25.2780017816s: None
En changeant pour mettre des %r :
'CommandError': CommandError("tenant creation failed (ERREUR: une instruction insert ou update sur la table \xc2\xab auth_permission \xc2\xbb viole la contrainte de cl\xc3\xa9\n\xc3\xa9trang\xc3\xa8re \xc2\xab auth_content_type_id_508cf46651277a81_fk_django_content_type_id \xc2\xbb\nDETAIL: La cl\xc3\xa9 (content_type_id)=(16) n'est pas pr\xc3\xa9sente dans la table \xc2\xab django_content_type \xc2\xbb.\n)",)
Et le schéma est créé donc lors de l'hobo_deploy suivant ça semble passer et en fait, non, c'est tout cassé.
Mis à jour par Frédéric Péters il y a environ 8 ans
À exécuter le create_tenant en mode verbose :
... Applying wcs.0009_remove_wcscategorycell_link_page... OK Applying wcs.0010_auto_20151029_1535... OK Applying wcs.0011_auto_20151215_1121... OK 'CommandError': CommandError("tenant creation failed (ERREUR: une instruction insert ou update sur la table \xc2\xab auth_permission \xc2\xbb viole la contrainte de cl\xc3\xa9\n\xc3\xa9trang\xc3\xa8re \xc2\xab auth_content_type_id_508cf46651277a81_fk_django_content_type_id \xc2\xbb\nDETAIL: La cl\xc3\xa9 (content_type_id)=(16) n'est pas pr\xc3\xa9sente dans la table \xc2\xab django_content_type \xc2\xbb.\n)",)
Mis à jour par Frédéric Péters il y a environ 8 ans
- Projet changé de Admin système à Hobo
- Sujet changé de crash migration combo prod à possible mauvaise création de django_content_types à la création d'un tenant
C'est passé avec :
+ from django.contrib.contenttypes.models import ContentType ... try: connection.set_schema_to_public() schema = TenantMiddleware.hostname2schema(hostname) + ContentType.objects.clear_cache() tenant = get_tenant_model()(schema_name=schema, domain_url=hostname) if verbosity >= 1: print print self.style.NOTICE("=== Creating schema ") \ + self.style.SQL_TABLE(tenant.schema_name) tenant.create_schema(check_if_exists=True)
Je dois partir, j'ai déplacé ça vers Hobo, si ça dit à quelqu'un de regarder pour faire un vrai patch.
Mis à jour par Benjamin Dauvergne il y a environ 8 ans
Ça ressemble à un souci lié au cache des objets ContentType; le code multitenant contient des appels à ContentType.objects.clear_cache() quand on change de schéma mais là il doit en manquer un au bon endroit, je ne trouve pas la plateforme ou reproduire le bug, mais ajouter un print
dans clear_cache
et voir quand il est appelé pourrait être utile.
Néanmoins avec un migrate_schemas
ciblé avec l'option -d
ça ne devrait pas arriver puisque qu'on ne chargerait pas les ContentType d'un autre tenant avant, idem pour la création du schéma dans reate_tenant
il me semble qu'on ne devrait pas avoir le temps de charger le cache des ContentType dans le schéma public, mais pareil il faudrait vérifier les appels à ContentType._add_to_cache (dans django/contrib/contentypes/models.py) et voir le tenant en cours à chaque appel (du django.db.connection.schema ou tenant).
Mis à jour par Benjamin Dauvergne il y a environ 8 ans
- Fichier 0001-clear-ContentType-on-each-schema-change-fixes-9891.patch 0001-clear-ContentType-on-each-schema-change-fixes-9891.patch ajouté
Voilà j'ai préféré corriger le souci à la source, il faudrait que j'arrive à reproduire le problème pour voir si ça le corrige bien; peut-être en supprimant à la main des objets Permission au hasard dans un tenant.
Mis à jour par Benjamin Dauvergne il y a environ 8 ans
Pas évident mais j'ai trouvé la source du problème. Il y a dans combo.data.apps ce code:
def ready(self): from .library import library library.ready()
qui appelle donc ce code ci:
def ready(self): # initialize the dictionary self.classes_by_content_str = {} for klass in self.classes: try: content_type = ContentType.objects.get_for_model(klass) except RuntimeError: # this is for RuntimeError: Error creating new content types. # Please make sure contenttypes is migrated before trying to # migrate apps individually. # # If that happens we switch to lazy initialization. self.classes_by_content_str = None break content_type_str_v = '%s_%s' % (content_type.app_label, content_type.model) self.classes_by_content_str[content_type_str_v] = klass
or au moment du ready()
on est pas dans le contexte du tenant mais dans le contexte "public". L'utilisation du modèle ContentType force l'initialisation du cache de ContentType (ainsi que la création des modèles qui n'existeraient pas normalement). Ensuite lors du passage dans le premier tenant, le signal post_migrate est appelé pour l'application momo
qui est la première dans la liste, cela appelle le handler de django.contrib.auth
pour la création des permissions, qui recherche le ContentType pour momoiconcell
qui n'a pas le même id dans la base public que dans le tenant de portail-agent.alfortville.fr et boum; il faut en plus que l'id trouvé dans la table du schéma public ne correspondent à aucun id existant, sinon l'erreur devient invisible (mais les permissions sont foirées). Ce qui est bizarre c'est que la table django_content_type ne devrait même pas exister, mais je pense que la base a été initialisée à une époque où on avait encore django.contrib.contenttypes listé dans SHARED_APPS.
Je pense qu'il faudrait remplacer ce code de combo par une utilisation de klass._meta.app_label
, klass._meta.model_name
car en plus il est contre-indiqué d'accéder aux modèles dans les méthodes ready()
[1] et ici ContentType ne me semble pas servir à grand chose. Fred est-ce que tu te souviens pourquoi tu as utilisé ContentType plutôt que l'objet Meta des modèles ?
[1]: https://docs.djangoproject.com/en/1.9/ref/applications/#django.apps.AppConfig.ready
Mis à jour par Benjamin Dauvergne il y a environ 8 ans
Le problème est d'ailleurs présent aussi sur portail-agents.vincennes.fr mais il n'est pas gênant:
154 | Can add Meta for mobile | 16 | add_momoiconcell 155 | Can change Meta for mobile | 16 | change_momoiconcell 156 | Can delete Meta for mobile | 16 | delete_momoiconcell 160 | Can add Meta for mobile | 38 | add_momoiconcell 161 | Can change Meta for mobile | 38 | change_momoiconcell 162 | Can delete Meta for mobile | 38 | delete_momoiconcell
idem sur fontenay:
106 | Can add Meta for mobile | 16 | add_momoiconcell 107 | Can change Meta for mobile | 16 | change_momoiconcell 108 | Can delete Meta for mobile | 16 | delete_momoiconcell
dès qu'on a le content_type_id == 16.
Mis à jour par Benjamin Dauvergne il y a environ 8 ans
Mis à jour par Frédéric Péters il y a environ 8 ans
- Lié à Bug #10308: erreur à l'exécution de commandes de manage avec le dernier django-tenant-schemas ajouté
Mis à jour par Benjamin Dauvergne il y a presque 8 ans
- Statut changé de Nouveau à Fermé
Corrigé dans django-tenant-schemas (notre fork):
commit 09175cc6d74f8891fcc2699f7f593839b9da1396 Author: Frédéric Péters <fpeters@entrouvert.com> Date: Wed Mar 16 11:05:41 2016 +0100 fix custom content type cache __get__ method (#10308) commit e2d86034c2e8a85d070a37123419b1f92c0b5fcd Author: Frédéric Péters <fpeters@entrouvert.com> Date: Wed Mar 16 11:03:17 2016 +0100 import ContentType, ContentTypeManager from contenttypes module (#10308) commit e0c423e1f285dd1430213f67009c534652bcf605 Author: Benjamin Dauvergne <bdauvergne@entrouvert.com> Date: Sat Feb 6 15:03:10 2016 +0100 clear ContentType on each schema change (fixes #9891) Also replace the cache dictionnary by a thread local variable to make it safe to use multitenancy with threads.