diff --git a/awx/main/migrations/0009_v300_rbac_migrations.py b/awx/main/migrations/0009_v300_rbac_migrations.py index 9c7f7d8dd7..dd26690b22 100644 --- a/awx/main/migrations/0009_v300_rbac_migrations.py +++ b/awx/main/migrations/0009_v300_rbac_migrations.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from awx.main.migrations import _rbac as rbac +from awx.main.migrations import _migration_utils as migration_utils from django.db import migrations @@ -12,11 +13,12 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RunPython(rbac.init_rbac_migration), + migrations.RunPython(migration_utils.set_current_apps_for_migrations), migrations.RunPython(rbac.migrate_users), migrations.RunPython(rbac.migrate_organization), migrations.RunPython(rbac.migrate_team), migrations.RunPython(rbac.migrate_inventory), migrations.RunPython(rbac.migrate_projects), migrations.RunPython(rbac.migrate_credential), + migrations.RunPython(rbac.rebuild_role_hierarchy), ] diff --git a/awx/main/migrations/0017_v300_prompting_migrations.py b/awx/main/migrations/0017_v300_prompting_migrations.py index f08d760a8c..c5a1df0eb9 100644 --- a/awx/main/migrations/0017_v300_prompting_migrations.py +++ b/awx/main/migrations/0017_v300_prompting_migrations.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from awx.main.migrations import _ask_for_variables as ask_for_variables +from awx.main.migrations import _migration_utils as migration_utils from django.db import migrations @@ -12,5 +13,6 @@ class Migration(migrations.Migration): ] operations = [ + migrations.RunPython(migration_utils.set_current_apps_for_migrations), migrations.RunPython(ask_for_variables.migrate_credential), ] diff --git a/awx/main/migrations/_migration_utils.py b/awx/main/migrations/_migration_utils.py new file mode 100644 index 0000000000..232310ca50 --- /dev/null +++ b/awx/main/migrations/_migration_utils.py @@ -0,0 +1,11 @@ +from awx.main.utils import set_current_apps + + +def set_current_apps_for_migrations(apps, schema_editor): + ''' + This is necessary for migrations which do explicit saves on any model that + has an ImplicitRoleFIeld (which generally means anything that has + some RBAC bindings associated with it). This sets the current 'apps' that + the ImplicitRoleFIeld should be using when creating new roles. + ''' + set_current_apps(apps) diff --git a/awx/main/migrations/_rbac.py b/awx/main/migrations/_rbac.py index 3570e0184a..0a816610ed 100644 --- a/awx/main/migrations/_rbac.py +++ b/awx/main/migrations/_rbac.py @@ -1,11 +1,13 @@ import logging +from time import time from django.utils.encoding import smart_text from django.db.models import Q -from django.utils.timezone import now +#from django.utils.timezone import now from collections import defaultdict -from awx.main.utils import getattrd, set_current_apps +from awx.main.utils import getattrd +from awx.main.models.rbac import Role import _old_access as old_access logger = logging.getLogger(__name__) @@ -26,9 +28,6 @@ def log_migration(wrapped): return wrapped(*args, **kwargs) return wrapper -@log_migration -def init_rbac_migration(apps, schema_editor): - set_current_apps(apps) @log_migration def migrate_users(apps, schema_editor): @@ -395,3 +394,22 @@ def migrate_job_templates(apps, schema_editor): if old_access.check_user_access(user, jt.__class__, 'start', jt, False): jt.execute_role.members.add(user) logger.info(smart_text(u'adding User({}) access to JobTemplate({})'.format(user.username, jt.name))) + +@log_migration +def rebuild_role_hierarchy(apps, schema_editor): + logger.info('Computing role roots..') + start = time() + roots = Role.objects \ + .all() \ + .exclude(pk__in=Role.parents.through.objects.all() + .values_list('from_role_id', flat=True).distinct()) \ + .values_list('id', flat=True) + stop = time() + logger.info('Found %d roots in %f seconds, rebuilding ancestry map' % (len(roots), stop - start)) + start = time() + Role.rebuild_role_ancestor_list(roots, []) + stop = time() + logger.info('Rebuild completed in %f seconds' % (stop - start)) + logger.info('Done.') + +