Welcome to Pirus’s documentation!

Contents:

Presentation

  • Pirus ( PIpeline RUnner Service) is a tool to manage installation and execution of informatic pipelines.
  • Stand alone project
  • Sub project of Regovar

Goals of Pirus

Pirus aimed at performing computing tasks taking as input files to produce results in the form of one or more files. First devised in order to perform bioinformatic pipelines as part of research and or medical diagnostics, Pirus is for both computer scientists developing these pipelines, as system administrators to ensure the computer server maintenance, that to end users.

Each of them have different needs :

https://raw.githubusercontent.com/REGOVAR/Pirus/master/docs/img/0032.1.png
Sys administrator Bio informaticien Clinician
  • No way they install anything on the server
  • I don’t want to struggle with theirs weirds dependancies
  • Deployement shall be easy
  • I want to do all I want
  • I want to use all softwares I wants (and I choose the version)
  • No time to spent on a endusers graphical interface
  • I don’t want to see any command line
  • I just want to click a button to get my results
  • I’m interruptable, I do many things at the same time, I don’t want to be stuck when waiting my results

Yes ! The solution exists ! Pirus !

https://raw.githubusercontent.com/REGOVAR/Pirus/master/docs/img/0032.2.png

Features

  • Deployement with pip install [TODO]
  • All in one product (server application, client web interface)
  • One simple config file
  • No exotics depencies, no weird customizations
  • Virtual environment for pipeline execution (LXD container)
  • API REST
  • Easy to create a custom pipeline (few technical constraints)
  • Resumable upload for big files
  • Possibility to expose a simple interface to setup a pipeline (according to a unique json file)
  • Push notification for Run progress
  • Mail notification for Run status changed (when finished or when an error occured by example) [TODO]
  • Run can be paused, resumed and canceled

Quick guide

Deploye and use Pirus in 5 minutes. In the below tutorial :
  • <HOST> : is the server host, by example “www.pirus.com”
  • <PORT> ! is the port that will be use by the pirus python application, by example 8080
  • <PIRUS_PATH> : is the path on the server where is deployed the pirus python application, by example “/var/pirus”

Installation

You need to have MongoDB and RabbitMQ installed on your system

sudo apt install rabbitmq-server
sudo apt install mongodb
sudo apt install lxd
sudo apt install nginx

You may need also to install

sudo apt install build-essential libssl-dev libffi-dev python3-dev virtualenv

You can then clone the repository and install requirements

git clone https://github.com/REGOVAR/Pirus.git
cd <PIRUS_PATH>
virtualenv -p /usr/bin/python3.5 venv
source venv/bin/activate
pip install -r requirements.txt

Using NginX

Create the file into /etc/nginx/sites-available/pirus with the following content

Replace <PORT> and <HOST> with the good value:

#
# Virtual Host configuration for <HOST>
#
upstream aiohttp_pirus
{
    server 127.0.0.1:<PORT> fail_timeout=0;
}
server
{
    listen 80;
    listen [::]:80;
    server_name <HOST>;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        proxy_buffering off;
        proxy_pass http://aiohttp_pirus;
    }

    location /static {
        root <PIRUS_PATH>/pirus/templates;
        #TODO : add path to run/files directories
    }
}

Enable this virtual host by creating a symbolic link

sudo ln -s /etc/nginx/sites-enable/pirus /etc/nginx/sites-available/pirus
sudo /etc/init.d/nginx restart

Installing genomic databases

According to the config file of the Pirus application, you will install databases in the folder /var/pirus/databases by examples. You have to put in this directory all heavy databases used by pipes. The organisation shall stay simple, one folder by reference

/var/pirus/databases
        /hg19
                hg19.fa
                1000g.vcf.gz
                1000g.vcf.gz.tbi
                ... <- all other files that could be used by pipelines
        /hg38
                hg38.fa
                ...

Below the command to get all files for hg19 from the gatk public repository

mkdir -p /var/pirus/databases/hg19
cd /var/pirus/databases/hg19
nohup wget ftp://gsapubftp-anonymous@ftp.broadinstitute.org/bundle/hg19/ -r &
# nohup allow the long task to run without bocking your shell session
# you can follow the execution by looking the log
tail -f nohup.out # Ctrl+C to quit

# meanwhile, downloading hg19.fa ref
wget http://hgdownload.soe.ucsc.edu/goldenPath/hg19/bigZips/hg19.2bit
md5sum hg19.2bit # compare fingerprint with online md5

# TODO : choice 1 : installing bioinfo tools on the server or choice 2 : download all file from a directory ?
twoBitToFa hg19.2bit hg19.fa
samtools faidx hg19.fa
bwa index hg19.fa


# when all other downloads are completed (look into nohup.out file)
mv ftp.broadinstitute.org/bundle/hg19/* .


# If you don't trust your connection, you can check if file are not corrupted...
# unfortunately, md5 provided by the broad institute are not for the good files :P
cat *.md5 >> all.md5
sed -i 's/humgen\/gsa-scr1\/pub\/bundle\/2.8\/hg19/var\/pirus\/databases\/hg19/' all.md5
md5sum -c all.md5

# Unfortunately -again-, all gz file in the gatk ftp are not in bzip format... so, to be used
# by bioinformatic's pipelines, we need to redo compression with the good algorithm
# To get the bzip tool, you need to get and compile Htslib (https://github.com/samtools/htslib)
gzip -d *.vcf.gz
rm *.vcf.idx.gz
rm *.md5
for i in `ls -L *.vcf`; bgzip $i;
for i in `ls -L *.vcf.gz`; tabix -p vcf $i;

Run pirus

Your need first to run celery

cd pirus/
celery worker -A pirus_worker --loglevel=info -Q PirusQueue

So you can run pirus web api

python application.py

Check if pirus is working there : http://localhost:8080/v1/www

You can also test pirus direclty from command line by using the pirus executable file

$: pirus file list

Using Pirus

Upload a file

todo

Install a Pipeline

todo

Launch a Run

todo

Developer Guide

Solution organisation

  • The core team of Pirus project:
    • As sub project of Revogar, the core team of Pirus, is the same as for Regovar : Ikit, dridk, Oodnadatta and Arkanosis. All of them are both consultant and developer.
  • Coding Rules :
  • Git branching strategy :
    • Dev on master,
    • One branch by release; with the version number as name (by example branch “v1.0.0” for the v1.0.0)
  • Discussion :

Architecture

See dedicated page

Model

Pipeline

Static property :
public_fields <str[]> : liste des champs exportable pour le enduser (client pirus)

Public properties :
name <str> : (required) human readable name for the pipeline
description <str> : little description about the goal of the pipeline
version <str> :
pirus_api <str> : (required)
license <str> :
developers <str[]> :
size <int> : (required) total size if the pipeline package (used for the upload progress)
upload_offset <int> : (required) current offset position of the upload
status <str> : (required) can take following value : UPLOADING, PAUSE, ERROR, INSTALLING, READY

Internal properties :
pipeline_file <str> : (required) the full path the the pipeline package is stored on the server
root_path <str> : the full path to the root directory where the pipeline is deployed (and so, ready to be used)
lxd_alias <str> : alias of the lxd image that shall be use to create a run with this pipeline
lxd_inputs_path <str> : full path in the lxc container where inputs files shall be mount for the run
lxd_outputs_path <str> : full path in the lxc container where outputs files will be put by the run
lxd_logs_path <str> : full path in the lxc container where logs will be put by the run
lxd_db_path <str> : full path in the lxc container where databases files shall be mount for the run
lxd_run_cmd <str> : bash command that shall be executed in the lxc container of the run to start it
form_file <str> : full path on the server where the json file that describe the form to be used to configure a run is
icon_file <str> : full path on the server where the icon file of the pipeline is

Static methods :
from_id(pipe_id) : return a Pipeline object from the database
remove(pipe_id) : uninstall a pipeline on the server and remove the entry in the database
install(pipe_id) : install a pipeline; as the pipeline have been uploaded, the entry in database already exists, that’s why we only need the pipe_id to install it

Internal methods :
export_server_data(self)
export_client_data(self)
import_data(self, data)
url(self) : return the url that shall be used to download the pipeline package
upload_url(self) : return the url that shall be used to upload the pipeline on the server

Run

Static property :
public_fields <str[]> : liste des champs exportable pour le enduser (client pirus)
Public properties :
pipe_id <str> : (required) the id of the pipe used for this run name <str> : (required) the name set by the user for this run config <str> : the json config data (result of the config form send by the user) provided to the run as input start <str> : end = StringField() status = StringField() # WAITING, PAUSE, INITIALIZING, RUNNING, FINISHING, ERROR, DONE, CANCELED inputs = ListField(StringField()) outputs = StringField() progress = DynamicField(required=True)
Internal properties :
lxc_alias <str> : the alias of the lxc container used for the run

API

See dedicated page for the current api implemented.

  • How to update current api
  • Implement a new version of the api

TUS.IO protocol

API REST : Vue d’ensemble

Le serveur Regovar expose une API Rest via aioHTTP. Tout le code concernant l’API se trouve dans le répertoire /regovar/web. L’API permet d’accéder et de gérer les resources de Regovar ainsi que de réaliser toutes les fonctionnalités proposées par le serveur via une interface web.

Pour connaître les détails concernant les resources et fonctionnalités de Regovar, lire la section concernant le core

Principaux points d’entrée

Les points d’entrée principaux de l’API sont les suivants :

  • /users : pour la manipulation des utilisateurs de Regovar
  • /projects : pour la manipulation des projets de Regovar
  • ... à venir ...

Règles générales

CRUD

    GET     Read
    POST    Create
    PUT     Update
    DELETE  Delete

Réponses et prise en charge des erreurs

Les seuls codes d’erreur HTTP retournés par le server sont : | Code | Description | |——| ———– | |200 | “OK”, le server fonctionne bien et vous a répondu (ce qui ne veut pas dire qu’il n’y a pas eu d’erreur)| |404 | “request not found”, l’url saisie n’existe pas | |403 |“authentication required”, l’utilisateur doit être identifié pour accéder au service, ou bien l’authentification a échoué (mauvais login/mot de passe saisis)| |5XX | “server errors”, une erreur non gérée côté server est survenue et a “cassé” le server... ça craint.|

Donc en théorie, quand tout fonctionne normalement, le server doit toujours renvoyer du JSON (utf8), avec code HTTP valant 200. La structure de la réponse JSON est toujours la même :

En cas de succès du traitement de la requête

HTTP code = 200
{
    "success" : True, // boolean à vrai pour indiquer le traitement avec succès
    
    // Optionnel si resultat attendu
    "data" : json, // toujours formaté en JSON
    
    // Optionnel si pagination du resultat
    "range_offset" : int, // l'offset de départ des résultats
    "range_limit"  : int, // la limit autorisée du nombre de résultats renvoyés utilisé par la requête (1000 par défaut)
    "range_total"  : int, // le nombre total d'éléments en base de donnée (à e pas confondre avec le nombre d'élement retournée par la requête)
}

En cas d’erreur (gérée) lors du traitement de la requête

HTTP code = 200
{
    "success" : False,    // boolean à faux 
    "msg": string,        // un message d'erreur humainement compréhensible en anglais
    "error_code": string, // le code d'erreur
    "error_url": string,  // l'url de la doc en ligne concernant l'erreur
    "error_id": string    // l'identifiant unique de l'erreur qui permet de localiser facilement l'erreur dans les logs.
}

Lazy Loading

Par défaut une requête va retourner les ressources avec un certain nombre de champs renseignés. Pour économiser de la bande passante il est parfois nécessaire de ne récupérer que les infos dont on a besoin. Par défaut les requêtes qui renvoient des listes de résultat ne fournissent qu’un nombre limité d’information, alors que les requêtes qui retournent un seul résultat vont retourner l’ensemble des infos disponibles. Mais tout ceci est détaillé dans les pages dédiées aux points d’accès des différentes ressources.

Pour les requêtes qui supportent le lazy loading (par exemple /users qui retourne la liste des utilisateurs), il est possible de spécifier quels champs à retourner dans la réponse.

Query Parameter : ?fields={fieldname}[,{fieldname2},...]

Exemple : 

GET regovar.org/users
{
    "success" : True,
    "data": [{
        "id" : int;
        "firstname": string,
        "lastname" : string,
        "function" : string,
        "location" : string,
        "email" : string,
        "roles" : json,
        // ...
    }]
}

GET regovar.org/users?fields=id,email
{
    "success" : True,
    "data": [
        {"id" : 1, "email" : "user1@mail.com"},
        {"id" : 2, "email" : "user2@mail.com"}, 
        {"id" : 3, "email" : "user3@mail.com"}, 
        ...]
}

Filtrage

Pour les requêtes qui le supportent (par exemple /users), il est possible de spécifier des paramètres de filtrage pour ne retourner qu’une certaine partie des résultats.

Query Parameter : ?{fieldname}={value}[,{or_value},...][&{fieldname2...}]

  • On peut filtrer en précisant en paramètre un champs de la ressource et la valeur attendue. La liste des champs filtrables est fournie par la requête principale sans aucun argument (dans notre exemple la requête /users). Seuls les attributs directs de la ressource peuvent être filtrés.;
  • On peut filtrer sur plusieurs champs à la fois en les séparant avec le &. Dans ce cas le moteur de filtrage appliquera implicement la condition AND entre chaque champs filtré;
  • On peut filtrer sur plusieurs valeurs pour un même champs, en les séparant avec le symble ,. Pour le moteur de filtrage il s’agira d’appliquer un OR pour chacune de ces valeurs;
  • il n’est pas possible de faire du filtrage complexe via ce systeme. Ainsi pour les recherches ou filtrages nécessitant l’usage d’expression régulière, d’opérateur type >=, etc, si la ressource le permet, une requete dédiée sera proposée (par exemple POST/users/search).
Exemple : 

GET regovar.org/users?firstname=Toto
// Return list of user with firstname == "Toto"
{
    "success" : True,
    "data": [
        {
            "id" : 15,
            "firstname" : "Toto",
            "lastname" : "TOTO",
        }, 
        {
            "id" : 16,
            "firstname" : "Toto",
            "lastname" : "TATA",
        }]
}

GET regovar.org/users?firstname=Toto,Titi&lastname=TATA
// Return list of user with (firstname == "Toto" or "Titi") and with lastname == "TATA"
{
    "success" : True,
    "data": [
        {
            "id" : 16,
            "firstname" : "Toto",
            "lastname" : "TATA",
        }]
}

Ordonner

Pour les requêtes qui le supportent (par exemple /users), il est possible de spécifier des paramètres pour ordonner les résultats selon certains champs par ordre croissant ou décroissant.

Query Parameter : ?sort={field1}[,{field2},...][&desc={fieldX}[,{fieldY}]]

  • L’attribut sort permet de lister les champs dans l’ordre suivant lequel les résultats vont être ordonnés (par ordre croissant pour chaque champs);
  • L’attribut desc liste les champs (parmis ceux avec l’attributs sort qui doivent suivrent l’ordre décroissant et non croissant)
Exemple : 

GET regovar.org/users?sort=lastname,firstname
// Retourne la liste des utilisateur par ordre alphabétique des Nom, puis des Prénoms

GET regovar.org/users?sort=lastname,firstname&desc=lastname
// Retourne la liste des utilisateur par ordre alphabétique inversé des Nom, puis par ordre alphabétique des Prénoms

Identification et authentification

Qui dit internet, dit authentification des utilisateurs à distance, session et mot de passe. Tout cela est géré via le point d’entrée /users, grâce aux actions :

  • POST/users/login : qui permet l’authentification grâce aux paramètres login et password à fournir dans le corps de la requête. Si l’authentification échoue, une erreur 403 est retournée (Forbidden); si elle réussit,
  • GET/users/logout :

API REST : Vue d’ensemble

Le serveur Regovar expose une API Rest via aioHTTP. Tout le code concernant l’API se trouve dans le répertoire /regovar/web. L’API permet d’accéder et de gérer les resources de Regovar ainsi que de réaliser toutes les fonctionnalités proposées par le serveur via une interface web.

Pour connaître les détails concernant les resources et fonctionnalités de Regovar, lire la section concernant le core

Principaux points d’entrée

Les points d’entrée principaux de l’API sont les suivants :

  • /users : pour la manipulation des utilisateurs de Regovar
  • /projects : pour la manipulation des projets de Regovar
  • ... à venir ...

Règles générales

CRUD

    GET     Read
    POST    Create
    PUT     Update
    DELETE  Delete

Réponses et prise en charge des erreurs

Les seuls codes d’erreur HTTP retournés par le server sont :

Code | Description —- | ———– 200 | “OK”, le server fonctionne bien et vous a répondu (ce qui ne veut pas dire qu’il n’y a pas eu d’erreur) 404 | “request not found”, l’url saisie n’existe pas 403 |“authentication required”, l’utilisateur doit être identifié pour accéder au service, ou bien l’authentification a échoué (mauvais login/mot de passe saisis) 5XX | “server errors”, une erreur non gérée côté server est survenue et a “cassé” le server... ça craint.

Donc en théorie, quand tout fonctionne normalement, le server doit toujours renvoyer du JSON (utf8), avec code HTTP valant 200. La structure de la réponse JSON est toujours la même :

En cas de succès du traitement de la requête

HTTP code = 200
{
    "success" : True, // boolean à vrai pour indiquer le traitement avec succès
    
    // Optionnel si resultat attendu
    "data" : json, // toujours formaté en JSON
    
    // Optionnel si pagination du resultat
    "range_offset" : int, // l'offset de départ des résultats
    "range_limit"  : int, // la limit autorisée du nombre de résultats renvoyés utilisé par la requête (1000 par défaut)
    "range_total"  : int, // le nombre total d'éléments en base de donnée (à e pas confondre avec le nombre d'élement retournée par la requête)
}

En cas d’erreur (gérée) lors du traitement de la requête

HTTP code = 200
{
    "success" : False,    // boolean à faux 
    "msg": string,        // un message d'erreur humainement compréhensible en anglais
    "error_code": string, // le code d'erreur
    "error_url": string,  // l'url de la doc en ligne concernant l'erreur
    "error_id": string    // l'identifiant unique de l'erreur qui permet de localiser facilement l'erreur dans les logs.
}

Lazy Loading

Par défaut une requête va retourner les ressources avec un certain nombre de champs renseignés. Pour économiser de la bande passante il est parfois nécessaire de ne récupérer que les infos dont on a besoin. Par défaut les requêtes qui renvoient des listes de résultat ne fournissent qu’un nombre limité d’information, alors que les requêtes qui retournent un seul résultat vont retourner l’ensemble des infos disponibles. Mais tout ceci est détaillé dans les pages dédiées aux points d’accès des différentes ressources.

Pour les requêtes qui supportent le lazy loading (par exemple /users qui retourne la liste des utilisateurs), il est possible de spécifier quels champs à retourner dans la réponse.

Query Parameter : ?fields={fieldname}[,{fieldname2},...]

Exemple : 

GET regovar.org/users
{
    "success" : True,
    "data": [{
        "id" : int;
        "firstname": string,
        "lastname" : string,
        "function" : string,
        "location" : string,
        "email" : string,
        "roles" : json,
        // ...
    }]
}

GET regovar.org/users?fields=id,email
{
    "success" : True,
    "data": [
        {"id" : 1, "email" : "user1@mail.com"},
        {"id" : 2, "email" : "user2@mail.com"}, 
        {"id" : 3, "email" : "user3@mail.com"}, 
        ...]
}

Filtrage

Pour les requêtes qui le supportent (par exemple /users), il est possible de spécifier des paramètres de filtrage pour ne retourner qu’une certaine partie des résultats.

Query Parameter : ?{fieldname}={value}[,{or_value},...][&{fieldname2...}]

  • On peut filtrer en précisant en paramètre un champs de la ressource et la valeur attendue. La liste des champs filtrables est fournie par la requête principale sans aucun argument (dans notre exemple la requête /users). Seuls les attributs directs de la ressource peuvent être filtrés.;
  • On peut filtrer sur plusieurs champs à la fois en les séparant avec le &. Dans ce cas le moteur de filtrage appliquera implicement la condition AND entre chaque champs filtré;
  • On peut filtrer sur plusieurs valeurs pour un même champs, en les séparant avec le symble ,. Pour le moteur de filtrage il s’agira d’appliquer un OR pour chacune de ces valeurs;
  • il n’est pas possible de faire du filtrage complexe via ce systeme. Ainsi pour les recherches ou filtrages nécessitant l’usage d’expression régulière, d’opérateur type >=, etc, si la ressource le permet, une requete dédiée sera proposée (par exemple POST/users/search).
Exemple : 

GET regovar.org/users?firstname=Toto
// Return list of user with firstname == "Toto"
{
    "success" : True,
    "data": [
        {
            "id" : 15,
            "firstname" : "Toto",
            "lastname" : "TOTO",
        }, 
        {
            "id" : 16,
            "firstname" : "Toto",
            "lastname" : "TATA",
        }]
}

GET regovar.org/users?firstname=Toto,Titi&lastname=TATA
// Return list of user with (firstname == "Toto" or "Titi") and with lastname == "TATA"
{
    "success" : True,
    "data": [
        {
            "id" : 16,
            "firstname" : "Toto",
            "lastname" : "TATA",
        }]
}

Ordonner

Pour les requêtes qui le supportent (par exemple /users), il est possible de spécifier des paramètres pour ordonner les résultats selon certains champs par ordre croissant ou décroissant.

Query Parameter : ?sort={field1}[,{field2},...][&desc={fieldX}[,{fieldY}]]

  • L’attribut sort permet de lister les champs dans l’ordre suivant lequel les résultats vont être ordonnés (par ordre croissant pour chaque champs);
  • L’attribut desc liste les champs (parmis ceux avec l’attributs sort qui doivent suivrent l’ordre décroissant et non croissant)
Exemple : 

GET regovar.org/users?sort=lastname,firstname
// Retourne la liste des utilisateur par ordre alphabétique des Nom, puis des Prénoms

GET regovar.org/users?sort=lastname,firstname&desc=lastname
// Retourne la liste des utilisateur par ordre alphabétique inversé des Nom, puis par ordre alphabétique des Prénoms

Identification et authentification

Qui dit internet, dit authentification des utilisateurs à distance, session et mot de passe. Tout cela est géré via le point d’entrée /users, grâce aux actions :

  • POST/users/login : qui permet l’authentification grâce aux paramètres login et password à fournir dans le corps de la requête. Si l’authentification échoue, une erreur 403 est retournée (Forbidden); si elle réussit,
  • GET/users/logout :

Architecture

Overview

https://raw.githubusercontent.com/REGOVAR/Pirus/master/docs/diagrams/architecture_overview.png

Tiers applications

  • Python 3.5 * aioHTTP * ...
  • RabbitMQ
  • MongoDB
  • NginX

Indices and tables