• Aucun résultat trouvé

Accès à la base de données par les sous-services de Nova

En ce qui concerne l’accès aux états stockés en base de données, depuis la version Grizzly d’OpenStack les sous-services de Nova ne sont pas autorisés à y accéder direc- tement. Comme le montre la figure 6.1, les sous-services de Nova passent par un autre sous-service nova-conductor, qui sert de Proxy à la base de données. Ce dernier expose ses méthodes au protocole RPC de Nova, qui en étant appelées permettront aux autres sous-services de changer les états stockés en base de données. Ce fonctionnement per- met de préserver un couplage faible entre la base de données et les implémentations des sous-services. Enfin, les méthodes de nova-conductor délèguent tout travail sur la base de données au composant nova.db.api, qui s’appuie à son tour sur l’outil de Mapping objet-relationnel (Object-relational Mapping - ORM) SQLAlchemy pour appliquer les changements sur la base de données.

6.2. Vers un support des bases de données clé/valeur dans Nova 79

6.2

Vers un support des bases de données clé/valeur dans

Nova

Le service nova-conductor étant écrit en langage Python qui intègre le paradigme de la programmation par objet, le code source des méthodes en charge la modification des états en base de données est écrit dans un style objet. Le composant nova.db.api définit des interfaces logicielles (nom de méthodes, arguments, conventions sur les types de retour, . . . ) qui doivent être suivies pour permettre à nova-conductor de manipuler une base de données. Actuellement, seule une implémentation utilisant SQLAlchemy est proposée. Un appel aux méthodes de ce composant engendre des manipulations sur la base de données relationnelle. Ces manipulations se font au moyen de l’ORM SQLAlchemy, qui expose lui aussi ses méthodes et fonctionnalités dans un style objet, leurs appels appels étant par la suite traduits en requêtes SQL. SQLAlchemy permet ainsi aux fonctions de l’implémenta- tion par défaut de nova.db.api de manipuler la base de données dans un style objet. Une étude du code de ce dernier a confirmé que le code source de l’implémentation par défaut contenait un nombre négligeable de requêtes SQL qui pouvaient être réécrites via l’ORM, et qu’ainsi ce code source était faiblement couplé avec les bases de données relationnelles. Cette absence de couplage fort permet d’envisager l’utilisation d’autres types de bases de données. Le composant nova.db.api centralisant les manipulations de la base de don- nées, c’est donc le composant à cibler pour ajouter le support d’autres types de bases de données à Nova. Pour ajouter le support des systèmes clé/valeur à Nova, il suffirait de fournir une implémentation nova.db.api qui suive les interfaces logicielles de ce dernier, tout en ciblant un système clé/valeur. Une première approche serait de repartir de ces in- terfaces logicielles et d’implémenter chacune des fonctions de façon à ce qu’elle réalise les actions spécifiées sur une base de type clé/valeur. Cette manière de procéder est la plus simple, mais exige de recoder toutes les fonctions existantes (284 fonctions), sachant que l’implémentation par défaut contient 6260 lignes de code. Cette première approche est donc fastidieuse et aboutirait en plus à une implémentation très différente de celle par défaut, qu’il faudrait faire évoluer en parallèle de cette dernière, exigeant beaucoup d’effort de maintenance de code. Avoir deux implémentations qui évoluent en parallèle n’a pas vraiment de sens, car à cause du faible couplage existant entre l’implémentation par défaut et les bases de données relationnelles, des pans entiers de cette implémentation devraient pouvoir être réutilisés.

Développer un ORM alternatif qui proposerait les mêmes interfaces logicielles que SQLAlchemy, mais manipulerait à la place des systèmes clé/valeur, permettrait de re- cycler l’implémentation par défaut. Cette approche présente de nombreux avantages, le premier étant que cela permettrait de limiter les modifications apportées au code source de Nova. Les modifications seraient limitées au clonage de l’implémentation par défaut de nova.db.api, ainsi que le remplacement des appels à SQLAlchemy par des appels à cet ORM alternatif. De cette manière, la majeure partie du développement serait fait à l’ex- térieur du code de Nova, ce qui pourrait en plus faciliter un transfert vers la communauté Nova car modifiant très peu l’implémentation par défaut. Le deuxième avantage réside dans le fait qu’en externalisant les manipulations des bases de données de type clé/valeur dans une bibliothèque ORM externe, indépendant de Nova, on permet à d’autres projets

80 Chapitre 6. Support des bases clé/valeur dans Nova de réutiliser cet ORM. Enfin, si l’ORM alternatif respecte scrupuleusement les interfaces logicielles de SQLAlchemy, alors il est raisonnable d’imaginer qu’à terme on puisse se passer de cette deuxième implémentation, car celle par défaut pourrait alors fonctionner avec les deux ORMs. Ce sont tous ces avantages qui ont fait que nous avons privilégié la conception d’un ORM alternatif qui permettrait à Nova de s’affranchir des bases de don- nées relationnelles et de leur besoin de mécanismes de synchronisation et de réplication.

6.3

Rome : un ORM pour bases clé/valeur

Au cours de ces travaux de doctorat, nous avons développé Rome, une bibliothèque ORM écrite en python qui facilite l’interfaçage entre les bases de données de type clé/valeur et les programmes écrits en Python. Rome reprend les interfaces logicielles de SQLAlchemy et en reproduit le comportement sur les bases de données clé/valeur. Ainsi, il est possible d’assurer une certaine compatibilité des composants écrits pour SQLAlchemy avec Rome, ce qui est particulièrement intéressant dans le cadre d’une adaptation de l’implémentation par défaut nova.db.api afin qu’elle puisse fonctionner avec des bases de type clé/valeur.

Les ORMs classiques traduisant les appels à leurs méthodes en opérations d’algèbre relationnelle (sous la forme de requêtes SQL), assurer le même comportement pour des bases de type clé/valeur nécessite un certain travail d’implémentation. En effet, les sys- tèmes de type clé/valeur fournissant un ensemble plus restreint d’opérations (manipula- tion d’une clé, récupération de la valeur associée à une clé, . . . ) que les bases de données relationnelles, certaines opérations d’algèbre relationnelle ne sont pas nativement dispo- nibles, telles que les jointures et les transactions. Afin de garantir une compatibilité entre SQLAlchemyet Rome, et pouvoir ainsi réutiliser au maximum l’implémentation par défaut de nova.db.api, Rome doit être en mesure de proposer ces opérations manquantes. Celles- ci s’appuieront sur des mécanismes qui les émuleront au-dessus de systèmes clé/valeur, en les recodant ou en utilisant des alternatives plus adaptées à un contexte fortement dis- tribué.

6.3.1

Interfaces logicielles inspirées par SQLAlchemy

SQLAlchemy contient de nombreuses classes d’objets python permettant de manipuler une base de données grâce à du code écrit dans un style objet. Chacun des aspects que l’on retrouve dans les opérations des bases de données relationnelles, telles que la créa- tion de tables, la sélection et la modification des données contenues dans les tables, se fait en appelant des méthodes exposées dans un style objet par SQLAlchemy. Vouloir réim- plémenter dans Rome chacune des classes d’objets présentes dans SQLAlchemy exigerait un gros travail d’implémentation, il apparaît plus intéressant de n’implémenter que celles qui seraient nécessaires. Une exploration du code source de l’implémentation par défaut de nova.db.api a fait apparaître que seule la classe Query de SQLAlchemy était utilisée dans cette première. Ainsi, à chaque manipulation de la base de données, une instance de la classe Query est instanciée, exposant des méthodes pour ajouter, sélectionner et mettre à jour les données de la base de données. En sus de la classe Query, les autres classes utilisées par nova.db.api représentent presque exclusivement la symbolique des

6.3. Rome : unORM pour bases clé/valeur 81 requêtes SQL, c’est-à-dire les équivalents des opérateurs (select, and, or, . . . ) et des fonc- tions (count, min, max, . . . ). L’implémentation par défaut de nova.db.api ne manipulant que les classes évoquées précédemment, la stratégie optimale d’implémentation de Rome serait de limiter celle-ci à la fourniture d’une classe équivalente à la classe Query de SQ- LAlchemy, qui appliquerait les mêmes opérations, mais cette fois sur du stockage de type clé/valeur.