Commit ae2ad61f authored by Giorgos Korfiatis's avatar Giorgos Korfiatis

astakos: Improve printing in quota-verify

Also add option to delete project and user holdings that do not correspond
to actual astakos entities.
parent 42304537
......@@ -34,75 +34,104 @@
from optparse import make_option
from django.db import transaction
from astakos.im.models import AstakosUser
from astakos.im.quotas import (
qh_sync_users_diffs,)
from astakos.im.functions import get_user_by_uuid
from astakos.im.models import Project
from astakos.im import quotas
from snf_django.management.utils import pprint_table
from snf_django.management.commands import SynnefoCommand
from astakos.im.management.commands import _common as common
import logging
logger = logging.getLogger(__name__)
def differences(local_quotas, qh_quotas):
unsynced = []
unexpected = []
for holder, h_quotas in local_quotas.iteritems():
qh_h_quotas = qh_quotas.pop(holder, {})
for source, s_quotas in h_quotas.iteritems():
qh_s_quotas = qh_h_quotas.pop(source, {})
for resource, value in s_quotas.iteritems():
qh_value = qh_s_quotas.pop(resource, None)
if value != qh_value:
data = (holder, source, resource, value, qh_value)
unsynced.append(data)
unexpected += unexpected_resources(holder, source, qh_s_quotas)
unexpected += unexpected_sources(holder, qh_h_quotas)
unexpected += unexpected_holders(qh_quotas)
return unsynced, unexpected
def unexpected_holders(qh_quotas):
unexpected = []
for holder, qh_h_quotas in qh_quotas.iteritems():
unexpected += unexpected_sources(holder, qh_h_quotas)
return unexpected
def unexpected_sources(holder, qh_h_quotas):
unexpected = []
for source, qh_s_quotas in qh_h_quotas.iteritems():
unexpected += unexpected_resources(holder, source, qh_s_quotas)
return unexpected
def unexpected_resources(holder, source, qh_s_quotas):
unexpected = []
for resource, qh_value in qh_s_quotas.iteritems():
data = (holder, source, resource, None, qh_value)
unexpected.append(data)
return unexpected
class Command(SynnefoCommand):
help = "Check the integrity of user quota"
help = "Check the integrity of user and project quota"
option_list = SynnefoCommand.option_list + (
make_option('--sync',
action='store_true',
dest='sync',
make_option("--include-unexpected-holdings",
default=False,
action="store_true",
help=("Also check for holdings that do not correspond "
"to Astakos projects or user. Note that fixing such "
"inconsistencies will permanently delete these "
"holdings.")),
make_option("--fix", dest="fix",
default=False,
help="Sync quotaholder"),
make_option('--user',
metavar='<uuid or email>',
dest='user',
help="Check for a specified user"),
action="store_true",
help="Synchronize Quotaholder with Astakos DB."),
)
@transaction.commit_on_success
def handle(self, *args, **options):
sync = options['sync']
user_ident = options['user']
if user_ident is not None:
users = [common.get_accepted_user(user_ident)]
else:
users = AstakosUser.objects.accepted()
qh_limits, diff_q = qh_sync_users_diffs(users, sync=sync)
if sync:
self.print_sync(diff_q)
else:
self.print_verify(qh_limits, diff_q)
def print_sync(self, diff_quotas):
size = len(diff_quotas)
if size == 0:
self.stderr.write("No sync needed.\n")
else:
self.stderr.write("Synced %s users:\n" % size)
uuids = diff_quotas.keys()
users = AstakosUser.objects.filter(uuid__in=uuids)
for user in users:
self.stderr.write("%s (%s)\n" % (user.uuid, user.username))
def print_verify(self, qh_limits, diff_quotas):
for holder, local in diff_quotas.iteritems():
registered = qh_limits.pop(holder, None)
user = get_user_by_uuid(holder)
if registered is None:
self.stderr.write(
"No quota for %s (%s) in quotaholder.\n" %
(holder, user.username))
else:
self.stdout.write("Quota differ for %s (%s):\n" %
(holder, user.username))
self.stdout.write("Quota according to quotaholder:\n")
self.stdout.write("%s\n" % (registered))
self.stdout.write("Quota according to astakos:\n")
self.stdout.write("%s\n\n" % (local))
diffs = len(diff_quotas)
if diffs:
self.stderr.write("Quota differ for %d users.\n" % (diffs))
write = self.stderr.write
fix = options['fix']
check_unexpected = options["include_unexpected_holdings"]
projects = Project.objects.all()
local_proj_quotas, local_user_quotas = \
quotas.astakos_project_quotas(projects)
qh_proj_quotas, qh_user_quotas = \
quotas.get_projects_quota_limits()
unsynced, unexpected = differences(local_proj_quotas, qh_proj_quotas)
unsync_u, unexpect_u = differences(local_user_quotas, qh_user_quotas)
unsynced += unsync_u
unexpected += unexpect_u
headers = ("Holder", "Source", "Resource", "Astakos", "Quotaholder")
if not unsynced and (not check_unexpected or not unexpected):
write("Everything in sync.\n")
return
printable = (unsynced if not check_unexpected
else unsynced + unexpected)
pprint_table(self.stdout, printable, headers, title="Inconsistencies")
if fix:
to_sync = []
for holder, source, resource, value, qh_value in unsynced:
to_sync.append(((holder, source, resource), value))
quotas.qh.set_quota(to_sync)
if check_unexpected:
to_del = []
for holder, source, resource, value, qh_value in unexpected:
to_del.append((holder, source, resource))
quotas.qh.delete_quota(to_del)
......@@ -320,31 +320,6 @@ def qh_sync_membership(membership):
set_quota(quota)
def compute_diff_quota(local, registered):
diff = {}
for holder, h_quota in local.iteritems():
for source, value in h_quota.iteritems():
reg_h_quota = registered.get(holder, {})
reg_value = reg_h_quota.get(source, {})
if value != reg_value:
set_path(diff, [holder, source], value, createpath=True)
return diff
def qh_sync_projects_diffs(projects, sync=True):
local_project, local_user = astakos_project_quotas(projects)
registered_project, registered_user = get_projects_quota_limits(projects)
diff_quotas = compute_diff_quota(local_project, registered_project)
diff_quotas.update(compute_diff_quota(local_user, registered_user))
if sync:
set_quota(diff_quotas)
all_registered = registered_project
all_registered.update(registered_user)
return all_registered, diff_quotas
def pick_limit_scheme(project, resource):
return resource.uplimit if project.is_base else resource.project_default
......
......@@ -75,6 +75,13 @@ def get_quota(holders=None, sources=None, resources=None, flt=None):
return quotas
def delete_quota(keys):
for holder, source, resource in keys:
Holding.objects.filter(holder=holder,
source=source,
resource=resource).delete()
def _get_holdings_for_update(holding_keys, resource=None, delete=False):
flt = Q(resource=resource) if resource is not None else Q()
holders = set(holder for (holder, source, resource) in holding_keys)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment