diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py index 4060cf13096b16d0b1ca5378a395e3267718ab39..62175f115d6a33390632c4811aa2cb7adf52b061 100755 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py @@ -406,49 +406,60 @@ def putTask(task_id): request.headers['Content-Type'].startswith('application/json'): try: updatedTask = json_loads(request.data) - logger.info('putTask: updatedTask: %s', updatedTask) if task_id != int(updatedTask['id']): abort(404, 'task_id in url is not equal to id in request.data') - org_task = radb().getTask(task_id) - - if not org_task: - abort(404, "unknown task %s" % updatedTask) - - for timeprop in ['starttime', 'endtime']: - if timeprop in updatedTask: - try: - updatedTask[timeprop] = asDatetime(updatedTask[timeprop]) - except ValueError: - abort(400, 'timestamp not in iso format: ' + updatedTask[timeprop]) + #check if task is known + task = radb().getTask(task_id) + if not task: + abort(404, "unknown task %s" % str(updatedTask)) + # first handle start- endtimes... if 'starttime' in updatedTask or 'endtime' in updatedTask: - # block time edits in productin for now until we've replaced the old scheduler. + logger.info('starttime or endtime in updatedTask: %s', updatedTask) if isProductionEnvironment(): - abort(403, 'Editing of startime/endtime of tasks by users is not yet approved') + abort(403, 'Editing of %s of tasks by users is not yet approved' % (time,)) + + #update dict for otdb spec + spec_update = {} + + for timeprop in ['starttime', 'endtime']: + if timeprop in updatedTask: + try: + updatedTask[timeprop] = asDatetime(updatedTask[timeprop]) + except ValueError: + abort(400, 'timestamp not in iso format: ' + updatedTask[timeprop]) + otdb_key = 'LOFAR.ObsSW.Observation.' + ('startTime' if timeprop == 'starttime' else 'stopTime') + spec_update[otdb_key] = updatedTask[timeprop].strftime('%Y-%m-%d %H:%M:%S') + + #update timestamps in both otdb and radb + otdbrpc.taskSetSpecification(task['otdb_id'], spec_update) # update the task's (and its claims) start/endtime # do not update the tasks status directly via the radb. See few lines below. task status is routed via otdb (and then ends up in radb automatically) # it might be that editing the start/end time results in a (rabd)task status update (for example to 'conflict' due to conflicting claims) # that's ok, since we'll update the status to the requested status later via otdb (see few lines below) - radb().updateTaskAndResourceClaims(task_id, starttime=updatedTask.get('starttime'), endtime=updatedTask.get('endtime')) + radb().updateTaskAndResourceClaims(task_id, + starttime=updatedTask.get('starttime'), + endtime=updatedTask.get('endtime')) + # ...then, handle status update which might trigger resource assignment, + # for which the above updated times are needed if 'status' in updatedTask: - if isProductionEnvironment() and org_task['type'] == 'observation': - abort(403, 'Editing of observation status by users is not yet approved') - try: - otdbrpc.taskSetStatus(org_task['otdb_id'], updatedTask['status']) + #update status in otdb only + #the status change will propagate automatically into radb via other services (by design) + otdbrpc.taskSetStatus(task['otdb_id'], updatedTask['status']) #block until radb and mom task status are equal to otdb task status (with timeout) start_wait = datetime.utcnow() while True: - org_task = radb().getTask(task_id) - details = momqueryrpc.getObjectDetails(org_task['mom_id']).get(org_task['mom_id']) + task = radb().getTask(task_id) + details = momqueryrpc.getProjectDetails(task['mom_id']).get(task['mom_id']) - if org_task['status'] == updatedTask['status'] and details['object_status'] == updatedTask['status']: + if task['status'] == updatedTask['status'] and details['object_status'] == updatedTask['status']: break if datetime.utcnow() - start_wait > timedelta(seconds=10): @@ -459,12 +470,16 @@ def putTask(task_id): if 'does not exist' in e.message: # task does not exist (anymore) in otdb #so remove it from radb as well (with cascading deletes on specification) - logger.warn('task with otdb_id %s does not exist anymore in OTDB. removing task radb_id %s from radb', org_task['otdb_id'], org_task['id']) - radb().deleteSpecification(org_task['specification_id']) + logger.warn('task with otdb_id %s does not exist anymore in OTDB. removing task radb_id %s from radb', task['otdb_id'], task['id']) + radb().deleteSpecification(task['specification_id']) if 'data_pinned' in updatedTask: - if not curpc.setTaskDataPinned(org_task['otdb_id'], updatedTask['data_pinned']): - abort(500, 'Could not (un)pin task') + task = radb().getTask(task_id) + + if not task: + abort(404, "unknown task %s" % str(updatedTask)) + + curpc.setTaskDataPinned(task['otdb_id'], updatedTask['data_pinned']) return "", 204 except Exception as e: