def task_user_callback_cb(task_id, parent_task_id, cb, **kwargs): """ Task for calling remote url in user defined callback """ try: obj = get_task_object(kwargs) except ObjectDoesNotExist: obj = None user = User.objects.get(id=user_id_from_task_id(parent_task_id)) payload, status = get_task_status(parent_task_id) try: response = UserCallback(parent_task_id).request( cb, user.callback_key, payload) except RequestException as ex: status = states.FAILURE details = ex else: status = states.SUCCESS details = str(response.status_code) + ': ' + response.reason if cb.get('cb_log'): task_log(parent_task_id, LOG_REMOTE_CALLBACK, obj=obj, task_status=status, detail=details)
def task_log_cb(result, task_id, task_status=None, msg='', vm=None, obj=None, cleanup=False, check_returncode=False, **kwargs): """ Log callback -> logs finished task. """ if vm: obj = vm if not obj: try: obj = get_task_object(kwargs) except ObjectDoesNotExist: pass if cleanup: # Sometimes when an execute task fails with an exception or is revoked # we might need to run things that the callback would run. But now the # callback won't run so emergency cleanup should go into this function. try: logger.info('Running cleanup for task=%s with task_status=%s', task_id, task_status) task_cleanup(result, task_id, task_status, obj, **kwargs) except Exception as e: logger.exception(e) logger.error( 'Got exception (%s) when doing cleanup for task=%s, task_status=%s, obj=%s', e, task_id, task_status, obj) if check_returncode: rc = result.get('returncode', None) if rc != 0: err = 'Got bad return code (%s)' % rc err_msg = result.get('message', None) if err_msg: err += ' Error: %s' % err_msg logger.error( 'Found nonzero returncode in result from %s. Error: %s', kwargs.get('apiview', msg), result) raise TaskException(result, err) task_log(task_id, msg, obj=obj, task_status=task_status, task_result=result) return result
def _update(cls, task_id, repo): err = res = images = None repo_url = repo.get_images_url() logger.info('Downloading images from image repository %s (%s)', repo.name, repo_url) try: curl = HttpClient(repo_url) res = curl.get(timeout=cls.HTTP_TIMEOUT, max_size=cls.HTTP_MAX_SIZE, allow_redirects=True) images = res.json() except RequestException as exc: err = '%s' % exc except ValueError as exc: err = 'Image server response could not be decoded (%s)' % exc else: if not isinstance(images, list): err = 'Unexpected output from image server (%s)' % type(images) if err: status = FAILURE msg = err logger.error(err) repo.error = err repo.save() else: status = SUCCESS img_count = len(images) msg = u'Downloaded metadata for %d images from image repository %s in %d μs' % ( img_count, repo.name, res.elapsed.microseconds) logger.info(msg) repo.image_count = img_count repo.last_update = timezone.now() repo.error = None repo.save(images=images) del images # The list can be big => remove from memory, we don't need it now task_log(task_id, LOG_IMAGE_STORE_UPDATE, obj=repo, task_status=status, detail=msg, update_user_tasks=False) return repo
def save(self, status): """Save task log entry if result is not None""" if hasattr(status, '__iter__'): status = [i for i in status if i is not None] # remove None from result if status: success = all(status) else: success = None else: success = status if success is None: return if success: task_status = states.SUCCESS else: task_status = states.FAILURE task_log(self.task_id, self.msg, obj=self.obj, task_status=task_status, task_result=True, detail=self.get_detail(), dc_id=self.dc_id, update_user_tasks=False)
def vm_status_changed(tid, vm, state, old_state=None, save_state=True, deploy_over=False, change_time=None): """ This function is something like a dummy callback. It should be called when VM state is changed from a task. """ if change_time: old_change_time = cache.get(Vm.status_change_key(vm.uuid)) if old_change_time and old_change_time > change_time: logger.warn( 'Ignoring status change %s->%s of VM %s (%s) because it is too old: %s > %s', vm.status, state, vm, vm.uuid, old_change_time, change_time) return None # save to DB and also update cache if save_state: vm.status = state if old_state is not None: # if cached status != vm.status (don't remember why we need this) vm._orig_status = old_state vm.save(update_fields=('status', 'status_change', 'uptime', 'uptime_changed'), status_change_time=change_time) if deploy_over: # deploy process ended # Set the deploy_finished flag to inform vm_create_cb vm.set_deploy_finished() if vm.is_slave_vm(): logger.info('Detected status change of slave VM %s - "%s"', vm.uuid, vm) return None # Adjust task ID according to VM parameters tid = task_id_from_task_id(tid, owner_id=vm.owner.id, dc_id=vm.dc_id) # Signals! vm_status_changed_sig.send(tid, vm=vm, old_state=old_state, new_state=state) # Signal! if vm.status == vm.RUNNING: vm_running.send(tid, vm=vm, old_state=old_state) # Signal! elif vm.status == vm.STOPPED: vm_stopped.send(tid, vm=vm, old_state=old_state) # Signal! # data for next operations msg = LOG_STATUS_CHANGE task_event = VmStatusChanged(tid, vm) # log task task_log(tid, msg, vm=vm, owner=vm.owner, task_result=task_event.result, task_status=states.SUCCESS, time=vm.status_change, update_user_tasks=False) # inform users (VM owners logged in GUI) task_event.send()
def __init__(self, request, result, task_id, msg='', vm=None, obj=None, owner=None, api_view=None, api_data=None, detail='', detail_dict=None, callback=None, **kwargs): if api_view is None: api_view = {} if api_data is None: api_data = {} if vm: obj = vm if task_id: # Exceptions set the task_id to None task_pending = False # noinspection PyBroadException try: t_s = result['status'] except Exception: t_s = None # noinspection PyBroadException try: t_r = result['result'] except Exception: t_r = None if msg: # msg => update task log & save pending user task if detail_dict: detail = self.check_detail(detail) detail += self.dict_to_detail(detail_dict) detail = self.save_callback(task_id, callback, detail=detail) task_pending = task_log(task_id, msg, obj=obj, user=request.user, api_view=api_view, owner=owner, task_status=t_s, task_result=t_r, detail=detail) elif t_s in TASK_STATE_PENDING and obj: # => save pending user task task_pending = True self.save_callback(task_id, callback) try: obj.tasks_add(task_id, api_view) except Exception as e: logger.exception(e) logger.error( 'Got exception (%s) when updating task %s for %s.', e, task_id, obj) if task_pending: # pending user task => send 'task-created' event context = request.parser_context # Send celery 'task-created' event, which may be captured by sio.monitor.que_monitor() # (this is a replacement for the internal 'task-sent' celery event) TaskCreatedEvent(task_id, apiview=api_view, task_status=t_s, task_result=t_r, method=request.method, view=context['view'].__class__.__name__, siosid=getattr(request, 'siosid', None), args=context['args'], kwargs=context['kwargs'], apidata=api_data).send() for i in UNUSED_RESPONSE_KWARGS: try: del kwargs[i] except KeyError: pass super(BaseTaskResponse, self).__init__(result, request=request, **kwargs) # Set es_task_id header self['es_task_id'] = task_id or '' # Attributes used by sio.namespaces.APINamespace self.apiview = api_view self.apidata = api_data