Table des matières
La documentation d'utilisation de astk et as_run est le document [u1.04.00]. Le présent document s'adresse aux développeurs d'as_run et à ceux qui veulent en savoir plus sur la manière dont il fonctionne, et vient compléter les documentations et commentaires présents dans toutes les fonctions du code Python.
Les chemins vers les fichiers/répertoires sont en général relatifs au répertoire d'installation ASTER_ROOT (qui vaut /aster, /opt/aster ou autre).
Lorsqu'on fait référence à un module, on indique son nom en relatif par rapport au package asrun ; par exemple dev/messages.py.
Pour citer une fonction, on note common.sysutils.is_localhost la fonction du module common/sysutils.py qui permet de savoir si une machine est la machine courante.
Les fichiers de configuration sont dans etc/codeaster. Les informations sont réparties dans :
Les commentaires présents dans les fichiers précisent le caractère obligatoire/facultatif, et les recommandations à suivre.
Il y a aussi le fichier config.txt dans chaque répertoire de version. Voir l'entête du fichier pour la description des paramètres définis. Paramètres particuliers :
- DEVEL : permet de dire qu'une version n'est pas surchargeable (C/fortran et catalogue), par exemple, quand il s'agit d'une distribution binaires et/ou sans les bibliothèques. Valeurs : no/yes (yes par défaut)
TODO: que retourne as_run --info
L'option --proxy agit, comme son nom l'indique, comme un intermédiaire pour appeler le serveur. Elle est donc appelé du côté client (par l'interface astk par exemple). C'est alors as_run client qui contacte as_run serveur (qu'il soit sur la même machine ou non).
Prenons l'exemple où un client exécute
as_run --proxy --serv filename.export
L'option --proxy exécute alors la fonction services.ProxyToServer qui elle regarde parmi les actions appelables par cet intermédiaire ; actions définies dans le dictionnaire plugins.actions.ACTIONS. Pour --serv
'serv' : { # --serv .export 'export_position' : 0, 'min_args' : 1, 'max_args' : 1, 'default_schema' : "asrun.plugins.default.serv", }
On définit le nombre d'arguments et parmi ceux-ci où on trouve le fichier export. Enfin, on définit le schéma par défaut, c'est-à-dire la fonction qui doit être utilisée pour exécuter cette action.
Ce fonctionnement permet ainsi de modifier la manière d'exécuter certaines tâches d'où le terme de plugin puisqu'il suffit d'ajouter un module exécutant une tâche et d'en indiquer le chemin d'accès (le schéma).
Note
Des tâches sont personnalisables à plusieurs niveaux :
L'appel de la fonction se fait par services.call_plugin en utilisant le schéma par défaut ou bien celui fournit en argument par l'option --schema. C'est le client qui choisit quel schéma utiliser (l'utilisateur pourrait ainsi choisir d'utiliser telle ou telle méthode).
Le client connait les schémas à utiliser pour chaque action en interrogeant le serveur par as_run --info (voir Informations sur le serveur).
Note
Un plugin peut être dans n'importe répertoire connu du PYTHONPATH. Le chemin recommandé est etc/codeaster/plugins. Le répertoire etc/codeaster est automatiquement mis (par installation.py) dans PYTHONPATH de manière à définir un schéma du type plugins.xxx.yyy, et ce répertoire est conservé lors des mises à jour.
Outre le fait de pouvoir ajouter des plugins, l'utilisation de l'option --proxy a permis de repenser les communications client/serveur et de les limiter au sens client > serveur. Une conséquence est, par exemple, que les fichiers résultats d'un calcul ne sont pas automatiquement recopiés mais sur demande (service --get_results).
[1] | Ce qui n'est sans doute pas très clair c'est que le serveur dit quel schema utiliser mais cette fonction est exécutée, et donc le code doit être disponible, côté client. |
Le fonctionnement par défaut pour chaque action est défini dans plugins/default.py. On présente ici un rapide synopsis de chaque action :
Le fonctionnement de serv où les connexions du serveur vers le client sont nécessaires, est disponible via le schéma plugins.default.serv_with_reverse_access.
Pour chaque action, on produit les objets Server (cf. Plugins Serveur) à partir de l'export fourni en argument.
[2] | Afin d'éviter les conflits de nom pour les fichiers de données et de résultats, on utilise une fonction de conversion (common.utils.unique_basename). Cette fonction est utilisée lors du relocate du profil dans plugins.default.copy_datafiles_on_server, puis lors du rappatriement des fichiers résultats dans le copyfrom de plugins.default.get_result. |
Note
Un paramètre supplémentaire est introduit dans l'export. Il s'agit de studyid. C'est une étiquette attribuée sur la machine cliente qui permet d'identifier un calcul, notamment dans la zone tampon. Le jobid est l'étiquette attribuée par le serveur lors de la soumission du calcul.
Aujourd'hui cohabitent deux moyens d'exécuter des commandes ou copier des fichiers sur des machines distantes :
A terme, les appels directs à Shell et Copy du module system.py avec des paramètres de machine distantes devraient être résorbés et remplacés par l'utilisation des nouveaux objets.
Ces serveurs utilisent une zone intermédiaire de transit pour les fichiers. C'est le paramètre proxy_dir du fichier de configuration.
Pour ajouter un nouveau protocole, on procède comme pour les actions et on le déclare dans le fichier de configuration asrun.
Sur le serveur de calcul centralisé, on veut personnaliser les paramètres lors de la soumission d'un job. Par exemple, on veut choisir la classe batch selon qu'il s'agit d'une étude standard ou paramétrique, que l'on soit en parallèle ou pas... Pour cela, on a créé un plugin aster4_calcul.py qui est placé dans etc/codeaster/plugins. Ce module définit une fonction modifier qui prend un objet calcul.AsterCalcul en argument et retourne un objet profil.AsterProfil.
Dans le fichier de configuration, on définit
schema_calcul : plugins.aster4_calcul.modifier
TODO A compléter
Cet objet représente le contenu d'un fichier export. Il est constitué de paramètres, d'arguments (de la ligne de commande de Code_Aster) et d'une collection (type EntryCollection) de fichiers/répertoires (de type ExportEntry).
Le paramètre tpsjob est le temps limite du job en minutes. Suite à la conversion, il est utilisé arrondi l'entier supérieur.
Les chemins de fichiers/répertoires (objets ExportEntry) peuvent utiliser des variables d'environnement. La fonction os.path.expandvars est appelée dans la méthode get dans la propriété path si le fichier/répertoire est sur la machine locale.
Note
Le support des variables d'environnement est limité aux objets ExportEntry. Le support restera très partiel et localisé à certaines portions du code tant que la migration vers l'objet EntryCollection ne sera pas entière.
Il existe en fait plusieurs classes représentant un calcul : AsterCalcul et AsterCalcHandler. Ces deux objets héritent un objet de base BaseCalcul.
AsterCalcul : Quand on exécute as_run --serv, on crée un objet de ce type qui permet de lancer une exécution standard en soumettant en batch ou interactif un script qui exécute lui-même as_run fichier.export. Si on utilise cet objet dans un script Python (cas de l'astout ou distribution), on peut conserver cet objet pour agir sur le calcul (méthodes get_state, wait, kill, get_diag, etc.).
À partir de cet classe, on a spécialisé deux classes pour les cas-tests (AsterCalcTestcase) et pour les études paramétriques (AsterCalcParametric) en créant une instance par test ou par variation de l'étude.
AsterCalcHandler : c'est en quelque sorte, le pendant de AsterCalcul vu du côté du client. On fait donc appel aux fonctions intermédiaires, --proxy, pour agir sur le calcul. Par exemple, là où AsterCalcul.get_state appelle la fonction Func_actu (utilisée par as_run --actu), AsterCalcHandler.get_state passe par le schema_actu (comme as_run --proxy --actu, soit par défaut plugins.default.actu).
C'est sur la base de cette classe qu'est défini AsterCalcMulti puisque le lancement multiple se place en tant que client des différents serveurs d'exécution. On crée une instance de AsterCalcMulti par serveur.
Note
Précaution à prendre quand on crée un objet calcul à partir d'un autre : le répertoire de travail étant stocké dans le profil, il faut le supprimer du calcul "esclave" (voir les méthodes change_profile). Sinon le calcul esclave utilise le même répertoire et donc le détruit avant que le calcul maître ne soit terminé.
Le coeur de la distribution est distrib.DistribTask.execute qui surveille l'exécution d'objet dérivé de AsterCalcul.
Il existe deux timeout :
La classe dérivée utilisée dans ce cas est distrib.DistribParametricTask. On exécute des objets AsterCalcParametric.
La classe dérivée utilisée dans ce cas est distrib.DistribTestTask. On exécute des objets AsterCalcParametric.
La classe dérivée utilisée dans ce cas est multiple.DistribMultipleTask. On exécute des objets AsterCalcMulti.
Une exécution multiple pouvant être une étude, un lancement de tests..., les résultats produits sont variés : fichiers de message, bases, répertoire de résultats de tests, etc. Les résultats sont donc systématiquement recopiés dans le répertoire $HOME/MULTI/nomjob_machine où nomjob est le nom de base du profil et machine la machine d'exécution. On a donc autant de répertoire de ce type que de machines d'exécution. Dans ces répertoires, on retrouve les fichiers/répertoires résultats (conflit possible si plusieurs résultats ont le même nom de base). De plus, si le paramètre multiple_result_on_client est à yes/oui, ces répertoires sont tous créés sur la machine client. Attention éventuellement au temps de transfert, espace disque.
Exemple d'un profil (syntaxe du fichier export) exécuté depuis server1 :
profil initial
P actions multiple P multiple_actions make_etude P multiple_result_on_client yes P multiple_server_list server1 server2 P mclient server1 P mode interactif F comm /opt/aster/NEW11/astest/adlv100a.comm D 1 F mail /opt/aster/NEW11/astest/adlv100a.mail D 20 F resu /tmp/adlv100a.resu R 8
profil sur``server1``
P actions make_etude P mclient server1 P nomjob adlv100a_server1 P serveur server1 P mode interactif F comm /opt/aster/NEW11/astest/adlv100a.comm D 1 F mail /opt/aster/NEW11/astest/adlv100a.mail D 20 F resu $HOME/MULTI/adlv100a_server1/adlv100a.resu R 8
profil sur server2
P actions make_etude P mclient server1 P mode batch P nomjob adlv100a_server2 P serveur server2 F comm /tmp/.../bff825ff8667cae36409ed4440d7d8e60e36ca31.adlv100a.comm D 1 F mail /tmp/.../d3f09aeaca641fa222cfce2181a29657f07d6a6d.adlv100a.mail D 20 F resu /tmp/.../dc8c57186334bce5283f586eda31e09b4efbc3f7.adlv100a.resu R 8
On voit que l'on passe en batch quand le serveur le permet (ici server2). Puisqu'on a demandé les résultats sur la machine cliente (P multiple_result_on_client yes), sur server2, ils sont produits dans un répertoire intermédiaire. C'est la machine cliente qui viendra chercher les résultats quand l'exécution sur server2 sera terminée.
Si on avait mis P multiple_result_on_client no, on aurait sur server2
F comm /tmp/.../bff825ff8667cae36409ed4440d7d8e60e36ca31.adlv100a.comm D 1 F mail /tmp/.../d3f09aeaca641fa222cfce2181a29657f07d6a6d.adlv100a.mail D 20 F resu $HOME/MULTI/adlv100a_aster4/adlv100a.resu R 8
On utilise alors le $HOME de server2.
Régulièrement, on a besoin d'exécuter des commandes shell ou de copier des fichiers, et donc de savoir si la machine en question est la machine locale ou un serveur distant. Il y a deux fonctions pour cela :
On utilise system.AsterSystem : devrait devenir un simple module.
Aujourd'hui on n'utilise pas subprocess car on a besoin de suivre l'output d'un calcul en cours d'exécution. A travailler...
Le module log_usage.py permet d'enregistrer une trace des exécutions Code_Aster demandées. L'enregistrement est déclenché dans calcul.AsterCalcul au moment du lancement effectif (méthode start) et à condition que le champ log_usage_version soit défini dans le fichier de configuration (etc/codeaster/asrun ou etc/codeaster/agla).
Cette option permet de lancer un calcul sans fichier export. Celui-ci est automatiquement généré à partir des noms de fichiers fournis en arguments. On utilise l'extension du nom de fichier pour terminer son type (le numéro d'unité logique associé est celui par défaut).
Les fichiers de données supportés sont les mêmes que ceux cherchés pour lancer un cas-test, soit (dans execution.py) : comm, mail, mmed, med, datg, mgib, msh, msup, para, ensi, repe. À ces types, on peut ajouter les fichiers se terminant par un numéro d'unité logique (exemple : filename.44).
Les types de fichiers résultats supportés sont : mess, resu, dat, rmed et les bases. Pour les bases, le nom du répertoire doit se terminer par l'extension .base ou .bhdf.
L'option --quick accepte aussi les options --surch_pyt et --surch_fort pour exécuter le calcul avec une surcharge.
TODO expliquer l'enrobage permettant d'exécuter une fonction en parallèle sur une liste de données et de consolider les résultats "sans risque". Peut-être obsolète (ou à simplifier) avec le module multiprocessing.