Commit 1542c439 authored by Giorgos Korfiatis's avatar Giorgos Korfiatis

astakos: Improve quota syncing

 - Split code that lists and syncs quotas
 - Merge the latter with qh_sync_users
 - Move qh_sync_projects in quotas.py; sync only active members
 - Add missing select for update in project suspend
 - Clean up quotas.py
parent 201a9714
......@@ -68,7 +68,7 @@ from astakos.im.models import (
AstakosUser, Invitation, ProjectMembership, ProjectApplication, Project,
UserSetting,
get_resource_names, new_chain)
from astakos.im.quotas import (qh_sync_user, qh_sync_users,
from astakos.im.quotas import (qh_sync_user, qh_sync_project,
register_pending_apps)
from astakos.im.project_notif import (
membership_change_notify, membership_enroll_notify,
......@@ -293,7 +293,7 @@ def activate(
if not user.activation_sent:
user.activation_sent = datetime.now()
user.save()
qh_sync_user(user.id)
qh_sync_user(user)
send_helpdesk_notification(user, helpdesk_email_template_name)
send_greeting(user, email_template_name)
......@@ -526,7 +526,7 @@ def accept_membership(project_id, memb_id, request_user=None):
user = membership.person
membership.accept()
qh_sync_user(user.id)
qh_sync_user(user)
logger.info("User %s has been accepted in %s." %
(user.log_display, project))
......@@ -593,7 +593,7 @@ def remove_membership(project_id, memb_id, request_user=None):
user = membership.person
membership.remove()
qh_sync_user(user.id)
qh_sync_user(user)
logger.info("User %s has been removed from %s." %
(user.log_display, project))
......@@ -614,7 +614,7 @@ def enroll_member(project_id, user, request_user=None):
raise PermissionDenied(m)
membership.accept()
qh_sync_user(user.id)
qh_sync_user(user)
logger.info("User %s has been enrolled in %s." %
(membership.person.log_display, project))
......@@ -655,7 +655,7 @@ def leave_project(project_id, request_user):
leave_policy = project.application.member_leave_policy
if leave_policy == AUTO_ACCEPT_POLICY:
membership.remove()
qh_sync_user(request_user.id)
qh_sync_user(request_user)
logger.info("User %s has left %s." %
(membership.person.log_display, project))
auto_accepted = True
......@@ -703,7 +703,7 @@ def join_project(project_id, request_user):
if (join_policy == AUTO_ACCEPT_POLICY and (
not project.violates_members_limit(adding=1))):
membership.accept()
qh_sync_user(request_user.id)
qh_sync_user(request_user)
logger.info("User %s joined %s." %
(membership.person.log_display, project))
auto_accepted = True
......@@ -844,7 +844,7 @@ def approve_application(app_id, request_user=None, reason=""):
qh_release_pending_app(application.owner)
project = application.approve(reason)
qh_sync_projects([project])
qh_sync_project(project)
logger.info("%s has been approved." % (application.log_display))
application_approve_notify(application)
......@@ -865,19 +865,19 @@ def terminate(project_id, request_user=None):
checkAlive(project)
project.terminate()
qh_sync_projects([project])
qh_sync_project(project)
logger.info("%s has been terminated." % (project))
project_termination_notify(project)
def suspend(project_id, request_user=None):
project = get_project_by_id(project_id)
project = get_project_for_update(project_id)
checkAllowed(project, request_user, admin_only=True)
checkAlive(project)
project.suspend()
qh_sync_projects([project])
qh_sync_project(project)
logger.info("%s has been suspended." % (project))
project_suspension_notify(project)
......@@ -892,7 +892,7 @@ def resume(project_id, request_user=None):
raise PermissionDenied(m)
project.resume()
qh_sync_projects([project])
qh_sync_project(project)
logger.info("%s has been unsuspended." % (project))
......@@ -969,11 +969,3 @@ def qh_add_pending_app(user, precursor=None, force=False, dry_run=False):
def qh_release_pending_app(user):
register_pending_apps(user, -1)
def qh_sync_projects(projects):
memberships = ProjectMembership.objects.filter(project__in=projects)
user_ids = set(m.person_id for m in memberships)
qh_sync_users(user_ids)
......@@ -35,7 +35,8 @@ from optparse import make_option
from django.core.management.base import CommandError
from astakos.im.models import AstakosUser
from astakos.im.quotas import set_user_quota, list_user_quotas, add_base_quota
from astakos.im.quotas import (
qh_sync_users, list_user_quotas, add_base_quota)
from astakos.im.functions import get_user_by_uuid
from astakos.im.management.commands._common import is_uuid, is_email
from snf_django.lib.db.transaction import commit_on_success_strict
......@@ -104,30 +105,22 @@ class Command(SynnefoCommand):
else:
users = AstakosUser.objects.verified()
try:
qh_limits, qh_quotas, astakos_i, diff_q = list_user_quotas(users)
except BaseException as e:
logger.exception(e)
raise CommandError("Failed to compute quota.")
if list_only:
qh_quotas, astakos_i = list_user_quotas(users)
info = {}
for user in users:
info[user.uuid] = user.email
info = {}
for user in users:
info[user.uuid] = user.email
if list_only:
print_data, labels = show_quotas(qh_quotas, astakos_i, info)
utils.pprint_table(self.stdout, print_data, labels,
output_format)
else:
elif verify or sync:
qh_limits, diff_q = qh_sync_users(users, sync=sync, diff_only=True)
if verify:
self.print_verify(qh_limits, diff_q)
if sync:
try:
set_user_quota(diff_q)
except BaseException as e:
logger.exception(e)
raise CommandError("Failed to sync quota.")
self.print_sync(diff_q)
def get_user(self, user_ident):
......
......@@ -83,11 +83,10 @@ def get_users_quotas(users, resources=None, sources=None):
return quotas
def get_users_quotas_and_limits(users, resources=None, sources=None):
def get_users_quota_limits(users, resources=None, sources=None):
counters = get_counters(users, resources, sources)
quotas = transform_data(counters)
limits = transform_data(counters, limits_only)
return quotas, limits
return limits
def get_user_quotas(user, resources=None, sources=None):
......@@ -112,7 +111,7 @@ def _level_quota_dict(quotas):
return lst
def set_user_quota(quotas):
def _set_user_quota(quotas):
q = _level_quota_dict(quotas)
qh.set_quota(q)
......@@ -130,10 +129,6 @@ def get_default_quota():
SYSTEM = 'system'
def resolve_pending_serial(serial, accept=True):
return qh.resolve_pending_commission('astakos', serial, accept)
def register_pending_apps(user, quantity, force=False, dry_run=False):
provision = (user.uuid, SYSTEM, 'astakos.pending_app'), quantity
name = "DRYRUN" if dry_run else ""
......@@ -162,13 +157,13 @@ def add_base_quota(user, resource, capacity):
if not created:
obj.capacity = capacity
obj.save()
qh_sync_user(user.id)
qh_sync_user(user)
def remove_base_quota(user, resource):
AstakosUserQuota.objects.filter(
user=user, resource__name=resource).delete()
qh_sync_user(user.id)
qh_sync_user(user)
def initial_quotas(users):
......@@ -244,27 +239,52 @@ def astakos_users_quotas(users, initial=None):
return quotas
def astakos_user_quotas(user):
quotas = astakos_users_quotas([user])
try:
return quotas[user.uuid]
except KeyError:
raise ValueError("could not compute quotas")
def list_user_quotas(users):
qh_quotas, qh_limits = get_users_quotas_and_limits(users)
qh_quotas = get_users_quotas(users)
astakos_initial = initial_quotas(users)
return qh_quotas, astakos_initial
# Syncing to quotaholder
def qh_sync_users(users, sync=True, diff_only=False):
uids = [user.id for user in users]
if sync:
users = AstakosUser.forupdate.filter(id__in=uids).select_for_update()
astakos_quotas = astakos_users_quotas(users)
diff_quotas = {}
for holder, local in astakos_quotas.iteritems():
registered = qh_limits.get(holder, None)
if local != registered:
diff_quotas[holder] = dict(local)
if diff_only:
qh_limits = get_users_quota_limits(users)
diff_quotas = {}
for holder, local in astakos_quotas.iteritems():
registered = qh_limits.get(holder, None)
if local != registered:
diff_quotas[holder] = dict(local)
if sync:
_set_user_quota(diff_quotas)
return qh_limits, diff_quotas
else:
if sync:
_set_user_quota(astakos_quotas)
return None
return (qh_limits, qh_quotas,
astakos_initial, diff_quotas)
def qh_sync_user(user):
qh_sync_users([user])
def qh_sync_projects(projects):
memberships = ProjectMembership.objects.filter(
project__in=projects, state__in=ProjectMembership.ACTUALLY_ACCEPTED)
users = set(m.person for m in memberships)
qh_sync_users(users)
def qh_sync_project(project):
qh_sync_projects([project])
def qh_add_resource_limit(resource, diff):
......@@ -288,13 +308,3 @@ def qh_sync_new_resource(resource, limit):
data.append((key, limit))
qh.set_quota(data)
def qh_sync_users(user_ids):
users = AstakosUser.forupdate.filter(id__in=user_ids).select_for_update()
astakos_quotas = astakos_users_quotas(list(users))
set_user_quota(astakos_quotas)
def qh_sync_user(user_id):
qh_sync_users([user_id])
......@@ -1417,7 +1417,7 @@ class QuotaAPITest(TestCase):
# create user
user = get_local_user('test@grnet.gr')
quotas.qh_sync_user(user.id)
quotas.qh_sync_user(user)
# create another service
service2 = Service.objects.create(
......
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