Projet

Général

Profil

EnvoleEoleDB » Historique » Version 11

« Précédent - Version 11/20 (diff) - Suivant » - Version actuelle
Philippe Caseiro, 27/01/2016 15:35


Comment migrer une application Envole à EoleDB

Comprendre EoleDB

EoleDB est une re-implémentation de l'ancien système eole-sql avec quatres objectifs principaux :
  1. Avoir 1 seul fichier de configuration.
  2. Supporter nativement plusieurs types de bases de données (mysql, postgresql, sqlite, ...).
  3. Supporter nativement l'externalisation des baes de données sur d'autres serveurs.
  4. Ne plus avoir fournir des scripts python pour pouvoir générer ou mettree à jour des bases de données quand de la configuration suffit largement (cf conf/updates/config.py).

EoleDB dispose d'un fichier de configuration par défaut, /etc/eole/eole-db.conf, ce fichier
au format yaml définis le comportement par défaut de EoleDB si aucune configuration spécifique
n'est définie par l'application.

L'application dispose d'un fichier de configuration au format yaml qui surcharge le comportement
de EoleDB. Les fichiers de configurations sont dans /etc/eole/eole-db.d/**.
Les fichiers de configuration spécifiques aux applications redéfinissent le comportement de EoleDB.

Actuellement EoleDB supporte complètement MySQL, le support postgresql et sqlite sont a compléter.

Pour des raisons pratiques, EoleDB réaliste également le changement de mots de passe dans les
fichiers de configuration des applications, les mots de passes sont changées a chaque lancement
de la commande eole_db_gen, dans le cas de EOLE au minimum cette commande est lancée a chaque reconfigure.

Pour utiliser EoleDB il suffit de mettre en place les fichiers de configuration et de lancer la commande
eole_db_gen

man eole_db_gen

Si vous lancez eole_db_gen sans aucun paramètre le programme vas utiliser les paramètres par défaut,
pour diverses raisons vous pouvez avoir envie d'utiliser d'autres fichiers de configurations.

Pour ce faire vous pouvez utiliser les paramètres de la commande suivants :

  • -h, --help: Affiche le message d'aide à l'utilisation de la commande
  • -c, --config: Définir un fichier de configuration a utiliser à la place de /etc/eole/eole-db.conf
  • -d, --dbdir: Définir un répertoire qui contiens les fichiers de configuration des applications qui n'est pas /etc/eole/eole-db.d/
  • -b, --backup-dir: Définir un répertoire pour copier les sauvegardes des fichiers modifiés par EoleDB

Configurer EoleDB

Les options de configuration possibles pour /etc/eole/eole-db.conf:

  • dbcont: Définition du conteneur par défaut de la base de données en mode conteneur
  • dbhost: Définition de l'adresse du serveur de base de données par défaut
  • dbport: Définition du port d'écoute du serveur de base de données par défaut
  • dbroot: Définition du nom de l'utilisateur ayant des droits "Administrateur" sur le serveur de base de données par défaut
  • dbrootpwd: Définition du mot de passe part défaut de l'utilisateur définis par l'option dbroot
  • dbtype : Définition du type de base de données par défaut du serveur de base de données (mysql, pgsql, sqlite, ...)
  • client_hosts: Liste des noms d'hôtes ou IP depuis lesquels les utilisateurs pourrons ouvrir des sessions sur le serveur de base de données.
  • dbcliconf : Définition d'un fichier de paramètrage par défaut (utile pour mysql)

Attention :

Les options passées dans le fichier définis dans dbcliconf rendent inutiles les options dbhost, dbport, dbroot, dbrootpwd et dbtype

L'option dbrootpwd ne prend pas un mot de passe en clair, mais un fichier qui contiens le mot de passe. Comme le .reader du LDAP.

Les options de configuration possibles pour les fichiers spécifiques aux applications (/etc/eole/eole-db.d/*.yml:

  • dbhost: définition de l'adresse du serveur de base de données utilisé par l'application (surcharge la valeur par défaut défnie dans /etc/eole/eole-db.conf)
  • dbport: définition du port d'écoute du serveur de base de données utilisé par l'application (surcharge la valeur par défaut défnie dans /etc/eole/eole-db.conf)
  • dbroot: Définition du nom de l'utilisateur ayant des droits "Administrateur" sur le serveur de base de données utilisé par l'application (surcharge la valeur par défaut défnie dans /etc/eole/eole-db.conf)
  • dbrootpwd: Définition du mot de passe part défaut de l'utilisateur définis par l'option dbroot (surcharge la valeur par défaut défnie dans /etc/eole/eole-db.conf)
  • dbname: Nom de la base de données de l'application
  • dbuser: Nom de l'utilisateur utilisé par l'application pour accéder à la base définies dans dbname
  • dbpass: Mot de passe utilisé par l'application pour l'utilisateur définis dans dbuser
  • createscript: Script SQL de création de la base de données définie dans dbname
  • sqlscripts: Scripts SQL a lancer après le script de création définis dans createscript
  • updatescripts: Scripts de mise à jour lancée sur la base définie dans dbname (lancé uniquement si la base existe déjà)
  • pwd_files : Définition des fichiers à mettre à jour après le changement du mot de passe de l'utilisateur définis dans dbuser

Note sur l'option pwd_files:

L'option pwd_files prend une liste de "dictionnaires" au sens python, cette option attend donc quelque chose comme ça :

pwd_files:
    - {file: '/var/www/html/posh/includes/config.inc.php',
       container: 'web',
       pattern: 'define("__PASS","',
       end_pattern: ');',
       owner: 'root:www-data',
       mod: '660' }
    - {file: '/usr/share/envole/eoledb/posh',
       pattern: 'dbpassPOSH="',
       owner: 'root:root',
       mod: '600' }

Voici la liste des options possibles pour les "structures" (dictionnaires au sens python) possibles pour un élément de la liste pwd_files:

  • file : Chemin complet du fichier a modifier, cette option est obligatoire
  • pattern : Modèle de ligne qui contiens le mot de passe entre ''. cette option est obligatoire
  • container: Conteneur ou ce trouve le fichier a modifier (valable uniquement en mode conteneur)
  • end_pattern: caractères a ajouter après le mot de passe sur la ligne lors de la modification du fichier
  • owner: Propriétaire, au format "user:group", a définir après la modification du mot de passe
  • mod: Droits au format unix (ex: 600) a définir après la modification du mot de passe

Note sur l'option pattern:

L'option pattern permet de définir le modèle de ligne qui contiens le mot de passe, il est important de définir la totalité de ce qui précède le mot de passe dans la ligne.

Par exemple si la ligne a changer est la suivante :

password: "JeSuiSunMauvaisPassowrd" 

Il faut définir la valeur suivante pour l'option pattern:

pwd_files:
   - {file: "/monfichier.conf",
      pattern: 'password: "'

Le " est important car lorsqu'il est définis EoleDB détermine automatiquement qu'il faut qu'il ferme les " après
la mise en place du nouveau mot de passe.

Si le pattern de votre mot de passe doit être entre des ' il faut préférer le format suivant :

pattern: "password: '" 

EoleDB gère également la fermeture des '

EoleDB détecte également les ";" en fin de ligne ce qui fait que si votre ligne de mot de passe ce termine par un ";" , il ajouteras automatiquement le ";" final. Si vous avez des problèmes avec la terminaison automatique de la ligne avec le ";" ou que votre ligne ce termine par autre chose que ";" vous pouvez utiliser l'option end_pattern.

Note sur l'option end_pattern:

Cette option permet de définir les caractères a ajouter a la fin de la ligne juste après le nouveau mot de passe.

Par exemple si votre ligne de mot de passe à le format suivant :

define('DBPASS': 'JeSuisUnMauvaisPassword');

Sans l'option end_pattern EoleDB vas produire la ligne suivante:

define('DBPASS': 'Sv;434up<'

Pour que votre ligne soit correctement fermée il faut défnir end_pattern de la manière suivante:

   end_pattern: ");",

Il faut noter que le *end_pattern * ne contiens pas le ' fermant car EoleDB gère automatiquement la fermeture des " il est donc inutil de le préciser. Avec cette définition la ligne produite par EoleDB sera:

define('DBPASS': 'Sv;434up<');

Voici un exemple tiré du projet eole-posh après migration a EoleDB :

dbtype: mysql
dbname: posh
dbuser: posh
dbpass: "MOTDEPASSE" 
createscript: "/usr/share/eole/mysql/posh/gen/posh-create-1.sql" 
sqlscripts: ["/usr/share/eole/mysql/posh/updates/posh-update-1.sql"]
pwd_files:
    - {file: '/var/www/html/posh/includes/config.inc.php',
       container: 'web',
       pattern: 'define("__PASS","',
       end_pattern: ');',
       owner: 'root:www-data',
       mod: '660' }
    - {file: '/usr/share/envole/eoledb/posh',
       pattern: 'dbpassPOSH="',
       owner: 'root:root',
       mod: '600' }
    - {file: '/usr/share/eole/postservice/10-posh',
       pattern: 'POSHPASS=',
       owner: 'root:root',
       mod: '700' }
    - {file: '/var/www/html/sap/config/mysql.inc.php',
       container: 'web',
       pattern: '$dbpwd="',
       end_pattern: ';',
       owner: 'root:www-data',
       mod: '660' }

Migrer une application vers EoleDB.

Pour migrer une application vers EoleDB le principe est plutôt simple, même si le faire n'est pas si simple.
En bref si votre application répond au standard eole-skeletor il suffit de remplacer les fichiers de configuration
du répertoire sql de votre dépôt par un seul et unique fichier de configuration au format yaml avec les options
que à disposition dans EoleDB.

Oui sur le papier c'est simple, et cela peut être très très simple pour reproduire ce que vous avez aujourd'hui
dans vos dépôts il suffit de transcrire les fichiers suivants dans un seul et unique yaml :
  • conf/updates/config.py
  • conf/gen/mon_apply.py
  • conf/passwords/mon_apply.ini

Par exemple pour l'application taskfreak, voici le yaml qu'il faut mettre dans /etc/eole/eole-db.d/ pour rempalcer tous les anciens fichiers de configuration (valable pour un scribe):

dbtype: mysql
dbname: taskfreak
dbuser: taskfreak
dbpass: "Un mot de passe !!" 
createscript: "/usr/share/eole/mysql/taskfreak/gen/taskfreak-create.sql" 
pwd_files:
    - {file: '/var/www/html/taskfreak/include/config.php',
       pattern: '$dbpass="',
       owner: 'www-data:www-data',
       mod: '600'}

Pas une ligne de python un seul fichier.

La ou l'affaire deviens complexe c'est lorsqu'on a envie que notre application bénéficie de toutes les possibilités de EoleDB et surtout de la base de données externalisée.

Dans le cas de l'exemple il suffit de fournir un template simple pour générer cette configuration, voir même de la fournir en dur en l'étât.

Pour comprendre pourquoi supporter les divers modes de base de données offerts par EoleDB est complexe il faut comprendre quels sont les dits modes.

Possibilités offertes par EoleDB aux applications.

Le mode "default" !

La première et la plus simple est le mode "défault" ce mode consiste a dire, je fait confiance a la configuration globale de EoleDB et mon application est très heureuse avec ça.

Ce qui ce traduit par l'exemple de taskfreak dans la partie précédente. Dans cette configuration :

dbtype: mysql
dbname: taskfreak
dbuser: taskfreak
dbpass: "Un mot de passe !!" 
createscript: "/usr/share/eole/mysql/taskfreak/gen/taskfreak-create.sql" 
pwd_files:
    - {file: '/var/www/html/taskfreak/include/config.php',
       pattern: '$dbpass="',
       owner: 'www-data:www-data',
       mod: '600'}

L'application ne prend aucune liberté avec la configuration de EoleDB et ce repose exclusivement sur ce qui est définis par défaut dans /etc/eole/eole-db.conf.

Le mode "local" !
Le second mode est le mode dit "local" dans ce mode l'application a envie de forcer l'utilisation d'un serveur local, pour ce faire on vas devoir générer la configuration suivante :

---
dbhost: 127.0.0.1
dbtype: mysql
dbname: taskfreak
dbuser: taskfreak
dbpass: "task;Freak" 
client_hosts: ["127.0.0.1", "localhost"]
createscript: "/usr/share/eole/mysql/taskfreak/gen/taskfreak-create.sql" 
pwd_files:
    - {file: '/var/www/html/taskfreak/include/config.php',
       pattern: '$dbpass="',
       owner: 'www-data:www-data',
       mod: '600' }

On vois déjà les différences entre les deux modes. Vous remarquerez que nous ne définissons pas de dbroot ni de dbrootpwd, c'est pour une raison simple, Sur un serveur Eole, EoleDB vas utiliser le fichier de configuration par défaut fournis par ubuntu pour ce connecter a la base de données et effectué les opérations, donc ces options ne sont pas nécessaires, cependant vous pouvez les définir si EoleDB ne fonctionne pas sur un serveur Eole.

Ici l'application dit a EoleDB d'ignorer la configuration définie dans le fichier de configuration /etc/eole/eole-db.conf pour utiliser le serveur local, donc si vous avez définis un serveur externe dans la configuration par défaut la base seras créer sur le serveur local.

Nous avons donc deux cas qui demandent des configurations différentes et il reste un troisième mode, pour que l'application puisse définir son propre serveur de base de données externe et une fois de plus dire a EoleDB de ne pas appliquer la configuration par défaut.

Le mode "externe"!

Dans ce mode l'application définie complètement un serveur externe de base de données. Voici a quoi la configuration pour ce mode pour l'application taskfreak :

---
dbhost: 192.168.45.34
dbport: 3309
dbroot: adminDB
dbrootpwd: /root/.secrets-mydb
dbtype: mysql
dbname: taskfreak
dbuser: taskfreak
dbpass: "task;Freak" 
client_hosts: ["127.0.0.1", "localhost", "192.168.0.14" ]
createscript: "/usr/share/eole/mysql/taskfreak/gen/taskfreak-create.sql" 
pwd_files:
    - {file: '/var/www/html/taskfreak/include/config.php',
       pattern: '$dbpass="',
       owner: 'www-data:www-data',
       mod: '600' }

Ici on définis des nouvelles valeurs pour dbhost, dbport, dbroot, dbrootpwd, on ajoute également l'adresse IP de la carte réseaux qui communique avec le serveur de base de données dans la liste client_hosts, attention si on n'ajoute pas cette adresse IP la connexion avec l'utilisateur définis dans dbname ne sera pas fonctionnelle.

Nous avons donc trois possibilités de configuration pour EoleDB et si nous voulons offrir les trois possibilités aux utilisateurs, il n'y a qu'une seule solution créer un template pour le fichier de configuration au foramt yaml de notre application.

Il existe d'autres possibilités qui ne sont pas développées ici, par exemple permettre la création de plusieurs bases de données une une seule application, mais ces usages relèves plus de nos délires de développeurs Eole/Envole que de la réalité du besoin. Nous nous sommes concentrés sur les 3 cas qui nous semblais être les plus utiles aux utilisateurs.

Avant d'entrer dans le vif du sujet il faut malgré tout parlé d'un "quatrième" cas, le mode conteneur et oui si on souhaite que notre application soit fonctionnelle sur un module comme AmonÉcole lorsque l'utilisateur selection le mode "local" il faut adapater la configuration.

Donc pour créer ce nouveau template nous allons avoir besoin de créer de nouvelles variables.

Mise à jour du dictionnaire pour le support des 3 modes

Afin de simplifier les choses pour l'utilisateur, nous avons pris le partis de mettre toutes les variables dans une
nouvelle famille (donc nouvel onglet dans gen_connfig) en mode expert.

<family name='taskfreak' mode='expert'>
</family>

La première variable de cette famille vas servir a permettre à l'utilisateur de faire le choix du mode.
Voici la dite variable pour taskfreak:

<variable name='tf_db_mode' type='string' description='Serveur de bases de données à utiliser'/>

Cetta variable est une simple liste des trois modes, il faut donc lui ajouter une contrainte :

<check name='valid_enum' target='tf_db_mode'>
    <param>['default', 'externe', 'local']</param>
</check>

Ensuite il nous faut une variable pour stocker l'adresse du serveur de base de données en mode "externe":

<variable type='string' name='tf_dbserver' description='Adresse du serveur de base de données'/>

Puis une variable pour le port d'écoute du serveur en mode "externe" :

<variable type='number' name='tf_dbport' description="Port d'écoute du serveur de base de données"/>

Une variable pour le nom de l'utilisateur ayant des droits administrateur sur le serveur de base de données en mode externe:

<variable type='string' name='tf_dbuser' description='Utilisateur du serveur de base de données'/>

Une variable pour permettre spécifier le fichier de mot de passe pour l'utilisateur définis précédement :

<variable type='string' name='tf_dbpass' description='Fichier de mot de passe du serveur'/>

Enfin il nous faut une variable pour permettre de saisir les adresse IP qui peuvent ouvrir des sessions sur le serveur distant:

<variable type='string' name='tf_allow_hosts' description="Hôtes authorisés à utiliser la base de données" multi='true'/>

Cette dernière est une liste et donc avec l'option "multi=true"


Il est évident qu'il faut des contraintes pour régler l'affichage ou non des options dans gen_config, en effet si l'utilisateur fait le choix
"local" aucun besoin d'afficher toutes les variables dans l'interface : 

Voici les conditions pour taskfreak :

Donc pour taskfreak voici la première containte : "Pas de EoleDB, pas de taskfreak !" 
<pre>
 <constraints>
     <condition name='disabled_if_in' source='activer_eoledb'>
         <param>non</param>
         <target type='variable'>activer_taskfreak</target>
     </condition>
</pre>

La traditionnelle "activer_monapply":

<condition name='hidden_if_in' source='activer_taskfreak'>
<param>non</param>
<target type='filelist'>taskfreak</target>
<target type='servicelist'>taskfreak</target>
</condition>

Le valid_enum déjà évoqué plus haut pour la liste des choix possible, un rappel ne fait jamais de mal

     <check name='valid_enum' target='tf_db_mode'>
         <param>['default', 'externe', 'local']</param>
     </check>

Voila la partie affichage des dites nouvelles variables, donc ici nous allons cacher les variables :
  • tf_dbserver,
  • tf_dbuser,
  • tf_dbport,
  • tf_dbpass,

si le mode choisis par l'utilisateur est "local".

     <condition name='disabled_if_in' source='tf_db_mode'>
         <param>local</param>
         <target type='variable'>tf_dbserver</target>
         <target type='variable'>tf_dbuser</target>
         <target type='variable'>tf_dbport</target>
         <target type='variable'>tf_dbpass</target>
     </condition>

Même opération si le mode est "default".

     <condition name='disabled_if_in' source='tf_db_mode'>
         <param>default</param>
         <target type='variable'>tf_dbserver</target>
         <target type='variable'>tf_dbuser</target>
         <target type='variable'>tf_dbport</target>
         <target type='variable'>tf_dbpass</target>
     </condition>
 </constraints>

Voila notre dictionnaire est à jour, nous allons pouvoir passer au tempalte de la configuration EoleDB.

Création du template pour le support des 3 modes et du mode bonus (support des conteneurs).

Attention n'oubliez pas de déclarer votre nouveau template dans le dictionnaire.

Ne perdons pas plus de temps et allons dans le code du tempalte.

Nous allons avoir besoin de connaitre le mode choisis par l'utilisateur plusieurs fois dans le template
commençons donc par déclarer une variable de template nommée "dmode"

%set dmode = %%getVar('tf_db_mode','non')

Vérifions d'abord si le mode est "externe", si c'est le cas nous allons utiliser les nouvelles variables
pour définir les configurations pour dbhost, dbroot, dbrootpwd ... Si le mode est "local" nous forçons simplement
la valeur de dbhost à 127.0.0.1. Pour le mode "default" il n'y a rien à faire.


%if %%dmode "externe"
dbhost: %%tf_dbserver
dbport: %%tf_dbport
dbroot: %%tf_dbuser
dbrootpwd: %%tf_dbpass
%else if %%dmode "local"
dbhost: 127.0.0.1
%end if

Cette partie du tempalte est commune a tous les modes :

dbtype: mysql
dbname: taskfreak
dbuser: taskfreak
dbpass: "task;Freak" 

Il nous faut maintenant résoudre les problèmes d'autorisations a joindre la base. On ne vas pas demander a l'utilisateur de saisir 127.0.0.1 lorsqu'il prend le mode local alors
que nous savons bien que cette valeur est obligatoire.

Ici nous vérifions si l'utilisateur a choisis le mode "local", si oui nous forçons la valeur de client_hosts à 127.0.0.1 et localhost.
Sinon si l'utilisateur choisis "externe" et que l'utilisateur et qu'il a défini des ĥôtes spécifiques a autorisé, nous ajoutons 127.0.0.1, localhost à la liste
des hôtes qu'il a définis, si il n'a pas définis d'hôtes en mode "externe" nous définissons 127.0.0.1, localhost, et l'adresse IP de ETH0. Il n'y a rien à faire pour le mode "défaut"


if %%dmode "local"
client_hosts: ["127.0.0.1", "localhost"]
%else if %%dmode "externe"
%if %%getVar('tf_allow_hosts', 'non') != 'non'
client_hosts: ["127.0.0.1", "localhost", "
%adresse_ip_eth0" slurp
%for %%hst in %%tf_allow_hosts
, "
%hst" slurp
%end for
]
%else
client_hosts: ["127.0.0.1", "localhost", "
%adresse_ip_eth0" ]
%end if
%end if

Cette partie est également commune a tous les modes

createscript: "/usr/share/eole/mysql/taskfreak/gen/taskfreak-create.sql" 

FIXME

pwd_files:
%if %%getVar('mode_conteneur_actif','non') == 'non'
    - {file: '/var/www/html/taskfreak/include/config.php',
%else
    - {file: '%%container_path_reseau/var/www/html/taskfreak/include/config.php',
%end if
       pattern: '$dbpass="',
       owner: 'www-data:www-data',
       mod: '600' }