diff --git a/README.md b/README.md index e16f6d5a4036b200c5b9078cd742c9fb0f69ec10..390f4081066964d84dd4b26be69ff00f3efcb025 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,35 @@ - Docker: https://www.docker.com/ - Python 3.5+ + +## Setup + +In order to run jobs, Opaque needs access to a Docker swarm manager. Currently it's not possible to specify a dedicated Docker host, instead Opaque expects the executing system to to be a swarm manager. + +1. Get the source code and navigate into the code directory +``` +git clone https://gitlab.ub.uni-bielefeld.de/sfb1288inf/opaque.git +cd opaque +``` + +2. Create Docker swarm + +2.1. Local +``` +# Set the variable values in setup_local_swarm.sh (nano setup_local_swarm.sh) +./setup_local_swarm.sh +``` + +2.2. Distributed + +2.2.1. Initialize swarm on manager machine +``` +docker swarm init +``` + +3. Create Python virtual environment, activate it and install the required python packages. +``` +python3 -m venv venv +source venv/bin/activate +pip install -r requirements.txt +``` diff --git a/app/__init__.py b/app/__init__.py index 87043486c0d64f4b683b472d8201af79f78c393e..260f65bd43f2a31521d055b29d21f66d3b7b96b8 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -24,6 +24,9 @@ def create_app(config_name): scheduler.init_app(app) scheduler.start() + from .api import api as api_blueprint + app.register_blueprint(api_blueprint, url_prefix='/api') + from .auth import auth as auth_blueprint app.register_blueprint(auth_blueprint, url_prefix='/auth') diff --git a/app/api/__init__.py b/app/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..27a63156ed63721630000492f12d5c3df57178b5 --- /dev/null +++ b/app/api/__init__.py @@ -0,0 +1,5 @@ +from flask import Blueprint + +api = Blueprint('api', __name__) + +from . import views diff --git a/app/api/views.py b/app/api/views.py new file mode 100644 index 0000000000000000000000000000000000000000..eb86d1056017290aba9b0259371858c8fcbb89b9 --- /dev/null +++ b/app/api/views.py @@ -0,0 +1,76 @@ +from flask import abort, jsonify, request +from flask_login import current_user, login_required +from . import api +from ..models import Job + + +@api.route('/v1.0/corpora') +@login_required +def corpora(): + corpora = [] + for corpus in current_user.corpora.all(): + corpora.append({'id': corpus.id, + 'creation_date': corpus.creation_date.timestamp(), + 'description': corpus.description, + 'title': corpus.title}) + return jsonify(corpora) + + +@api.route('/v1.0/corpora/<int:corpus_id>') +@login_required +def corpus(corpus_id): + corpus = current_user.corpora.filter_by(id=corpus_id).first() + if not corpus: + return abort(404) + return jsonify({'id': corpus.id, + 'creation_date': corpus.creation_date, + 'description': corpus.description, + 'title': corpus.title}) + + +@api.route('/v1.0/jobs') +@login_required +def jobs(): + jobs = [] + all = request.args.get('all') + if all and all.lower() == 'true': + if current_user.is_administrator(): + jobs_query = Job.query + else: + return abort(403) + else: + jobs_query = current_user.jobs + for job in jobs_query.all(): + jobs.append({'id': job.id, + 'creation_date': job.creation_date.timestamp(), + 'description': job.description, + 'end_date': (job.end_date.timestamp() if job.end_date else + None), + 'mem_mb': job.mem_mb, + 'n_cores': job.n_cores, + 'service': job.service, + 'service_args': job.service_args, + 'service_version': job.service_version, + 'status': job.status, + 'title': job.title}) + return jsonify(jobs) + + +@api.route('/v1.0/jobs/<int:job_id>') +@login_required +def job(job_id): + job = current_user.jobs.filter_by(id=job_id).first() + if not job: + return abort(404) + return jsonify({'id': job.id, + 'creation_date': job.creation_date.timestamp(), + 'description': job.description, + 'end_date': (job.end_date.timestamp() if job.end_date else + None), + 'mem_mb': job.mem_mb, + 'n_cores': job.n_cores, + 'service': job.service, + 'service_args': job.service_args, + 'service_version': job.service_version, + 'status': job.status, + 'title': job.title})