def post(self, request, taskname): """ Execute a task **Example request**: .. sourcecode:: http POST /api/task/async-apply/tasks.add HTTP/1.1 Accept: application/json Accept-Encoding: gzip, deflate, compress Content-Length: 16 Content-Type: application/json; charset=utf-8 Host: localhost:5555 { "args": [1, 2] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Length: 71 Content-Type: application/json; charset=UTF-8 Date: Sun, 13 Apr 2014 15:55:00 GMT { "state": "PENDING", "task-id": "abc300c7-2922-4069-97b6-a635cc2ac47c" } :query args: a list of arguments :query kwargs: a dictionary of arguments :query options: a dictionary of `apply_async` keyword arguments :reqheader Authorization: optional OAuth token to authenticate :statuscode 200: no error :statuscode 401: unauthorized request :statuscode 404: unknown task """ args, kwargs, options = self.get_task_args() logger.debug("Invoking a task '%s' with '%s' and '%s'", taskname, args, kwargs) try: task = self.capp.tasks[taskname] except KeyError: raise HTTPError(404, "Unknown task '%s'" % taskname) try: self.normalize_options(options) except ValueError: raise HTTPError(400, 'Invalid option') result = task.apply_async(args=args, kwargs=kwargs, **options) response = {'task-id': result.task_id} if self.backend_configured(result): response.update(state=result.state) return self.write(response)
def post(self, request, taskname): """ Execute a task by name and wait results **Example request**: .. sourcecode:: http POST /api/task/apply/tasks.add HTTP/1.1 Accept: application/json Accept-Encoding: gzip, deflate, compress Content-Length: 16 Content-Type: application/json; charset=utf-8 Host: localhost:5555 { "args": [1, 2] } **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Length: 71 Content-Type: application/json; charset=UTF-8 { "state": "SUCCESS", "task-id": "c60be250-fe52-48df-befb-ac66174076e6", "result": 3 } :query args: a list of arguments :query kwargs: a dictionary of arguments :reqheader Authorization: optional OAuth token to authenticate :statuscode 200: no error :statuscode 401: unauthorized request :statuscode 404: unknown task """ args, kwargs, options = self.get_task_args() logger.debug("Invoking a task '%s' with '%s' and '%s'", taskname, args, kwargs) try: task = self.capp.tasks[taskname] except KeyError: raise HTTPError(404, "Unknown task '%s'" % taskname) try: self.normalize_options(options) except ValueError: raise HTTPError(400, 'Invalid option') result = task.apply_async(args=args, kwargs=kwargs, **options) response = {'task-id': result.task_id} return self.write(response)
def post(self, request, taskname): """ Change rate limit for a task **Example request**: .. sourcecode:: http POST /api/task/rate-limit/tasks.sleep HTTP/1.1 Content-Length: 41 Content-Type: application/x-www-form-urlencoded; charset=utf-8 Host: localhost:5555 ratelimit=200&workername=celery%40worker1 **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Length: 61 Content-Type: application/json; charset=UTF-8 { "message": "new rate limit set successfully" } :query workername: worker name :reqheader Authorization: optional OAuth token to authenticate :statuscode 200: no error :statuscode 401: unauthorized request :statuscode 404: unknown task/worker """ workername = self.get_argument('workername') ratelimit = self.get_argument('ratelimit') if taskname not in self.capp.tasks: raise HTTPError(404, "Unknown task '%s'" % taskname) if workername is not None and not self.is_worker(workername): raise HTTPError(404, "Unknown worker '%s'" % workername) logger.info("Setting '%s' rate limit for '%s' task", ratelimit, taskname) destination = [workername] if workername is not None else None response = self.capp.control.rate_limit(taskname, ratelimit, reply=True, destination=destination) if response and 'ok' in response[0][workername]: response = self.write(dict(message=response[0][workername]['ok'])) else: logger.error(response) response = HttpResponse("Failed to set rate limit: '%s'" % self.error_reason(taskname, response)) return response
def get_task_args(self): try: body = self.request.body options = json.loads(body) if body else {} except ValueError as e: raise HTTPError(400, str(e)) args = options.pop('args', []) kwargs = options.pop('kwargs', {}) if not isinstance(args, (list, tuple)): raise HTTPError(400, 'args must be an array') return args, kwargs, options
def get(self, request, task_id): try: task = get_task_by_id(self.settings.state, task_id) except Exception: raise HTTPError(404, "Unknown task '%s'" % task_id) return self.render("flower/task.html", context={'task': task})
def get_current_user(self): # Basic Auth basic_auth = self.settings.basic_auth if basic_auth: auth_header = self.request.headers.get("Authorization", "") try: basic, credentials = auth_header.split() credentials = b64decode(credentials.encode()).decode() if basic != 'Basic' or credentials not in basic_auth: raise HTTPError(401) except ValueError: raise HTTPError(401) # Google OpenID if not self.settings.auth: return True user = self.request.user username = getattr(user, settings.USERNAME_FIELD) if re.search(self.settings.auth, username): return user return None
def get(self, request, taskid): """ Get a task result **Example request**: .. sourcecode:: http GET /api/task/result/c60be250-fe52-48df-befb-ac66174076e6 HTTP/1.1 Host: localhost:5555 **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Length: 84 Content-Type: application/json; charset=UTF-8 { "result": 3, "state": "SUCCESS", "task-id": "c60be250-fe52-48df-befb-ac66174076e6" } :query timeout: how long to wait, in seconds, before the operation times out :reqheader Authorization: optional OAuth token to authenticate :statuscode 200: no error :statuscode 401: unauthorized request :statuscode 503: result backend is not configured """ timeout = self.get_argument('timeout', None) timeout = float(timeout) if timeout is not None else None result = AsyncResult(taskid) if not self.backend_configured(result): raise HTTPError(503) response = {'task-id': taskid, 'state': result.state} if timeout: result.get(timeout=timeout, propagate=False) self.update_response_result(response, result) elif result.ready(): self.update_response_result(response, result) return self.write(response)
def post(self, request, taskid): """ Abort a running task **Example request**: .. sourcecode:: http POST /api/task/abort/c60be250-fe52-48df-befb-ac66174076e6 HTTP/1.1 Host: localhost:5555 **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Length: 61 Content-Type: application/json; charset=UTF-8 { "message": "Aborted '1480b55c-b8b2-462c-985e-24af3e9158f9'" } :reqheader Authorization: optional OAuth token to authenticate :statuscode 200: no error :statuscode 401: unauthorized request :statuscode 503: result backend is not configured """ logger.info("Aborting task '%s'", taskid) result = AbortableAsyncResult(taskid) if not self.backend_configured(result): raise HTTPError(503) result.abort() return self.write(dict(message="Aborted '%s'" % taskid))
def get(self, request): """ List workers **Example request**: .. sourcecode:: http GET /api/workers HTTP/1.1 Host: localhost:5555 **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Length: 1526 Content-Type: application/json; charset=UTF-8 Date: Tue, 28 Jul 2015 01:32:38 GMT Etag: "fcdd75d85a82b4052275e28871d199aac1ece21c" Server: TornadoServer/4.0.2 { "celery@worker1": { "active_queues": [ { "alias": null, "auto_delete": false, "binding_arguments": null, "bindings": [], "durable": true, "exchange": { "arguments": null, "auto_delete": false, "delivery_mode": 2, "durable": true, "name": "celery", "passive": false, "type": "direct" }, "exclusive": false, "name": "celery", "no_ack": false, "queue_arguments": null, "routing_key": "celery" } ], "conf": { "CELERYBEAT_SCHEDULE": {}, "CELERY_INCLUDE": [ "celery.app.builtins", "__main__" ], "CELERY_SEND_TASK_SENT_EVENT": true, "CELERY_TIMEZONE": "UTC" }, "registered": [ "tasks.add", "tasks.echo", "tasks.error", "tasks.retry", "tasks.sleep" ], "stats": { "broker": { "alternates": [], "connect_timeout": 4, "heartbeat": null, "hostname": "127.0.0.1", "insist": false, "login_method": "AMQPLAIN", "port": 5672, "ssl": false, "transport": "amqp", "transport_options": {}, "uri_prefix": null, "userid": "guest", "virtual_host": "/" }, "clock": "918", "pid": 90494, "pool": { "max-concurrency": 4, "max-tasks-per-child": "N/A", "processes": [ 90499, 90500, 90501, 90502 ], "put-guarded-by-semaphore": false, "timeouts": [ 0, 0 ], "writes": { "all": "100.00%", "avg": "100.00%", "inqueues": { "active": 0, "total": 4 }, "raw": "1", "total": 1 } }, "prefetch_count": 16, "rusage": { "idrss": 0, "inblock": 211, "isrss": 0, "ixrss": 0, "majflt": 6, "maxrss": 26996736, "minflt": 11450, "msgrcv": 4968, "msgsnd": 1227, "nivcsw": 1367, "nsignals": 0, "nswap": 0, "nvcsw": 1855, "oublock": 93, "stime": 0.414564, "utime": 0.975726 }, "total": { "tasks.add": 1 } }, "timestamp": 1438049312.073402 } } :query refresh: run inspect to get updated list of workers :query workername: get info for workername :query status: only get worker status info :reqheader Authorization: optional OAuth token to authenticate :statuscode 200: no error :statuscode 401: unauthorized request """ refresh = self.get_argument('refresh', default=False, type=bool) status = self.get_argument('status', default=False, type=bool) workername = self.get_argument('workername', default=None) if status: info = {} for name, worker in self.settings.state.workers.items(): info[name] = worker.alive return self.write(info) if self.worker_cache and not refresh and workername in self.worker_cache: return self.write({workername: self.worker_cache[workername]}) if refresh: try: result = self.update_cache(workername=workername) assert result, 'refresh failed' return self.write({'messages': 'Refreshed'}) except Exception as e: msg = "Failed to update workers: %s" % e logger.error(msg) raise HTTPError(503, msg) if workername and not self.is_worker(workername): raise HTTPError(404, "Unknown worker '%s'" % workername) if workername: response = self.write({workername: self.worker_cache[workername]}) else: response = self.write(self.worker_cache) return response
def get(self, request, taskid): """ Get a task info **Example request**: .. sourcecode:: http GET /api/task/info/91396550-c228-4111-9da4-9d88cfd5ddc6 HTTP/1.1 Accept: */* Accept-Encoding: gzip, deflate, compress Host: localhost:5555 **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Length: 575 Content-Type: application/json; charset=UTF-8 { "args": "[2, 2]", "client": null, "clock": 25, "eta": null, "exception": null, "exchange": null, "expires": null, "failed": null, "kwargs": "{}", "name": "tasks.add", "received": 1400806241.970742, "result": "'4'", "retried": null, "retries": null, "revoked": null, "routing_key": null, "runtime": 2.0037889280356467, "sent": null, "started": 1400806241.972624, "state": "SUCCESS", "succeeded": 1400806243.975336, "task-id": "91396550-c228-4111-9da4-9d88cfd5ddc6", "timestamp": 1400806243.975336, "traceback": null, "worker": "celery@worker1" } :reqheader Authorization: optional OAuth token to authenticate :statuscode 200: no error :statuscode 401: unauthorized request :statuscode 404: unknown task """ task = tasks.get_task_by_id(self.settings.state, taskid) if not task: raise HTTPError(404, "Unknown task '%s'" % taskid) response = task.as_dict() if task.worker is not None: response['worker'] = task.worker.hostname return self.write(response)