From: Maciej Tronowski Date: Thu, 19 Feb 2015 16:08:48 +0000 (+0100) Subject: synchronizing user jobs & basic task list view X-Git-Tag: v1.0~169 X-Git-Url: http://mmka.chem.univ.gda.pl/gitweb/?a=commitdiff_plain;h=f65c86b86fd66ad8b0d45f3a5e4f6169e2e71d19;p=qcg-portal.git synchronizing user jobs & basic task list view --- diff --git a/qcg/templates/qcg/jobs.html b/qcg/templates/qcg/jobs.html index 747d382..78e3dd2 100644 --- a/qcg/templates/qcg/jobs.html +++ b/qcg/templates/qcg/jobs.html @@ -85,66 +85,64 @@ Koniec Status Host - Uwagi +{# Uwagi#} - - - - - - - urban - 04.07.13 17:03 - - - PENDING - hydra - - - - - - - - - urban - 04.07.13 17:03 - - - RUNNING - inula - - - - - - - - - urban - 04.07.13 17:03 - - - FINISHED - inula - - - - - - - - - urban - 04.07.13 17:03 - - - CANCELED - inula - - + {% regroup tasks by job as jobs %} + + {% for job in jobs %} + {% ifequal job.list|length 1 %} + {% with job.list.0 as task %} + + + + +{# {{ task }}#} + + + {{ task.note }} + {{ task.submission_time }} + {{ task.start_time }} + {{ task.finish_time }} + {{ task.get_status_display }} + {{ task.hosts|join:', ' }} + + {% endwith %} + {% else %} + + + + +{# {{ job.grouper }}#} + + + {{ job.grouper.note }} + {{ job.grouper.submission_time }} + - + {{ job.grouper.finish_time }} + {{ job.grouper.get_status_display }} + - + + + {% for task in job.list %} + + + + +{# {{ task }}#} + + + {{ task.note }} + {{ task.submission_time }} + {{ task.start_time }} + {{ task.finish_time }} + {{ task.get_status_display }} + {{ task.hosts|join:', ' }} + + {% endfor %} + {% endifequal %} + {% endfor %} diff --git a/qcg/utils.py b/qcg/utils.py new file mode 100644 index 0000000..353dc0c --- /dev/null +++ b/qcg/utils.py @@ -0,0 +1,60 @@ +from datetime import timedelta +from django.db import transaction +from django.utils.timezone import now +from pyqcg.service import Registry +from pyqcg.utils import Credential, TimePeriod + + +def get_attributes(obj, attrs): + return {name: getattr(obj, name) for name in attrs if getattr(obj, name) is not None} + + +def username_from_dn(dn): + _, username = dn.rsplit('=', 1) + + return username + + +@transaction.atomic +def update_user_data(user, proxy): + from qcg.models import User, Job, Task, Allocation, NodeInfo + + credential = Credential(proxy) + registry = Registry(credential) + + # put lock on user record (hopefully..?) + user = User.objects.select_for_update().get(pk=user.pk) + + changed_filter = {'changed': TimePeriod(after=user.last_update)} + + ################################### + # Jobs + ################################### + for qcg_job in registry.jobs(**changed_filter): + params = Job.qcg_map(qcg_job, user) + job_id = params.pop('job_id') + + Job.objects.update_or_create(job_id=job_id, defaults=params) + + ################################### + # Tasks + ################################### + jobs_cache = {j.job_id: j for j in Job.objects.filter(owner=user)} + for qcg_task in registry.tasks(**changed_filter): + params = Task.qcg_map(qcg_task, jobs_cache) + task_id = params.pop('task_id') + + task, created = Task.objects.update_or_create(job__job_id=qcg_task.job_id, task_id=task_id, defaults=params) + + if not created: + task.allocations.all().delete() + + for qcg_alloc in qcg_task.allocations: + alloc = task.allocations.create(**Allocation.qcg_map(qcg_alloc)) + + for qcg_node in qcg_alloc.nodes: + alloc.nodes.create(**NodeInfo.qcg_map(qcg_node)) + + # release user lock + user.last_update = now() + user.save() diff --git a/qcg/views.py b/qcg/views.py index eb54d58..dd6ecf7 100644 --- a/qcg/views.py +++ b/qcg/views.py @@ -1,11 +1,16 @@ from django.conf import settings from django.contrib.auth import REDIRECT_FIELD_NAME +from django.contrib.auth.decorators import login_required from django.core.urlresolvers import reverse from django.http import HttpResponse from django.shortcuts import render from django.utils.http import urlencode from django_openid_auth.views import make_consumer from openid.extensions import ax +from pyqcg.qcg import QCG +from qcg.models import Task + +from qcg.utils import update_user_data def index(request): @@ -35,8 +40,16 @@ def openid_begin(request): return HttpResponse(openid_request.htmlMarkup(request.build_absolute_uri('/'), return_to)) +@login_required def jobs_list(request): - return render(request, 'qcg/jobs.html') + # QCG.start() + # update_user_data(request.user, request.session['proxy']) + + tasks = Task.objects.filter(job__owner=request.user) \ + .select_related('job').prefetch_related('allocations__nodes') \ + .order_by('-job__submission_time', '-submission_time')[:25] + + return render(request, 'qcg/jobs.html', {'tasks': tasks}) def job_details(request):