def get_workflows(paginate=None): # noqa r"""Get all workflows. --- get: summary: Returns all workflows. description: >- This resource is expecting a user UUID. The information related to all workflows for a given user will be served as JSON operationId: get_workflows produces: - application/json parameters: - name: user in: query description: Required. UUID of workflow owner. required: true type: string - name: type in: query description: Required. Type of workflows. required: true type: string - name: verbose in: query description: Optional flag to show more information. required: false type: boolean - name: search in: query description: Filter workflows by name. required: false type: string - name: sort in: query description: Sort workflows by creation date (asc, desc). required: false type: string - name: status in: query description: Filter workflows by list of statuses. required: false type: array items: type: string - name: page in: query description: Results page number (pagination). required: false type: integer - name: size in: query description: Number of results per page (pagination). required: false type: integer responses: 200: description: >- Requests succeeded. The response contains the current workflows for a given user. schema: type: object properties: total: type: integer items: type: array items: type: object properties: id: type: string name: type: string status: type: string size: type: object properties: raw: type: number human_readable: type: string user: type: string created: type: string progress: type: object examples: application/json: [ { "id": "256b25f4-4cfb-4684-b7a8-73872ef455a1", "name": "mytest.1", "status": "running", "size":{ "raw": 10490000, "human_readable": "10 MB" }, "user": "******", "created": "2018-06-13T09:47:35.66097", }, { "id": "3c9b117c-d40a-49e3-a6de-5f89fcada5a3", "name": "mytest.2", "status": "finished", "size":{ "raw": 12580000, "human_readable": "12 MB" }, "user": "******", "created": "2018-06-13T09:47:35.66097", }, { "id": "72e3ee4f-9cd3-4dc7-906c-24511d9f5ee3", "name": "mytest.3", "status": "created", "size":{ "raw": 184320, "human_readable": "180 KB" }, "user": "******", "created": "2018-06-13T09:47:35.66097", }, { "id": "c4c0a1a6-beef-46c7-be04-bf4b3beca5a1", "name": "mytest.4", "status": "created", "size": { "raw": 1074000000, "human_readable": "1 GB" }, "user": "******", "created": "2018-06-13T09:47:35.66097", } ] 400: description: >- Request failed. The incoming data specification seems malformed. 404: description: >- Request failed. User does not exist. examples: application/json: { "message": "User 00000000-0000-0000-0000-000000000000 does not exist" } 500: description: >- Request failed. Internal controller error. examples: application/json: { "message": "Internal workflow controller error." } """ try: user_uuid = request.args["user"] user = User.query.filter(User.id_ == user_uuid).first() type_ = request.args.get("type", "batch") verbose = json.loads(request.args.get("verbose", "false").lower()) sort = request.args.get("sort", "desc") search = request.args.get("search", "") status_list = request.args.get("status", "") if not user: return jsonify( {"message": "User {} does not exist".format(user_uuid)}), 404 workflows = [] query = user.workflows if search: query = query.filter(Workflow.name.ilike("%{}%".format(search))) if status_list: workflow_status = [ RunStatus[status] for status in status_list.split(",") ] query = query.filter(Workflow.status.in_(workflow_status)) if sort not in ["asc", "desc"]: sort = "desc" column_sorted = getattr(Workflow.created, sort)() pagination_dict = paginate(query.order_by(column_sorted)) for workflow in pagination_dict["items"]: workflow_response = { "id": workflow.id_, "name": get_workflow_name(workflow), "status": workflow.status.name, "user": user_uuid, "created": workflow.created.strftime(WORKFLOW_TIME_FORMAT), "progress": get_workflow_progress(workflow), } if type_ == "interactive" or verbose: int_session = workflow.sessions.first() if int_session: workflow_response["session_type"] = int_session.type_.name workflow_response["session_uri"] = int_session.path workflow_response[ "session_status"] = int_session.status.name # Skip workflow if type is interactive and there is no session elif type_ == "interactive": continue empty_disk_usage = { "human_readable": "", "raw": -1, } if verbose: workflow_response["size"] = (workflow.get_quota_usage().get( "disk", {}).get("usage", empty_disk_usage)) else: workflow_response["size"] = empty_disk_usage workflows.append(workflow_response) pagination_dict["items"] = workflows pagination_dict["user_has_workflows"] = user.workflows.first( ) is not None return jsonify(pagination_dict), 200 except (ValueError, KeyError): return jsonify({"message": "Malformed request."}), 400 except json.JSONDecodeError: return jsonify({"message": "Your request contains not valid JSON."}), 400 except Exception as e: return jsonify({"message": str(e)}), 500
def get_workflow_status(workflow_id_or_name): # noqa r"""Get workflow status. --- get: summary: Get workflow status. description: >- This resource reports the status of workflow. operationId: get_workflow_status produces: - application/json parameters: - name: user in: query description: Required. UUID of workflow owner. required: true type: string - name: workflow_id_or_name in: path description: Required. Workflow UUID or name. required: true type: string responses: 200: description: >- Request succeeded. Info about workflow, including the status is returned. schema: type: object properties: id: type: string name: type: string created: type: string status: type: string user: type: string logs: type: string progress: type: object examples: application/json: { "id": "256b25f4-4cfb-4684-b7a8-73872ef455a1", "name": "mytest-1", "created": "2018-06-13T09:47:35.66097", "status": "running", "user": "******" } 400: description: >- Request failed. The incoming data specification seems malformed. examples: application/json: { "message": "Malformed request." } 403: description: >- Request failed. User is not allowed to access workflow. examples: application/json: { "message": "User 00000000-0000-0000-0000-000000000000 is not allowed to access workflow 256b25f4-4cfb-4684-b7a8-73872ef455a1" } 404: description: >- Request failed. Either User or Workflow does not exist. examples: application/json: { "message": "User 00000000-0000-0000-0000-000000000000 does not exist" } application/json: { "message": "Workflow 256b25f4-4cfb-4684-b7a8-73872ef455a1 does not exist" } 500: description: >- Request failed. Internal controller error. """ try: user_uuid = request.args["user"] workflow = _get_workflow_with_uuid_or_name(workflow_id_or_name, user_uuid) workflow_logs = build_workflow_logs(workflow) if not str(workflow.owner_id) == user_uuid: return ( jsonify({ "message": "User {} is not allowed to access workflow {}".format( user_uuid, workflow_id_or_name) }), 403, ) return ( jsonify({ "id": workflow.id_, "name": get_workflow_name(workflow), "created": workflow.created.strftime(WORKFLOW_TIME_FORMAT), "status": workflow.status.name, "progress": get_workflow_progress(workflow), "user": user_uuid, "logs": json.dumps(workflow_logs), }), 200, ) except ValueError: return ( jsonify({ "message": "REANA_WORKON is set to {0}, but " "that workflow does not exist. " "Please set your REANA_WORKON environment " "variable appropriately.".format(workflow_id_or_name) }), 404, ) except KeyError as e: return jsonify({"message": str(e)}), 400 except Exception as e: return jsonify({"message": str(e)}), 500
def get_workflows(): # noqa r"""Get all workflows. --- get: summary: Returns all workflows. description: >- This resource is expecting a user UUID. The information related to all workflows for a given user will be served as JSON operationId: get_workflows produces: - application/json parameters: - name: user in: query description: Required. UUID of workflow owner. required: true type: string - name: type in: query description: Required. Type of workflows. required: true type: string - name: verbose in: query description: Optional flag to show more information. required: false type: boolean - name: block_size in: query description: Size format, either 'b' (bytes) or 'k' (kilobytes). required: false type: string responses: 200: description: >- Requests succeeded. The response contains the current workflows for a given user. schema: type: array items: type: object properties: id: type: string name: type: string status: type: string size: type: string user: type: string created: type: string progress: type: object examples: application/json: [ { "id": "256b25f4-4cfb-4684-b7a8-73872ef455a1", "name": "mytest.1", "status": "running", "size": "10M", "user": "******", "created": "2018-06-13T09:47:35.66097", }, { "id": "3c9b117c-d40a-49e3-a6de-5f89fcada5a3", "name": "mytest.2", "status": "finished", "size": "12M", "user": "******", "created": "2018-06-13T09:47:35.66097", }, { "id": "72e3ee4f-9cd3-4dc7-906c-24511d9f5ee3", "name": "mytest.3", "status": "created", "size": "180K", "user": "******", "created": "2018-06-13T09:47:35.66097", }, { "id": "c4c0a1a6-beef-46c7-be04-bf4b3beca5a1", "name": "mytest.4", "status": "created", "size": "1G", "user": "******", "created": "2018-06-13T09:47:35.66097", } ] 400: description: >- Request failed. The incoming data specification seems malformed. 404: description: >- Request failed. User does not exist. examples: application/json: { "message": "User 00000000-0000-0000-0000-000000000000 does not exist" } 500: description: >- Request failed. Internal controller error. examples: application/json: { "message": "Internal workflow controller error." } """ try: user_uuid = request.args["user"] user = User.query.filter(User.id_ == user_uuid).first() type = request.args.get("type", "batch") verbose = json.loads(request.args.get("verbose", "false").lower()) block_size = request.args.get("block_size") if not user: return jsonify({"message": "User {} does not exist".format(user)}), 404 workflows = [] for workflow in user.workflows: workflow_response = { "id": workflow.id_, "name": get_workflow_name(workflow), "status": workflow.status.name, "user": user_uuid, "created": workflow.created.strftime(WORKFLOW_TIME_FORMAT), "progress": get_workflow_progress(workflow), "size": "-", } if type == "interactive": if (not workflow.interactive_session or not workflow.interactive_session_name or not workflow.interactive_session_type): continue else: workflow_response[ "session_type"] = workflow.interactive_session_type workflow_response[ "session_uri"] = workflow.interactive_session if verbose: reana_fs = fs.open_fs(SHARED_VOLUME_PATH) if reana_fs.exists(workflow.workspace_path): absolute_workspace_path = reana_fs.getospath( workflow.workspace_path) disk_usage_info = get_workspace_disk_usage( absolute_workspace_path, block_size=block_size) if disk_usage_info: workflow_response["size"] = disk_usage_info[-1]["size"] else: workflow_response["size"] = "0K" workflows.append(workflow_response) return jsonify(workflows), 200 except ValueError: return jsonify({"message": "Malformed request."}), 400 except KeyError: return jsonify({"message": "Malformed request."}), 400 except json.JSONDecodeError: return jsonify({"message": "Your request contains not valid JSON."}), 400 except Exception as e: return jsonify({"message": str(e)}), 500