= Soumission des Jobs = [[TracNav]] [[TOC(inline)]] Pour effectuer cette partie du tutorial, il faut télécharger le [http://quattor.web.lal.in2p3.fr/packages/tutorial/tutorial-lal.tar.gz tarfile] contenant les fichiers utilisés dans les exercices et le désarchiver dans votre répertoire de travail. S'il n'y a pas de browser web accessible sur l'UI, il est possible d'utiliser la commande : {{{ wget http://quattor.web.lal.in2p3.fr/packages/tutorial/tutorial-lal.tar.gz }}} == Premiers pas... == === Principales Commandes === Les commandes permettant de soumettre et gérer un job commencent toutes par `glite-wms-job-` et utilise les services d'un gLite WMS. ''Note : pour soumettre et gérer un job avec l'ancien LCG RB, il faut utiliser les commandes `edg-job-`. Ces commandes sont obsolètes et il faut préférer l'utilisation d'un WMS, sauf raisons très particulières. De même il ne faut pas utiliser les commandes `glite-job-xxx`, elles-mêmes obsolètes.'' Les principales commandes sont : * `glite-wms-job-submit` : soumission d'un job. Cette commande nécessite un ''delegation proxy'' qui peut être créé automatiquement si on utilise l'option `-a` ou être créé avec la commande `glite-wms-job-delegation-proxy` et être spécifié avec l'option `-d identifieur`. L'utilisation de `-d` doit être préférée si on soumet plusieurs jobs car elle est beaucoup plus efficace. * `glite-wms-job-status` : affichage de l'état d'un job (en attente, en cours d'exécution, terminé...). L'option `--all` permet d'afficher l'état de tous les jobs de l'utilisateur, si le LB (''Logging and Bookkeeping'', l'un des services du WMS) utilisé fait partie des LBs configurés par défaut sur l'UI. L'option '--verbosity n' (`-v n`) permet de modifier le niveau de verbosité. Il est conseillé d'utiliser `-v 1`. * `glite-wms-job-cancel` : permet d'annuler (de tuer) un job soumis. * `glite-wms-job-output` : récupération de l'output du job. Le répertoire utilisé pour stocker les résultats dépend de la configuration du site. Au LAL, le répertoire est `~/JobOutput/`. Ce répertoire '''doit exister''' avant l'exécution de la commande : il faut le créer si nécessaire. Il est possible d'utiliser l'option --dir qui spécifie le repertoire ou l'on stockera les outputs * `glite-wms-job-logging-info` : affichage d'informations détaillées sur l'exécution du job et les éventuelles erreurs rencontrées. * `glite-wms-job-delegate-proxy -d identifieur` : obtention d'un `delegation proxy` pour soumettre plusieurs jobs. `identifieur` est un nom arbitraire qui sera utilisé pour désigner le ''delegation proxy'' et l'utiliser dans avec les commandes comme `glite-wms-job-submit`. ''Note: l'utilisation des commandes `glite-wms-job-xxx` nécessite d'avoir un proxy valide.'' Toutes les commandes ont une aide en ligne accessible en utilisant l'option `--help` ou la commande `man`. La commande `glite-wms-job-submit` retourne un ''jobid'' qui est un URL. Ce ''jobid'' devra être utilisé pour désigner le job dans les autres commandes. Il doit être conservé sans quoi il n'est plus possible d'interagir avec le job (connaitre son état ou récupérer son output). Quand on soumet plusieurs jobs, il peut être plus pratique d'utiliser l'option `-o fichier` lors du submit : dans ce cas, le ''jobid'' sera écrit dans le fichier. Le même fichier pourra être utilisé à la place du paramètre ''jobid'' dans les autres commandes en utilisant l'option `-i`. Les commandes `glite-wms-job-xxx` nécessitant d'avoir un proxy valide, il n'y a pas besoin de spécifier la VO utilisée pour ces commandes. Elle est obtenue à partir du proxy. Il existe également des APIs ([http://glite.web.cern.ch/glite/documentation/R3.0/autogen/org.glite.wms/org.glite.wms.wmproxy-api-java/doc/autogen/html/index.html Java], C, C++) qui permettent la gestion des jobs depuis une application. Ce tutorial ne couvre pas la description de ces APIs. === Soumission d'un Job "Hello World" === Cette exercice consiste à soumettre un job très simple qui écrira "Hello World" dans le fichier d'output. Le job en lui-même n'a pas d'intérêt particulier mais permet d'illuster la soumission et le suivi de l'exécution d'un job. Un job grille est décrit dans un langage particulier appelé [wiki:Tutorial/JobSubm#DescriptiondesJobsJDL JDL]], décrit dans la partie suivante. 1. Si ce n'est pas déjà fait, créez un proxy à l'aide de la fonction `voms-proxy-init`. 1. Soumettez le job `HelloWorld.jdl` se trouvant dans le matériel du tutorial récupéré précédemment, en utilisant la commande `glite-wms-job-submit`. Sauver le ''jobid'' retourné ou utiliser l'option `-o`. 1. Vérifiez le statut du job en utilisant la commande `glite-wms-job-status -v 1`. On peut utiliser la commande `watch` pour exécuter une commande dans une boucle (pour effectuer la commande `glite-wms-job-status` toutes les 15 secondes, utilisez `watch -n 15 glite-wms-job-status -v 1 ` et taper ctrl-c pour sortir). * Suivez les modifications de l'état du job jusqu'à l'état "Done(Success)". * Combien d'états différents pouvez-vous distinguer ? * Si le job se termine dans l'état "Aborted", c'est qu'il y a eu une erreur. On peut trouver plus d'informations avec la commande `glite-wms-job-get-logging-info`. 1. Lorsque le job est terminé (Status: Done (Success)), récupérez les données générées à l'aide de la commande `glite-wms-job-output`. 1. Vérifiez que tout s'est déroulé correctement en consultant les fichiers `std.out` et `std.err`. Le fichier `std.err` doit être vide et `std.out` doit contenir "Hello World". Cette procédure simple est utilisée pour le suivi de tous les jobs. == Description des Jobs (JDL) == === Modification et Edition === Le fichier de description des jobs (JDL) utilise un langage particulier pour décrire les attributs et besoins du job. Ces informations sont utilisés par le WMS pour sélectionner le CE approprié à l'exécution du job et par le CE pour lancer l'application de l'utilisateur. Le format de ce fichier est un ensemble de définition attribut/valeur, en utilisant le format suivant : {{{ Attribut: Valeur; }}} ''Note: `Attribut` n'est pas case sensitive. Certaines valeurs le sont, par exemple des noms de fichiers. Les chaines de caractères doivent être entre `"`.'' Les principaux attributs sont: * `Executable` (obligatoire) : définit la commande à exécuter. S'il s'agit d'un shell script, le shell utilisé par le script (indiqué dans la ligne `#!`) doit exister dans le worker node. * `Arguments` (facultatif) : une chaine de caractère passée comme argument de la commande, en utilisant la syntaxe attendue par la commande. * `InputSandbox` (facultatif) : liste des fichiers locaux à transférer avec le job. * `OutputSandbox` (obligatoire) : liste des fichiers produits par le job et devant être retournés par la commande `glite-wms-job-output`. Il doit y avoir au moins `stdout` et `stderr`. Pour plus d'information, consulter la liste des [http://server11.infn.it/workload-grid/docs/DataGrid-01-NOT-0101-0_6-Note.pdf attributs] JDL valides. __Exercices__ : 1. Modifiez le fichier `HelloWorld.jdl` de manière à ce qu'il n'appelle plus `/bin/echo` mais le script `HelloWorldScript.sh`. Pour cela : * la ligne `Executable` doit être `HelloWorldScript.sh` * la ligne `Arguments` peut rester avec `Hello World` * Il faut définir le paramètre `InputSandbox`. Tous les fichiers listés dans `InputSandbox` sont transfèrés avec le job. Quand on soumet plusieurs jobs avec les mêmes fichiers d'entrée, une nouvelle copie des fichiers est créée pour chaque job. 1. Modifier de nouveau `HelloWorld.jdl` de manière à ce qu'il appelle cette fois l'exécutable `myhostname`. Vous pouvez visualiser la source de cet exécutable, qui est un programme C : `myhostname.c`. Vous n'avez cette fois pas besoin de définir d'argument. Il faut modifier la ligne `InputSandbox`. Exécutez le job et vérifiez que tout fonctionne. Sur quel ordinateur a tourné votre job ? 1. L'exécution d'un programme en C compilé n'est pas forcément pratique : l'exécutable peut être d'une grande taille, dépendre de plusieurs fichiers, ou dépendre d'un environnement d'exécution particulier. Une solution consiste à compiler le programme directement sur le CE. Modifier une nouvelle fois `HelloWorld.jdl` de manière à ce qu'il appelle le script `buildandrun.sh`, avec pour argument `myhostname`. * Testez ce script seul pour comprendre l'argument nécessaire. * Exécutez le job et vérifiez qu'il fonctionne toujours. * Votre job a-t-il tourné sur le même ordinateur que précédemment? ''Note : si la VO que vous utilisez est acceptée par plusieurs CE, il peut être utile d'ajouter la ligne suivante dans votre JDL pour forcer le job à aller sur un CE particulier (sur le CE `grid10.lal.in2p3.fr` LAL dans l'exemple) :'' {{{ Requirements = regexp("grid10\.lal\.in2p3\.fr:.*", other.GlueCEUniqueID); }}} === Requirements et Rank === Il y a deux mots-clés très importants dans les fichiers JDL : `Requirements` et `Rank` . Leurs valeurs sont des expressions. Ces deux mot-clés servent à sélectionner le CE auxquels sera envoyé le job. * `Requirements` : ce mot-clé permet de sélectionner les CE qui ont les ressources requises pour exécuter le job. L'expression des ressources peut porter sur n'importe quelle information publié dans le système d'information (BDII). En particulier, le nombre de CPUs libres, le temps d'exécution minimum, et la quantité de mémoire. La valeur est une condition logique utilisant une syntaxe assez habituelle (proche de celle du langage C). On peut utiliser des ''regular expressions'' avec les chaines de caractères, en utilisant la fonction `RegExp(pattern, attribut)`. Par exemple, pour sélectionner un CE appartenant au domaine `lal.in2p3.fr`, on pourra utiliser l'expression : {{{ Requirements = regexp(".*\.lal\.in2p3\.fr:.*", other.GlueCEUniqueID); }}} * `Rank` : cet mot-clé définit l'ordre de classement des CEs sélectionnés par la clause `Requirements`. Le CE sélectionné pour exécuter le job est celui ayant le meilleur classement suivant le critère défini par `Rank`. En cas d'ex-aequo, le CE est choisi aléatoirement parmi eux. Par exemple pour trier sur le nombre de CPUs libres dans le CE : {{{ Rank = other.GlueCEStateFreeCPUs; }}} Le résultat de l'évaluation de `Requirements` et `Rank` est différent suivant la VO utilisée car toutes les sites n'acceptent pas les mêmes VOs. On peut connaitre le résultat de l'évaluation de `Requirements` et `Rank` avant de soumettre le job en utilisant la commande `glite-wms-job-list-match` et en indiquant le fichier JDL en paramètre. Cette commande retourne la liste des CEs sélectionnés par Requirements, classés dans l'ordre indiqué par `Rank`. On peut exécuter cette commande pour une VO pour laquelle on a pas de proxy en ajoutant l'option `--vo voname` (par exemple : `--vo dteam`). __Exercices__ : Dans les exercices proposés, vous allez éditer le fichier `HelloWorld.jdl` pour modifier les expressions `Requirements` et `Rank`. Pour voir l'effet de la modification, utiliser la commande `glite-wms-job-list-match` puis essayer de soumettre le job en utilisant la commande `glite-wms-job-submit`. Pour soumettre le job, vous devez avoir un proxy valide. 1. Sélectionner les sites qui acceptent des jobs nécessitant plus de 1 heure de CPU : {{{ Requirements = (other.GlueCEPolicyMaxCPUTime > 60); }}} 1. Essayer de modifier la clause `Requirements` pour demander plus de 2h, plus de 24h. Indiquer le besoin en temps d'exécution total plutôt qu'en temps CPU (`other.GlueCEPolicyMaxWallClockTime`). 1. Choisir uniquement des sites francais. Pour cela on peut utiliser la valeur suivante (d'abord seule puis en la combinant avec la précédente avec l'opérateur `&&`) : {{{ RegExp(".*\.fr:.*",other.GlueCEUniqueID) }}} 1. Sélectionner un CE offrant la version R2008b de MatLab (publiée avec le ''software tag'' `MATLAB_R2008B`) en utilisant la fonction `Member`: {{{ Requirements = Member("MATLAB_R2008B", other.GlueHostApplicationSoftwareRunTimeEnvironment); }}} 1. Ajoutez les lignes suivantes pour utiliser la ressource avec le plus grand nombre des CPUs libres et comparer le CE qui sera sélectionné. {{{ Rank = other.GlueCEStateFreeCPUs; }}} 1. Utiliser la valeur `-other.GlueCEStateFreeCPUs` : quelle est l'effet ? 1. Que se passe-t-il si on utilise `Rank = 1;`? ''Note : Une option `-r` existe pour la commande `glite-wms-job-submit` qui permet de choisir une ressource spécifique. Cependant cette option court-circuite le processus de match-making du Resource Broker (sélection du CE approprié à partir des différents requirements) et ne crée pas le fichier nécessaire (`BrokerInfo`) pour la gestion de données. Il faut donc préférer l'utilisation de `other.GlueCEUniqueID` dans la ligne `Requirements`.'' === Controlling Retries done by WMS === After the job has been submitted to WMS, WMS goes through several phases until final submission of the job to the CE and its execution. For various reasons, errors can occured at each stage and a user can control the number of retries WMS must do through two JDL attributes: * `ShallowRetryCount`: defines the maximum number of times the WMS try to submit a job to the selected CE in case of an error occured at submission time, before the job has actually started. This is called a ''shallow resubmission'' : at each attempt, a different CE is selected. Default is site specific and there is a maximum defined on the WMS itself. * `RetryCount`: defines the maximum number of times the WMS try to resubmit a job in case of an error occured after the job started to run on the CE. This is called a ''deep resubmission'' : specific actions may be required to cleanup files left by the previous run attempt. The default is site specific and there is a maximum defined on the WMS itself. In addition to resubmission, the WMS can retry the first phase of the job processing, called ''match making'', responsible for selecting a CE. In the event of an error during this phase, the ''match making'' is retried at an interval defined by the site during a maximum period also defined by the site. The user has no control on this. During this period the job status is `Waiting` and if the ''match making'' fails after the maximum period allowed the request job fails with a status reason which is either `No compatible resource` (match making process failed to find a resource matching job requirements) or `Request expired` if the match making failed because the maximum period allowed was reached before `ShallowRetryCount`. ''Note: when debugging jobs, it is often desirable to set `RetryCount` and `ShallowRetryCount` to 0 to get a quick feedback in case of errors.'' === Some Other Useful JDL Attributes === JDL files accept many [http://server11.infn.it/workload-grid/docs/DataGrid-01-NOT-0101-0_6-Note.pdf different attributes]. In addition to those already described, a few other useful attributes are: * `ShortDeadlineJob`: if `true`, WMS adds requirements to ensure the job is queued on a CE accepting such jobs (a Short Deadline Job is a job that must be run immediately if accepted by the CE but has generally very short limit in CPU time). ''Note: This attribute is treated after the match making on the WMS and doesn't affect the output of the `glite-wms-job-list-match` command.'' __Exercices__ : 1. Add the `ShortDeadlineJob` attribute to the job description and submit the job. Verify that the job runs on a queue with "sdj" in the name. == L'environnent d'exécution sur le Worker Node [NPF] == Chaque utilisateur de la grille est associé à un compte local, spécifique à chaque site. L'accès aux ressources locales est contrôlé par les droits de ce compte. Si on soumet plusieurs jobs en utilisant des proxies différents (VO et/ou groupe/rôle), on n'est pas associé au même compte sur le worker node. L'exercice suivant permet de l'illustrer. __Exercices__ : 1. Initialiser votre proxy sans utiliser de groupe/rôle particulier. 1. Visualisez le contenu du fichier JDL `whoami.jdl`. Lancez le job et récupérez l'output. Visualisez le fichier `std.out`. Sur quel compte êtes-vous mappé? 1. Visualisez le contenu du script `envvar.jdl`. Soumettez un job qui lance ce script dans la grille. Regardez la liste des variables. Combien de variables concernent la grille? 1. Ecrivez un job qui liste les versions des logiciels disponibles dans le `Worker Node`. On peut utiliser la commande `rpm` pour le faire. 1. Initialiser un nouveau proxy en utilisant le [wiki:Tutorial/Authorization#UtilisationdesGroupesetRôlesdansuneVO rôle] `Tutorial1` ou `Tutorial2`, suivant celui que vous avez le droit d'utiliser et reexécuter le fichier JDL `whoami.jdl`. == Renouveler le proxy en cours de job == Par défaut, la validité d'un proxy est relativement courte, généralement entre 12 et 96h. La durée maximale est fixée par le serveur VOMS de la VO. Si le proxy expire avant la fin du job, il ne sera pas possible de récupérer les résultats. S'il expire avant le début du job, le job échouera. Pour permettre à un job de s'exécuter sans problème quelque soit son temps d'attente et sa durée, il faut utiliser un service de renouvellement de proxy, appelé MyProxy. Son utilisation est très simple. Il faut d'abord ajouter la ligne suivante dans le JDL du job (la valeur du paramètre doit être un serveur MyProxy acceptant la VO utilisée pour le `voms-proxy-init` et le resource broker utilisé pour soumettre le job, `myproxy.grif.fr` est le serveur MyProxy de GRIF) : {{{ MyProxyServer = "myproxy.grif.fr"; }}} Après avoir fait le `voms-proxy-init` et avant de soumettre le job, il faut exécuter la commande `myproxy-init`, comme suit : {{{ myproxy-init -d -n -s myproxy.grif.fr }}} La configuration d'un serveur MyProxy détermine les resource brokers autorisés à utiliser le service pour renouveler des proxies. Le serveur MyProxy de GRIF, `myproxy.grif.fr`, accepte les demandes de renouvellement en provenance du RB de GRIF, `grid09.lal.in2p3.fr`. On peut voir la liste des proxies valides avec la commande `myproxy-info` et on peut mettre fin au renouvellement du proxy (avant ou pendant l'exécution du job) avec la commande `myproxy-destroy`. L'option `-d` doit être toujours être utilisée avec l'ensemble des commandes `myproxy-*.` ''Note : les commandes `myproxy-xxx` utilisent un nom de fichier différent des autres commandes gLite si on utilise un fichier unique pour le certificat et la clé privée (extension `.p12`). Pour résoudre le problème, il faut créer le lien symbolique suivant :'' {{{ cd ~/.globus ln -s usercert.p12 usercred.p12 }}} __Exercices__ : 1. Utiliser la commande `myproxy-init` pour vérifier que vous pouvez créer un proxy dans le serveur. 1. Utiliser aussi les commandes `myproxy-info` et `myproxy-destroy`. == Soumission d'un job MPI (facultatif) [NPF] == Beaucoup de disciplines utilisent des jobs parallèles. MPI (Message PassingInterface) est un protocole qui permet la communication entre les tâches parallèles. Les jobs MPIs sont supportés dans la grille. La grille permet d'utiliser les différentes versions et implémentations de MPI : * MPI v1 : LAM MPICH * MPI v2 : openMPI et MPICH2 Le logiciel `mpi-start` développé par le projet européen [http://www.interactive-grid.eu/ int.eu.grid] facilite l'utilisation du MPI dans la grille. Pour plus de détails, voir le [https://wiki.fzk.de/i2g/index.php/Compiling_and_running_MPI_parallel_Applications:_what_is_different_on_the_Grid Running MPI on grid] and the [https://wiki.fzk.de/i2g/index.php/Hook_CookBook Hook Cook Book]. L'utilisateur peut définir : 1. Un script à exécuter avant le binaire MPI (par exemple pour compiler le programme), 1. Le programme lui-même, et 1. Un script à exécuter après le binaire MPI (par exemple pour enregistrer les résultats dans un SE). Le fichier `mpi-hooks.sh` définit les scripts à exécuter avant et après le binaire MPI. Le fichier JDL définit les paramètres comme des nombres de CPU pour le job. La grille supporte les jobs MPI sur un seul site. MPI avec esclaves sur plusieurs sites n'est pas supporté. Les informations officielles à jour pour l'utilisation de MPI sur la grille EGEE sont disponibles sur le site [http://egee-uig.web.cern.ch/egee-uig/production_pages/MPIJobs.html EGEE UIG]. Plus de détails sont disponibles sur le site du [http://www.grid.ie/mpi/wiki MPI Working Group]. __Exercices__ : 1. Lancez un job avec `MPIHelloWorld.jdl` Regardez la sortie du job. S'il a fonctionné correctement, on pourra lire des lignes telles que: * `Hello world! from processor 3 out of 8` 1. Changez le nombre de CPUs utilisé par le job. Vérifiez que le job marche toujours. Fonctionne t-il aussi si vous spécifiez 1000 CPU? == Fonctionnalités Avancées (facultatif) == === Collection de jobs (bulk submission) === La ''bulk submission'' permet de soumettre une collection de jobs indépendants en une seule commande. Pour cela, il faut mettre tous les .jdl dans un même directory et utiliser l'option --collection avec glite-wms-job-submit en donnant comme argument le nom du directory contenant les .jdl. Ce mécanisme est très performant et préférable à la soumission individuel d'un grand nombre de jobs. Ici nous avons par exemple trois fichiers .jdl dans le directory jdl : {{{ [diarra@ipnlinux2 ~/work]$ ls -l jdl/* -rw-r--r-- 1 diarra sii 247 Jun 3 17:25 jdl/job1.jdl -rw-r--r-- 1 diarra sii 247 Jun 3 17:25 jdl/job2.jdl -rw-r--r-- 1 diarra sii 247 Jun 3 17:25 jdl/job3.jdl }}} Pour soumettre la collection des 3 jobs dans le sous-directory ./jdl, faire : {{{ [diarra@ipngrid01 ~/work]$ glite-wms-job-submit -a --collection jdl Connecting to the service https://grid09.lal.in2p3.fr:7443/glite_wms_wmproxy_server ====================== glite-wms-job-submit Success ====================== The job has been successfully submitted to the WMProxy Your job identifier is: https://grid02.lal.in2p3.fr:9000/6zqZkrgnQ2vYkPaeNabbiQ ========================================================================== }}} Je jobId affiché est l'identifiant de la collection (). Il faut utiliser pour pouvoir connaitre l'état individuel des jobs ainsi que les vrais jobIDs. {{{ diarra@ipngrid01 ~/work]$ glite-wms-job-status https://grid02.lal.in2p3.fr:9000/6zqZkrgnQ2vYkPaeNabbiQ ************************************************************* BOOKKEEPING INFORMATION: Status info for the Job : https://grid02.lal.in2p3.fr:9000/6zqZkrgnQ2vYkPaeNabbiQ Current Status: Running Submitted: Tue Jun 3 17:25:54 2008 CEST ************************************************************* - Nodes information for: Status info for the Job : https://grid02.lal.in2p3.fr:9000/-nUgO-prNqqBNn1JL5i-uA Current Status: Running Status Reason: Job successfully submitted to Globus Destination: ipnls2001.in2p3.fr:2119/jobmanager-pbs-ipno Submitted: Tue Jun 3 17:25:54 2008 CEST ************************************************************* Status info for the Job : https://grid02.lal.in2p3.fr:9000/0Zits9wf2vkNLmk2eVUaMg Current Status: Running Status Reason: Job successfully submitted to Globus Destination: ipnls2001.in2p3.fr:2119/jobmanager-pbs-ipno Submitted: Tue Jun 3 17:25:54 2008 CEST ************************************************************* Status info for the Job : https://grid02.lal.in2p3.fr:9000/74kheBpT3e3qV-vq7dkG1A Current Status: Running Status Reason: Job successfully submitted to Globus Destination: ipnls2001.in2p3.fr:2119/jobmanager-pbs-ipno Submitted: Tue Jun 3 17:25:54 2008 CEST ************************************************************* }}} La commande glite-wms-job-output sur la , permet d'obtenir les sorties des jobs qui se sont terminés sans erreur. Les sorties sont rangées dans un sous-directory par job. {{{ [diarra@ipngrid01 ~/work]$ glite-wms-job-output https://grid02.lal.in2p3.fr:9000/6zqZkrgnQ2vYkPaeNabbiQ Connecting to the service https://grid09.lal.in2p3.fr:7443/glite_wms_wmproxy_server ================================================================================ JOB GET OUTPUT OUTCOME Output sandbox files for the DAG/Collection : https://grid02.lal.in2p3.fr:9000/6zqZkrgnQ2vYkPaeNabbiQ have been successfully retrieved and stored in the directory: /home/diarra/JobOutput/diarra_6zqZkrgnQ2vYkPaeNabbiQ ================================================================================ }}} Dans le répertoire contenant les logs des différents jobs, le fichier `ids_nodes.map` indique quel sous-directory est utilisé pour chaque jobId. Les commandes glite-wms-job-cancel et glite-wms-job-logging-info s'appliquent également sur les collections. === DAG jobs (chainage de jobs) === Un ''DAG (directed acyclic graph) job'' représente un ensemble de jobs pour lesquels l'exécution d'un ou de plusieurs jobs depend de l'exécution de un ou plusieurs autres jobs. Un DAG job permet de chainer l'exécution d'un ensemble de jobs. Dans le graph (DAG) les jobs (ou sub-jobs) sont les noeuds (nodes) et les arcs correspondent au dependances. Les attributs JDL indispensables dans le DAG job sont : * ''nodes'' : permet de spécifier les différents nodes. Le nom du node est une chaine au choix (ex: nodeA, Calcul1, JobSimulation). * ''file'' : permet d'indiquer le nom du fichier contenant le JDL d'un node * ''dependencies'' : permet de définir les dependances entre les jobs * ''description'' : permet d'écrire directement le JDL d'un node plutôt que d'utiliser l'attribut file __Remarques__ * La ''InputSandbox'' du DAG est partagée par tous les nodes qui n'en ont pas * Les nodes qui n'ont pas besoin de InputSandbox doivent avoir dans leur .jdl {{{ InputSandbox = {}; }}} * Le .jdl du DAG job ne doit pas contenir d'attribut ''OutputSandbox''. Seul les nodes peuvent avoir cet attribut. * Un node peut accéder aux ''InputSandbox'' du DAG job ainsi qu'aux ''OutputSandbox'' des autres jobs terminés avant lui. * Pour que tous les nodes s'exectuent sur le même CE, mettre dans le .jdl. {{{ NodesCollocation = true; }}} Les dependances entre nodes (jobs) sont décrites de la façon suivantes dans le .JDL du DAG. * {nodeSimu, nodeDepou} : signifie que nodeDepou ne peut pas démarrer avant l'exécution réussie de nodeSimu. * {{nodeA, nodeB, nodeC}, nodeD} : signifie que nodeD ne peut pas démarrer avant l'exécution réussie de nodeA, nodeB et nodeC. Par contre les jobs nodeA, nodeB et nodeC s'exécuteront en parallèle car ils sont indépendants. * {{nodeA, nodeB}, {nodeB, nodeC}, {nodeC, nodeD}, ...} : décrit un pipeline de jobs. Les jobs s'exécutent dans l'ordre nodeA->nodeB->nodeC->nodeD->... * Exemple de jdl: dependencies = {{nodeA, nodeB}, {nodeA, nodeC}, {nodeA,mynode}, {{nodeB,nodeC,mynode}, nodeD}}; Ce jdl a l'effet suivant: nodeB,nodeC,mynode ne s'exécuteront qu'après l'exécution réussie de nodeA. Ensuite nodeD ne s'exécutera qu'après l'exécution réussiede nodeB,nodeC,mynode. Pour plus d'informations sur les autres attributs des DAG jobs, consulter le chapitre 'DAG ATTRIBUTES DESCRIPTION' du document https://edms.cern.ch/document/590869/1/ Illustrons tout cela par un exemple. Prenons deux nodes (jobs) nodeA et nodeB. On veut que nodeA s'exécute avant nodeB, car nodeB a besoin d'un fichier de sortie de nodeA. {{{ [diarra@ipngrid01 DAG]$ cat dag.jdl Type = "dag"; VirtualOrganisation = "vo.ipno.in2p3.fr"; MyProxyServer = "myproxy.grif.fr"; # InpuSandbox partage' par tous les nodes qui n'ont pas de InputSandbox InputSandbox = { "DAGInput.txt" }; nodes = [ nodeA = [ file = "nodeA.jdl"; ]; nodeB = [ file = "nodeB.jdl"; ]; ]; dependencies = { { nodeA, nodeB } }; }}} L'attribut ''file'' précise le fichier contenant le JDL de chaque node. Examinons les JDL des nodes. __JDL de nodeA__ {{{ diarra@ipngrid01 DAG]$ cat nodeA.jdl Executable = "nodeA.sh"; Arguments = "600 DAGInput.txt nodeAOutput.txt"; StdOutput = "std.out"; StdError = "std.err"; InputSandbox = { "nodeA.sh", "nodeAInput.txt", root.InputSandbox }; OutputSandbox = { "std.out", "std.err", "nodeAOutput.txt" }; }}} nodeA a sa propre ''InputSandbox'' mais peut inclure en plus la ''InputSandbox'' du DAG via la variable ''root.InputSandbox''. Ainsi il peut accéder ici par exemple au fichier DAGInput.txt compris dans la ''InputSandbox'' du DAG job. __JDL de nodeB__ {{{ [diarra@ipngrid01 DAG]$ cat nodeB.jdl Executable = "nodeB.sh"; Arguments = "100 nodeAOutput.txt nodeBOutput.txt"; StdOutput = "std.out"; StdError = "std.err"; InputSandbox = { "nodeB.sh", root.nodes.nodeA.description.OutputSandbox[2] }; OutputSandbox = { "std.out", "std.err", "nodeBOutput.txt" }; }}} On voit que nodeB peut accéder au fichier de sortie de nodeA via ''root.nodes.nodeA.description.OutputSandbox[2]'' qui est le 3ème fichier de la OutputSandbox du JDL (description) de nodeA du DAG (root); Dans les fichiers exécutables (''Executable''), il suffit de récupérer les arguments (''Arguments'') et de faire le traitement souhaité. La soumission d'un DAG job se fait comme pour un job normal. On obtient un qui permet de controler le dag. {{{ [diarra@ipngrid01 DAG]$ glite-wms-job-submit -a -o dag.jid dag.jdl }}} Pour obtenir le status du DAG job : {{{ [diarra@ipngrid01 DAG]$ glite-wms-job-status -i dag.jid ************************************************************* BOOKKEEPING INFORMATION: Status info for the Job : https://grid02.lal.in2p3.fr:9000/IMLwU59oEl76Iv3BsAsFJA Current Status: Done (Success) Exit code: 0 Status Reason: Job terminated successfully Destination: dagman Submitted: Wed Jun 11 15:13:30 2008 CEST ************************************************************* - Nodes information for: Status info for the Job : https://grid02.lal.in2p3.fr:9000/LwEKbpSL4lZ84gDSOc4T5Q Current Status: Done (Success) Exit code: 0 Status Reason: Job terminated successfully Destination: ipngrid12.in2p3.fr:2119/jobmanager-pbs-ipno Submitted: Wed Jun 11 15:13:30 2008 CEST ************************************************************* Status info for the Job : https://grid02.lal.in2p3.fr:9000/chFdlLNj2S1vIPAkPgv-sg Current Status: Done (Success) Exit code: 0 Status Reason: Job terminated successfully Destination: ipngrid12.in2p3.fr:2119/jobmanager-pbs-ipno Submitted: Wed Jun 11 15:13:30 2008 CEST ************************************************************* }}} Les sorties récupérées sont rangées dans des sous-directories portant les noms des nodes. {{{ diarra@ipngrid01 DAG]$ glite-wms-job-output -i dag.jid Connecting to the service https://grid09.lal.in2p3.fr:7443/glite_wms_wmproxy_ser ver ================================================================================ JOB GET OUTPUT OUTCOME Output sandbox files for the DAG/Collection : https://grid02.lal.in2p3.fr:9000/IMLwU59oEl76Iv3BsAsFJA have been successfully retrieved and stored in the directory: /home/diarra/JobOutput/diarra_IMLwU59oEl76Iv3BsAsFJA ================================================================================ }}} On retrouve les sorties: {{{ [diarra@ipngrid01 DAG]$ ls -lR /home/diarra/JobOutput/diarra_IMLwU59oEl76Iv3BsAsFJA/ /home/diarra/JobOutput/diarra_IMLwU59oEl76Iv3BsAsFJA/: total 12 -rw-r--r-- 1 diarra sii 397 Jun 11 15:25 ids_nodes.map drwxr-xr-x 2 diarra sii 4096 Jun 11 15:25 nodeA drwxr-xr-x 2 diarra sii 4096 Jun 11 15:25 nodeB /home/diarra/JobOutput/diarra_IMLwU59oEl76Iv3BsAsFJA/nodeA: total 8 -rw-r--r-- 1 diarra sii 99 Jun 11 15:25 nodeAOutput.txt -rw-r--r-- 1 diarra sii 0 Jun 11 15:25 std.err -rw-r--r-- 1 diarra sii 212 Jun 11 15:25 std.out /home/diarra/JobOutput/diarra_IMLwU59oEl76Iv3BsAsFJA/nodeB: total 8 -rw-r--r-- 1 diarra sii 23 Jun 11 15:25 nodeBOutput.txt -rw-r--r-- 1 diarra sii 96 Jun 11 15:25 std.err -rw-r--r-- 1 diarra sii 137 Jun 11 15:25 std.out }}} === Examen en temps réel des fichiers de sortie : Job Perusal === Avec le gLite WMS, on peut voir les fichiers produits par un job pendant qu'il est encore en exécution. C'est la fonctionnalité ''Job Perusal''. Cette fonctionnalité facilite le debugging de jobs longs. Par contre '''il ne faut pas l'utiliser avec des jobs courts''' car cela n'amène rien et représente une charge importante pour le WMS. Cette fonctionnalité est basé sur une copie périodique de l'output du job par le WN sur le WMS, ce qui peut être assez pénalisant avec de gros fichier d'output. Pour activer le Job Perusal pour un job, il faut ajouter les deux lignes suivantes dans le .jdl : {{{ PerusalFileEnable = true; PerusalTimeInterval = 120; }}} La valeur de `PerusalTimeInterval` est en secondes : c'est l'intervalle entre deux uploads des fichiers sur le WMS par le WN. '''Eviter de mettre des valeurs trop petites''' : utiliser un interval de plusieurs minutes. Dans l'exemple ci-dessous nous allons lancer le job perusal.jdl et récupérer des fichiers pendant que le job tourne. Nous avons choisi ici un upload toutes les 2 minutes (120 secondes) du WN vers le WMS. {{{ diarra@ipnlinux2 ~/work]$ cat perusal.jdl Executable = "perusal.sh"; Arguments = "10"; StdOutput = "std.out"; StdError = "std.err"; InputSandbox = {"perusal.sh"}; OutputSandbox = {"std.out", "std.err", "perusal.log"}; PerusalFileEnable = true; PerusalTimeInterval = 120; #Requirements = RegExp("ipnls2001.*\.fr:2119/jobmanager.*ipno$", other.GlueCEUniqueID); }}} ''Note : on peut utiliser l'attribut `PerusalFilesDestURI` dans le `.jdl` pour demander l'upload vers un serveur GridFTP plutôt que que vers le WMS.'' Après la soumission du job, on doit indiquer au WMS la liste des fichiers qu'on veut inspecter (ici std.err, std.out, perusal.log) avec la commande suivante : {{{ glite-wms-job-perusal --set -f file [-f file2...] jodID }}} Par exemple : {{{ [diarra@ipngrid01 ~/work]$ glite-wms-job-perusal --set -f std.err -f std.out -f perusal.log -i pjid Connecting to the service https://grid09.lal.in2p3.fr:7443/glite_wms_wmproxy_server ====================== glite-wms-job-perusal Success ====================== Files perusal has been successfully enabled for the job: https://grid02.lal.in2p3.fr:9000/1nX3gfh6Ba9NLtxy5FKe2g ========================================================================== }}} Pour examiner (récupérer) un fichier, par exemple le fichier perusal.log, il faut utiliser la commande : {{{ glite-wms-job-perusal --get -f file [--nodisplay] [--all] JOBID }}} L'option `--nodisplay` permet l'enregistrement du fichier plutôt que son affichage immédiat. L'option `--all` force la récupération de la totalité du fichier. Sans cette option, seule la différence depuis la dernière récupération est affichée ou sauvegardée. Par exemple : {{{ [diarra@ipngrid01 ~/work]$ glite-wms-job-perusal --get --nodisplay -f perusal.log -i pjid Connecting to the service https://grid09.lal.in2p3.fr:7443/glite_wms_wmproxy_server ====================== glite-wms-job-perusal Success ====================== The retrieved files have been successfully stored in: /home/diarra/JobOutput/diarra_1nX3gfh6Ba9NLtxy5FKe2g ========================================================================== }}} Enfin l'option `--unset` de `glite-wms-job-perusal` permet de désactiver le Job Perusal :