samedi 7 septembre 2013

Ansible: l'orchestration facile (2/2)


Cet article est la suite de l'article n°1 présentant Ansible. Celui-ci a pour but de créer notre premier playbook.

En route !

Mon premier Playbook

Objectifs


Maintenant que l'on dispose de notre structure de base, on va configurer la liste des tâches permettant d'installer Tomcat8 sur un Ubuntu 12.04 à savoir:

  1. Installer le paquet OpenJDK 7 (le paquet se nomme openjdk-7-jdk)
  2. Créer un dossier permettant le téléchargement de l'archive de tomcat8 (dans /home/vagrant/archives)
  3. Télécharger tomcat8 depuis le miroir suivant
  4. Créer le dossier /opt/apache-tomcat appartenant à l'utilisateur vagrant
  5. Décompresser notre archive
  6. Créer un lien symbolique de /opt/apache-tomcat/apache-tomcat-8.0.0-RC1 à /opt/apache-tomcat/tomcat8
  7. Modifier le fichier server.xml
  8. Redémarrer tomcat à chaque fois que le fichier catalina.properties est modifié

Résolution

Étape 1: installer un paquet

 

On va créer une tâche permettant l'installation d'un paquet sur notre Ubuntu dans le fichier roles/tomcat8/tasks/main.yml:

- name: install package openJDK 7
  apt: pkg=openjdk-7-jdk update_cache=yes
  sudo: yes

Toutes les tâches nécessitent un nom qui sera affiché lors de l'exécution d'Ansible.
La deuxième ligne précise le module a utiliser à savoir ici le module "apt", on lui passe deux paramètres pkg (qui indique le nom du paquet à installer) et update_cache (qui va déclencher un apt-get update avant l'installation). Mais il existe d'autres options.
Enfin la dernière ligne indique qu'il faut lancer cette commande via sudo.

Testons maintenant notre première tâche via la commande suivante qui va exécuter notre playbook site.yml sur l'ensemble des machines de notre fichier production:

$ ansible-playbook -i production site.yml

Et le résultat (ça peut prendre un peu de temps):
PLAY [application-server] ***************************************************** 
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [install package openJDK 7] *********************************************
changed: [127.0.0.1]
PLAY RECAP ********************************************************************
127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
Si vous avez des vaches qui s'affichent vous pouvez soit désinstaller le paquer cowsay soit exécuter la commande suivante:
export ANSIBLE_NOCOWS=1

Étape 2: créer un dossier

 

Pour créer un dossier on ajoute juste une tâche à notre fichier main.yml en utilisant le module file:
- name: create archives folder
  file: path=/home/vagrant/archives state=directory
On teste à nouveau et voilà le résultat:
PLAY [application-server] ***************************************************** 
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [install package openJDK 7] *********************************************
ok: [127.0.0.1]
TASK: [create archives folder] ************************************************
changed: [127.0.0.1]
PLAY RECAP ********************************************************************
127.0.0.1 : ok=3 changed=1 unreachable=0 failed=0
On peut voir ici qu'Ansible ne ré-installe pas le package openJDK (statut: ok) mais créé par contre bien notre dossier (statut: changed).

Pour les étapes suivantes je vais vous laisser travailler en ne vous donnant que le nom des modules à utiliser. Le fichier final main est indiqué à la fin de l'article.

Étape 3: télécharger une archive

 

Utiliser pour cela le module get_url.

Étape 4: créer un dossier

 

Voir l'étape 2 en ajoutant les options qui vont bien.

Étape 5: décompresser une archive

 

Utiliser pour cela le module command. Attention à bien utiliser l'option creates pour ne pas décompresser l'archive à chaque exécution d'Ansible.

Étape 6: créer un lien symbolique

 

Encore et toujours le module file avec les options dest et src ce coup-ci.

Étape 7: Modifier le fichier server.xml

 

Pour copier un fichier depuis notre dossier roles/tomcat8/files il suffit d'utiliser le module copy. Pour l'exemple le fichier local copié sur le serveur distant est le fichier server.xml classique auquel ont été enlevé les commentaires:

- name: Copy server.xml
  copy: dest=/opt/apache-tomcat/tomcat8/conf/server.xml owner=vagrant group=vagrant src=roles/tomcat8/files/server.xml

Étape 8: Redémarrer automatiquement Tomcat

 

L'étape précédente nous a permis de modifier facilement la configuration de nos serveurs Tomcat. Néanmoins il faut après une modification de la conf redémarrer le serveur.
Pour réaliser cela nous allons ajouter un handler, une action qui ne sera exécutée que sur notification d'une autre action. Ainsi si le fichier de conf n'est pas modifié Tomcat ne sera pas redémarré.
On ajoute une ligne à notre tâche de l'étape 7 pour notifier notre handler:

- name: Copy server.xml
  copy: dest=/opt/apache-tomcat/tomcat8/conf/server.xml owner=vagrant group=vagrant src=roles/tomcat8/files/server.xml
  notify: restart tomcat
Et on créé le fichier handler correspondant dans roles/tomcat8/handlers/main.yml:

- name: restart tomcat
  shell: /opt/apache-tomcat/tomcat8/bin/shutdown.sh && /opt/apache-tomcat/tomcat8/bin/startup.sh
Voilà normalement lors de la prochaine modification du fichier server.xml notre tomcat sera redémarré. Pour tester nous pouvons rajouter une ligne vide dans le fichier roles/tomcat8/files/server.xml et relancer ansible-playbook:

PLAY [application-server] ***************************************************** 
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [install package openJDK 7] *********************************************
ok: [127.0.0.1]
TASK: [create archives folder] ************************************************
ok: [127.0.0.1]
TASK: [Download Tomcat 8] *****************************************************
ok: [127.0.0.1]
TASK: [Create tomcat directory] ***********************************************
ok: [127.0.0.1]
TASK: [Unzip tomcat] **********************************************************
skipping: [127.0.0.1]
TASK: [Create Tomcat symlink] *************************************************
ok: [127.0.0.1]
TASK: [Copy server.xml] *******************************************************
changed: [127.0.0.1]
NOTIFIED: [restart tomcat] ****************************************************
changed: [127.0.0.1]
PLAY RECAP ********************************************************************
127.0.0.1 : ok=8 changed=2 unreachable=0 failed=0

Fichier Final

 

Aller plus loin

Il est possible de faire encore plus de chose avec Ansible comme par exemple :

Bref aller jeter un oeil à la doc qui bien qu'un peu fouillis contient l'essentiel.


Post 14/52

vendredi 6 septembre 2013

Ansible : l'orchestration facile



L'une des choses qui m'intéresse énormément ces dernières années est le déploiement automatisé et industrialisé des plateformes en particulier via Puppet. Marre des scripts shell !

Présentation

Aujourd'hui j'ai découvert un outil nommé Ansible semblable à bien des aspects à Puppet mais avec quelques différences très intéressantes:

  • Aucun agent à installer sur les machines cibles. Ca permet de se lancer plus rapidement et plus facilement, on installe ansible et c'est parti !
  • Le déploiement et le passage de commande est réalisé via ssh ce qui permet de ne pas tout le temps être en root
  • Possibilité de lancer facilement des commandes shell sur tout ou partie de notre plateforme. Du genre un ping ou un apache status chose qui n'est pas facile via Puppet
  • Ecrit en python plutôt qu'en ruby (mais ça c'est personnel :)
  • Bien plus simple à prendre en main que Puppet

Après l'outil est encore un peu jeune et manque de certaines fonctionnalités dans la version open-source comme:

  • Avoir un dashboard pour consulter le résultat de déploiements réalisés de manière régulières (via cron par exemple). Actuellement on lance ansible il effectue ses actions et affiche le résultat sur la sortie standard. Pas de console centralisée
  • Logs d'exécution. Dans le cas où quelque chose se passe mal, le résultat affiché est très léger et oblige quasiment tout le temps à se logguer sur la machine pour voir de quoi il en retourne alors qu'avoir plus de logs et récupérés sur la machine exécutant ansible serait bien plus pratique quand même !
  • Déploiement sous Windows
Ces fonctionnalités semblent disponibles dans la version enterprise à 100$/machine/an.

Premiers pas

Assez parlé il est temps de jouer un peu avec Ansible !

Installation d'Ansible

L'installation est facile et prévue pour à peu près toutes les distributions Linux et même pour Mac sur la page getting started.

Pour ma part j'ai installé ça via un PPA:

On ajoute ça à nos sources:
deb http://ppa.launchpad.net/rquillo/ansible/ubuntu precise main 

deb-src http://ppa.launchpad.net/rquillo/ansible/ubuntu precise main

Et puis:
sudo apt-get install ansible

Et c'est bon !

Premiers tests

Pour faire nos tests nous allons initier une machine virtuelle via Vagrant:
vagrant init precise64

Et on lance notre vm:
vagrant up

Une fois la machine up nous allons faire un simple test de connexion à notre VM. Tout d'abord créons un dossier ansible à côté de notre Vagrantfile afin de travailler:
mkdir ansible && cd ansible

On créé ensuite le fichier hosts qui va contenir la liste des machines de notre plateforme qui ne contient qu'une machine:
127.0.0.1 ansible_ssh_port=2222 ansible_connection=paramiko

Le paramètre "ansible_ssh_port" permet de spécifier un port différent du port 22 par défaut pour se connecter via SSH. Le port 2222 est une redirection du port 22 de notre VM qui est ouvert automatiquement par Vagrant.

Le paramètre "ansible_connection" a été nécessaire pour moi afin de contourner un bug qui avait pour conséquence que Ansible restait bloqué après la connexion.

Pour info ce type de connexion est le type par défaut à partir d'Ansible 1.3.1 (j'ai fait mes tests avec la v1.2.2).


Et ensuite on lance le module "ping" (inclus dans Ansible) sur l'ensemble des machines de notre plateforme (donc juste en local):
ansible all -i hosts -m ping -u vagrant -k

Les options utilisées:
  • all: permet de préciser à quel groupe/machine appliquer la commande ou le module
  • -i : pour préciser le fichiers hosts à utiliser (par défaut /etc/ansible/hosts)
  • -m: le nom du module à exécuter
  • -u: l'utilisateur utilisé pour la connexion
  • -k: demander le mot de passe sur l'entrée standard
Et le résultat:
localhost | success >> {

    "changed": false, 

    "ping": "pong"

}

Ça marche ! On va maintenant exécuter une commande Unix quelconque, par exemple "uptime". Cela se fait via la commande suivante:
ansible all -i hosts -m shell -a "uptime" -u vagrant -k

Et le résultat:
localhost | success | rc=0 >>

 19:26:06 up 17 min,  2 users,  load average: 0.28, 0.33, 0.32


Tout fonctionne on va maintenant créer un module afin d'organiser un peu notre travail.

Structure d'un rôle

Les modules se nomment dans Ansible des playbook et représente en gros une liste de tâches au format YAML.

D'après la page Best practices nous allons créer quelques fichiers à la racine de notre dossier ansible:
  • Un fichier nommé "production" qui va contenir la liste de nos serveurs de production en l'occurrence uniquement les lignes suivantes:
[application-server]

127.0.0.1 ansible_ssh_port=2222 ansible_connection=paramiko

Nous allons également déclarer un playbook maître qui aura pour seule fonction d'inclure les autres playbooks afin de mieux séparer les choses:
  • site.yml:
- include: appservers.yml

Et notre fichier appservers.yml contenant les différents rôles de nos serveurs d'application:

- hosts: application-server
 
  roles:
  
    - tomcat8


Et maintenant la structure standard d'un rôle:

├── appservers.yml
├── production
├── roles
│   └── tomcat8
│   ├── files
│   ├── handlers
│   ├── tasks
│   └── templates
└── site.yml


Quelques explications:

  • Sous le dossier roles, un dossier pour chaque rôle (tomcat8 par exemple)
  • Ce dossier contient des sous-dossiers:
    • tasks: le fichier principal contenant la liste des tâches associées au rôle tomcat8
    • files: des fichiers destinés à être copié en tant que tels sur les serveurs cibles
    • handlers: les handlers utilisés par nos tâches (on verra un handler en détail un peu plus tard)
    • templates: les templates permettant de générer des fichiers instanciés en fonction des variables du serveur
C'est tout pour cette fois-ci dans le prochain article on réalisera un playbook permettant d'installer Tomcat 8 sur Ubuntu 12.04 !

Edit: l'article 2 vient d'être publié !


Post 13/52

dimanche 1 septembre 2013

[Java] Parallélisme et Immutabilité (1/2)



Ces derniers temps j'ai passé pas mal d'entretiens en Java et je me suis rendu compte qu'il s'agissait toujours des même questions qui revenaient.
Voici donc une petite série sur les questions les plus classiques et comment y répondre.
Pour débuter nous allons parler de parallélisme et d'immutabilité un sujet très classique dans les entretiens.

Souvent le sujet sera introduit de la manière suivante:

Vous voulez paralléliser votre code, comment faites-vous ?

Réponse simple et efficace: en utilisant des threads. Et à partir de là ça se gâte en général !

A quoi faut-il faire attention lors de l'utilisation des Threads ?

Le code utilisé avec des Threads doit être "Thread-Safe" afin d'éviter des incohérences dans le résultat du code.
En particulier lors de l'écriture et de la lecture de valeurs il arrive bien souvent que l'on tombe sur des incohérences telles que:
  1. La valeur lue n'est pas la dernière valeur écrite en mémoire. Cela est du au fait que les threads disposent de leur propre cache et ne le synchronise pas forcément avec la mémoire centrale où est stockée la valeur.
  2. La valeur écrite par un Thread est écrasée par un autre.
Voici un exemple de code pouvant éventuellement (cela dépend beaucoup de la machine, de la JVM et de l'OS) montrer le problème 1:


Résultat: Le script ne se termine jamais car le thread ne voit pas que le champ keepRunning vient de passer à false


Et un autre pour le cas 2:


Résultat:


On voit que le thread 1 se lance et fait ses 10 boucles sans aucun problème.
A la fin de son exécution count vaut 10 ce qui est normal.

Malheureusement le thread 2 ne prend pas la suite car il a déjà démarré il y a quelques temps a récupéré la valeur de count qui valait alors 0 mais n'a pu faire son incrément qu'à la fin de l'exécution du thread 1.

Contrairement à ce qu'on pourrait croire l'opération "count++" n'est pas atomique, il s'agit d'une lecture puis d'une écriture dans le champ count.

Dans le cas présent le thread 2 a pu lire mais pas écrire la valeur dans count. Il ne le fait qu'à la toute fin de la boucle de t1. En fait il écrit sa valeur juste avant que t1 n'écrive "10" dans count.
Cela explique pourquoi t2 continue avec 11 au lieu de 2 s'il avait écrit après la fin de t1.

Dans tous les cas il n'a pu incrémenter correctement count et cela se voit sur le résultat final avec un count valant 19 au lieu de 20 si tout s'était déroulé normalement.


Comment éviter le problème de rafraîchissement de cache d'un Thread ?

Dans le cas présenté ci-dessus notre paramètre "keepRunning" est un paramètre servant à contrôler la fin d'une boucle. Typiquement dans ce cas le plus simple est d'utiliser le mot clé "synchronized".

Pour faire simple ce mot clé permet d'indiquer à la JVM que le champ concerné sera accédé par différents threads et donc de stocker cette valeur dans la mémoire centrale et non dans le cache de chacun des threads.

Le cas d'utilisation typique est de mettre à jour un flag dans un thread et de le lire dans un autre:





Ce mot clé ne permet pas de résoudre le problème n°2 car il ne rend atomique que le get et le set et pas une combinaison des deux (ce qu'est le "count++").

Il n'est pas pertinent non plus d'utiliser le mot clé volatile dans certains cas:
  • Le champ est déclaré "final" (voir la seconde partie sur l'immutabilité)
  • Le champ n'est accédé que par un seul thread
  • Le champ doit être protégé pour des accès complexes (comme dans notre exemple n°2).

Comment éviter le problème d'écrasement d'une valeur par un autre thread ?


La façon la plus simple d'éviter le problème n°2 est d'utiliser le mot clé "synchronized" qui permet de limiter l'exécution d'un bloc de code à un seul thread à la fois:





Le problème de l'utilisation du mot clé synchronized est qu'il induit un lock bloquant les autres threads ce qui est mauvais pour les performances et la scalabilité car il constitue un véritable goulet d'étranglement limitant le passage à un seul Thread à la fois.


Une autre solution est de n'échanger entre les threads que des objets immutables qui évitent les locks et permettent d'obtenir des résultats corrects.

Mais ça on le verra dans la seconde partie de l'article qui arrive bientôt ! (... :)


Post 12/52

mercredi 28 août 2013

Play Framework et les Tests Unitaires



Depuis quelques jours, je joue avec Play!, un framework web Java.
Il possède plusieurs avantages forts sympathiques je trouve:

  • Stateless
  • REST
  • Asynchrone
  • Intgérant nativement Junit
Et c'est de ce dernier point en particulier que je vais parler aujourd'hui car l'intégration n'est pas si native que cela et je suis tombé sur plusieurs bugs gênants.

play test ne fait rien


La méthode conseillée pour lancer les tests est la commande "play test" mais malheureusement avec la version 2.1.3, cette commande ne teste absolument rien. Gênant ce bug...
Pour contourner cela il est nécessaire d'ajouter dans le fichier project/Build.scala les lignes suivantes:


val appDependencies = Seq(
    // Add your project dependencies here,
    javaCore,
    javaJdbc,
    javaEbean,
    "play" %% "play-test" % play.core.PlayVersion.current % "test" exclude("com.novocode", "junit-interface"),
    "com.novocode" % "junit-interface" % "0.9" % "test"
)


Ce problème devrait être corrigée dans la 2.1.4 qui ne devrait pas tarder à sortir.

play test se bloque lors des tests IHM


Il est possible avec Play! Framework de réaliser des tests fonctionnels en testant directement une page de notre application. Pour cela on utilise un testbrowser (cf la documentation sur le sujet).

Malheureusement si l'on fait cela avec la version actuelle de Play! Framework cela va bloquer entièrement la commande "play test" qui ne sera donc plus très utile.

Cela est dû à une incompatibilité avec la version de JQuery livré avec Play! Framework d'après ce bug.
La seule façon de débloquer cela est de télécharger la version 1.8.3 de jquery et de l'ajouter dans le dossier public/javascript en remplacement de la version 1.9.0 (ne pas oublier de mettre à jour vos pages aussi).

Lancer les tests unitaires depuis Eclipse


La commande "play test" est sympathique mais il arrive très régulièrement que l'on souhaite lancer uniquement un test ou une classe de tests depuis notre Eclipse et là malheureusement cela ne marche pas comme attendu à cause de l'erreur suivante:


java.lang.IllegalStateException: Class [class play.db.ebean.Model] is enhanced and [class models.Company] is not - (you can not mix!!)



Pour corriger cela il est nécessaire de télécharger le jar d'ebean et de l'ajouter en tant que paramètre par défaut dans Eclipse. Pour cela il est nécessaire d'aller dans Preferences > Java > Installed JRE > Edit et d'ajouter la ligne suivante:


-javaagent:/path/to/ebean/ebean-2.7.3-agent.jar



Et voilà ça devrait mieux aller !


Vraiment ? Pas dans tous les cas en fait. Il peut arriver que suite à cela un test soit cassé car lors d'un select en base via Ebean qui renvoie un objet avec un champ null.
Dans mon cas il s'agissait d'un champ Text (ou @Lob pour Ebean) qui était systématiquement vide alors que l'objet inséré le contenait bien.

Pour corriger cela il faut passer le champ concerné en private et générer soit même les getter/setter au lieu de laisser Play! le faire tout seul.
Et c'est tant mieux, je n'aime pas le fait d'avoir l'ensemble de mes champs public ça casse un peu le principe de l'encapsulation.

Fichier "init-data.conf" non trouvé


Si vous avez suivi les tutoriels du site Play! Framework vous avez vu que l'on peux ajouter facilement des données aux tests ou à l'application en cours de développement en créant un fichier Yaml dans le dossier conf/ et contenant l'ensemble des éléments à créer en base.

Le problème étant que si l'on fait les tests ensuite via Junit dans Eclipse il ne va jamais trouver ce fichier et donc ne va pas précharger votre base de données...

Pour corriger cela il faut ajouter le dossier conf au classpath d'Eclipse car celui-ci n'est pas ajouté lors de la commande "play eclipse".

Pour l'ajouter il suffit de faire un click droit sur le dossier conf/ dans le projet et choisir "Build Path" > "Use as Source Folder".

Je veux le coverage de mon code !


Maintenant que l'on a des tests qui fonctionnent que ça soit via la commande play test ou dans Eclipse on aimerait bien avoir également la couverture de code que l'on teste. Nous allons utiliser jacoco pour générer notre coverage.

Pour cela il faut ajouter plusieurs éléments à notre configuration:

  • Dans le fichier project/plugins.sbt ajouter les lignes suivantes:
libraryDependencies ++= Seq(
  "org.jacoco" % "org.jacoco.core" % "0.5.9.201207300726" artifacts(Artifact("org.jacoco.core", "jar", "jar")),
  "org.jacoco" % "org.jacoco.report" % "0.5.9.201207300726" artifacts(Artifact("org.jacoco.report", "jar", "jar")))

addSbtPlugin("de.johoop" % "jacoco4sbt" % "1.2.4")
  • Dans le fichier project/Build.scala:
  • Ajouter sous les import déjà existant les lignes suivantes:
import de.johoop.jacoco4sbt._
import JacocoPlugin._
  • Ajouter sous le bloc "val appDependencies = Seq(...)" une ligne:
lazy val s = Defaults.defaultSettings ++ Seq(jacoco.settings:_*)


  • Puis modifier le dernier bloc pour qu'il ressemble à cela (attention à bien ajouter le paramètre settings = s):
val main = play.Project(appName, appVersion, appDependencies, settings = s).settings(
    
    parallelExecution     in jacoco.Config := false,    
    jacoco.reportFormats  in jacoco.Config := Seq(XMLReport("utf-8"), HTMLReport("utf-8")),    
    jacoco.excludes       in jacoco.Config := Seq("views.*", "controllers.Reverse*", "controllers.javascript.*", "controllers.ref.*", "Routes*")
  )



Et voilà la couverture peut maintenant être générée via la commande:

play jacoco:cover



L'ensemble des fichiers seront placés dans le dossier /target/scala-2.9.1/jacoco/html.


Petit exemple du look:





Post 11/52

lundi 26 août 2013

QTodoTxt: une application pour todo.txt simple, rapide et multiplateforme




Aujourd'hui j'aimerai vous parler d'un sujet qui me tient particulièrement à coeur à savoir l'organisation personnelle et en particulier "Getting things done" (GTD).


J'ai découvert ce système et lu le livre allant avec il y a 3 ans alors que je cherchais une méthode un peu plus évoluée afin de gérer mes actions et projets au mieux. Cela m'aide beaucoup afin de ne pas tout reporter au lendemain ni de conserver en tête toute la liste de choses que j'ai à faire.
Du coup cela me libère l'esprit et me permet de me concentrer sur ce que je fais à l'heure actuelle. En plus de ne rien oublier, je suis plus efficace dans ce que je fais, que du bénef !


Par contre il me manquait un outil me permettant d'appliquer cette méthode au quotidien. Mon cahier des charges était assez simple (enfin je pensais):

  • Libre
  • Fonctionnant sur Android, Linux et Windows
  • Permettant de synchroniser mes tâches entre mes différents appareils
  • Avec une interface utilisateur simple
En ce qui concerne la partie mobile et la synchro (via Dropbox) j'ai trouvé assez rapidement avec l'outil Todo.txt Touch de Gina Trapani qui est la partie mobile de todo.txt. Payant mais open-source, il fonctionne bien et est maintenu par une communauté active.
De plus l'application n'a pas une structure très complexe, uniquement 2 fichiers texte dont un optionnel:

  • todo.txt: contenant l'ensemble des tâches
  • done.txt: contenant l'ensemble des tâches terminées (optionnel)
Je me retrouvais donc avec 2 fichiers synchronisés sur mes ordinateurs mais rien pour les lire de manière un peu sympa...

Après moultes recherches où j'ai trouvé des interfaces web (un peu chiant de devoir installer un apache absolument partout), des outils pour Windows uniquement ou seulement pour Linux je suis tombé sur la perle rare: QTodoTxt.

Un outil simple, multi-plateforme codé en python + Qt, open-source et rapide. Bref il semblait idéal sauf qu'il:

  • n'était plus maintenu depuis 2011
  • avait quelques bugs gênants (pas de support de l'utf8,...)
  • manquait de quelques fonctionnalités (date de création, sauvegarde automatique, auto-archivage,...)
Heureusement le code étant opensource et ayant toujours voulu jouer un peu avec du python, je me suis dis pourquoi pas, adoptons une application !

Première fois et tout se passe bien , j'ajoute des fonctionnalités, des paquets binaires, je corrige quelques bugs et j'ai même reçu mes premiers rapports de bug d'utilisateurs externes.

C'est sympa de se dire que mon application est utile à d'autres.

Du coup après 2 versions l'application permet maintenant de gérer les URLs dans les tâches, les dates de fin, la sauvegarde automatique, l'archivage automatique et la correction des quelques bugs gênants.


Même si je ne suis pas dessus en permanence je m'en sers tous les jours et elle remplie bien son but, simple,rapide et efficace!


N'hésitez pas à la tester vous aussi !

Post: 10/52

samedi 17 août 2013

Compilation de lien n°3



Ca fait longtemps que je n'ai rien publié, mille excuses !

On est reparti pour un tour avec plein de nouvelles idées et de truc sympas à découvrir. Pour le moment on va commencer doucement avec une petite collection de liens intéressants.

  • http://colorschemedesigner.com/ : Si comme moi vous galérez toujours pour trouver des couleurs qui s'accordent bien ensemble ce site est fait pour vous. À partir d’une couleur donnée et du schéma choisi (monochrome, complémentaire, triade,...), l’application déduit les différentes teintes pouvant s’accorder entre elles. Toujours pratique !
  • Nginx vient de devenir le nouveau serveur web le plus utilisé parmi les sites du Top 1000 d'après cet article de w3techs.com. Va vraiment falloir que je teste ça !
  • Twitter: un article passionnant sur l'architecture utilisée par Twitter pour gérer 150 millions d'utilisateurs.
  • Un article donnant quelques conseils pour bien réussir un entretien (on y reviendra sur ce sujet :) et pas mal de liens utiles.
  • Dernier lien mais pas des moindres, il s'agit de RunDeck, un outil permettant d'automatiser des workflows à travers une ferme de serveurs. Puppet est super sympa mais malheureusement il n'est pas possible de demander à déployer d'abord le serveur A puis le B. RunDeck permet de faire ça et bien plus encore !
Et voilà c'est tout pour le moment !

Post: 9/52

lundi 18 mars 2013

Remplacer Google Reader en 5 minutes et gratuitement


L'annonce de la part de Google de la fermeture du service Reader au 1er juillet 2013 en a perturbé plus d'un car en 7 ans d'existence Goggle Reader s'était imposé comme la solution n°1 pour consulter ses flux RSS et Atom.


Comme tout le monde je me suis mis à chercher des alternatives à Google Reader, il en existe beaucoup (Feedly, Netvibes, NewsBlur,...) mais aucune ne me convenait. Pourtant je ne demande pas grand chose:

  1. Une interface web pas trop chargée
  2. Une appli Android
  3. Une appli Android qui fonctionne en mode offline (les joies du transport en commun)
Et c'est sur le point 3. que ça bloque, je n'ai rien de trouvé de très convaincant mis à part un produit open-source Tiny tiny RSS qui se charge de tout le travail et dispose même d'un client Android gratuit et fonctionnant en mode offline, génial !

Le seul défaut et pas des moindre pour moi est qu'il faut l'installer sur son propre serveur... Pas envie de faire de l'administration de serveur le soir chez moi j'en fais déjà assez au travail, et encore moins envie de payer pour la lecture de flux RSS (je n'ai qu'une cinquantaine de flux).


Et on va faire tout ça en 3 étapes:

  1. S'inscrire à OpenShift
  2. Installer Tiny Tiny RSS
  3. Utiliser l'application Android

Inscription à OpenShift

OpenShift est la solution de PaaS de Redhat (un peu comme Google App Engine). Le gros avantage est qu'elle dispose d'une offre gratuite pour une utilisation raisonnée et c'est de ça que l'on va profiter maintenant.
On commence d'abord par s'inscrire sur OpenShift :



On remplit les champs, on valide l'email et on arrive alors à une page demandant de créer une application. Inutile d'aller plus loin on fera tout ça automatiquement par la suite.


On passe à l'étape 2.

Installation de Tiny Tiny RSS

Installation de rhc

Pour installer notre application Tiny Tiny RSS il faut installer l'outil rhc. Voici comment faire sur Linux Ubuntu (pour les autres systèmes d'exploitation voir la page RedHat dédiée):


$ sudo apt-get install ruby-full rubygems git-core
$ sudo gem install rubygems-update
$ sudo update_rubygems
$ sudo gem install rhc
$ rhc setup


Pour la dernière commande il faudra entrer le nom d'utilisateur (l'adresse mail) et le mot de passe choisit lors de la première étape.

Création de notre application Tiny Tiny RSS

On va ensuite utiliser la commande rhc pour créer automatiquement notre application grâce au travail de who-me :


$ rhc app create <app name> php-5 postgresql-8 \
--from-code=git://github.com/who-me/ttrss-fast-deployment.git
$ rhc cartridge add cron-1.4 -a <app name>


Et voilà l'installation de Tiny Tiny RSS est terminée et on peut se connecter à notre application à l'url http://<app name>-<your namespace>.rhcloud.com :





Le couple nom d'utilisateur / mot de passe par défaut est admin / password (à changer immédiatement bien sûr...).

Configuration

Nous avons notre application de gestion des flux RSS tout propre, toute neuve mais elle fait un peu vide quand même ! Pour la remplir nous allons exporter nos données de Google Reader. Pour cela utiliser le service Google Takeout qui vous permettra de récupérer vos données sous la forme d'une archive zip.

Le fichier qui nous intéresse dans cette archive se nomme subscriptions.xml et va nous servir à intégrer dans Tiny Tiny RSS tous nos flux RSS.

Pour cela dans Tiny Tiny RSS aller dans "Actions..." > "Preferences" > "Feeds" > "OPML" et sélectionner le fichier subscriptions.xml :





Tant que l'on est dans les préférences on va également activer les API externes pour le client Android Dans l'onglet "Preferences" au paragraphe "General" changer la ligne "Enable external API" à "Yes".


Et voilà terminé pour l'installation de l'application ! On passe à la partie Android !

Utilisation de l'application Android

Sur Google Play installer l'application nommée TTRSS-Reader de Nils Braden (ne pas prendre l'autre, elle ne fonctionne que 7 jours) et l'installer.

Au niveau des préférences de l'application entrer l'url de votre serveur (http://<app name>-<your namespace>.rhcloud.com normalement), le nom d'utilisateur et le mot de passe. N'activer pas le mode "Lazy Server" j'ai eu des problèmes avec. De même ne mettez pas de quote (') dans le mot de passe cela semble poser problème.


Et voilà vous avez un client Android qui fonctionne en mode déconnecté:





Bon, je l'admet les cinq minutes c'était uniquement pour appâter le chaland mais malgré tout vous voilà avec une solution viable, gratuite et qui ne s'arrêtera pas le 1 juillet !


Amusez-vous bien !


Post 8/52

samedi 9 mars 2013

Ajout d'un syntaxe highlighter à Blogger



Blogger est plutôt sympa mais il manque un truc essentiel pour un geek, un syntaxe highlighter pour que vos extraits de code ne ressemble pas à rien !

Pour ajouter ça à Blogger c'est plutôt simple, on va utiliser pour cela un script externe fait par un Googler (on reste dans la même crêmerie...): Prettify.
Prettify est composé d'un module Javascript et d'une classe CSS permettant de colorer un grand nombre de langages et cela de manière très légère. Il est égalemment modifiable via quelques styles CSS fournis (et si ça ne vous plait toujours pas le code source est disponible).
Actuellement Prettify est utilisé sur code.google.com et stackoverflow, pas mal comme références !

Installation

L'installation se déroule en une étape et on est tranquille ensuite. Il faut aller dans la partie "Modèle" de votre blog et appuyer sur le bouton "Modifier le code HTML":







Puis repérer la balise "</body>" et insérer la ligne suivante juste avant:


<script src="https://google-code-prettify.googlecode.com/svn/loader/run_prettify.js"/>


On sauvegarde et c'est terminé !

Utilisation

Utilisation Basique

Vous pouvez ensuite poster un nouveau message bien geek et lorsque vous voudrez ajouter de la coloration syntaxique il suffira d'ajouter les balises suivantes autour du contenu à modifier (en mode "HTML" bien sûr):

<pre class="prettyprint">
<?php
    echo "Hello World!"; 
?>
</pre>

Résultat:

<?php
echo "Hello World!"; 
?>

Numero de lignes

Il est possible également d'ajouter les numéros de lignes en marge du message. Pour cela il faut ajouter "linenum" à la balise pre précédente:

<pre class="prettyprint linenums">
<?php
echo "Hello World!\n";
echo "Les numéros de ligne sont affichés toutes les 5 lignes.\n";
echo "Cela peut être modifié dans la feuille de style.\n";
?>
</pre>

Résultat:

<?php
echo "Hello World!";
echo "Les numéros de ligne sont affichés toutes les 5 lignes.\n";
echo "Cela peut être modifié dans la feuille de style.\n";
?>

Spécifier un langage particulier

Prettify fait son maximum pour détecter le langage utilisé mais on peut lui faciliter la vie en précisant le langage présent entre les balises <pre>:

<pre class="prettyprint lang-dart">
library hi;

import 'dart:html';

main() {
  query('#status').text = 'Hi, Dart';
}
</pre>

Résultat:

library hi;

import 'dart:html';

main() {
  query('#status').text = 'Hi, Dart';
}


Post 7/52

Memcached: optimisation


Cet article fait partie d'une série de trois posts sur Memcached. Il fait suite au premier article: "Memcached: principe de fonctionnement" et au deuxième article: "Memcached: Gestion de la mémoire".
Troisième et dernier article sur Memcached et on finit en beauté: comment optimiser son Memcached afin de faire toujours plus avec la même quantité de mémoire !

Optimiser l'utilisation de son Memcached

Superviser son Memcached

Avant de modifier les paramètres de son Memcached il faut d'abord pouvoir les observer afin de vérifier que ce que l'on fait améliore effectivement les choses.

Pour cela deux options faciles:

  • utiliser l'interface telnet fournie afin d'obtenir des informations sur le serveur. Les informations intéressantes sont fournies par la commande "stats" et "stats slabs"
  • utiliser un script PHP affichant de manière un peu plus sympathique l'état du Memcached. Ce script est disponible sur le blog de l'auteur.






Les informations qui nous intéressent sont le compteur d'éviction (accessible uniquement via l'interface telnet) et le nombre d'éléments par slabs (via la commande "stats slabs" ou le bouton "variables" de memcached.php):





Quelques conseils

Afin de tirer le meilleur partie de Memcached il faut vérifier que:

  1. Les dates d'expiration ont été correctement paramétrées ; rien ne sert de remplir la mémoire avec des éléments inutiles. Vérifier pour cela le pourcentage de hit sur vos get memcached si celui-ci est trop bas soit vous n'avez pas assez de mémoire pour stocker tous vos éléments soit vos durées d'expiration sont trop courtes.
  2. Les données sont réparties harmonieusement au sein des slabs: si vous avez un slab qui contient 90% des éléments il peut être intéressant de partitionner plus finement ce slab en jouant sur les paramètres -n (plage de début) et -f (facteur d'augmentation). Voir à ce sujet l'exemple ci-dessous
  3. Vérifier régulièrement la taille des objets que vous stockez dans Memcached car au fur et à mesure que votre application s'étoffe il se peut que la taille des données stockées dans Memcached augmente et que les paramètres initiaux ne soient plus adaptés.
J'ai mis en pratique récemment le conseil numéro 2: il faut savoir que sur mon projet actuel nous utilisons énormément Memcached mais que les paramètres mis en place datent de plus de 4 ans et que le projet n'a plus grand chose à voir avec ce qu'il était à l'époque.
En étudiant l'un des Memcached voici ce que j'ai pu constater:

  • De nombreuses évictions (1 par seconde en moyenne)
  • 65 000 objets max stockés dans le Memcached
  • Une distribution sur les différents slabs complètement disproportionnée:



Avec -n = 8000 et -f = 2


On voit clairement sur le graphique que le premier slab contient l'immense majorité des données. Le paramètre de taille initiale du slab a été visiblement mal choisi et il faut l'affiner.
La principale conséquence de ce choix est que l'on utilise 8 kio de mémoire pour tous les objets stockés dans Memcached alors que ceux-ci font en moyenne entre 3 et 4 kio (soit 50% de mémoire perdue à chaque fois!!) ce qui implique que l'on ne peut stocker que peu d'informations.
On voit bien ici l'importance de connaître ses données afin d'optimiser au mieux les paramètres.


Nous avons donc modifié les paramètres comme suit:

  • Diminution de la taille du premier slab de 8000 octets à 1000 octets afin de mieux découper l'espace où se trouve nos données
  • Même facteur d'accroissement
  • Même mémoire allouée






Les conséquences de cette modification:

  • Peu d'évictions (Quelques centaines par jour)
  • 125 000 éléments stockés dans Memcached (pour la même quantité de mémoire allouée !!)
  • Une distribution mieux répartie
On peut se dire au vu du graphique qu'il est encore possible de faire mieux en diminuant le facteur multiplicatif afin de décomposer encore plus le slab3 en de multiples slabs. Cette solution n'a pas été retenue car nous souhaitions garder une relative flexibilité dans la taille de nos données qui sont amenées à bouger régulièrement et donc nous focaliser sur la tranche 3 à 4 kio nous semblait trop réducteur pour les développements futurs de l'application.


C'est ainsi que se termine cette série de trois articles sur Memcached un outil fantastique pour améliorer les performances et la scalabilité de votre application.




Quelques liens intéressants:

Post 6/52

vendredi 8 mars 2013

Memcached: Gestion de la mémoire


Cet article fait partie d'une série de trois posts sur Memcached. Il fait suite au premier article: "Memcached: principe de fonctionnement"

Deuxième article sur Memcached et on passe aux choses sérieuses, la gestion de la mémoire par Memcached !


Gestion de la mémoire par Memcached

Expiration

En fonctionnement nominal la mémoire utilisée par les éléments expirés dans Memcached n'est pas réclamée activement. Ainsi même si l'élément est expiré alors sa mémoire ne sera pas libérée immédiatement.
Un cas particulier arrive quand on essaye de récupérer un élément expiré. Dans ce cas Memcached va se rendre compte que l'élément est expiré et libérer immédiatement la mémoire utilisée.

Insertion d'un élément dans le cache

Lorsque l'on ajoute un nouvel élément dans Memcached celui-ci vérifie un certain nombre de choses:

  • Étape 1: Reste-t-il de la place dans la page courante ?
  • Étape 2: Reste-t-il des pages mémoires non allouée à un slab ?
  • Étape 3: Déclenchement de l'algorithme LRU

Étape 1 : affectation simple

 

Cette étape est la plus simple et la plus classique: s'il reste de l'espace dans la page courante alors on utilise un chunk de cette page pour stocker notre élément.
Rien de bien compliqué ici !


Étape 2 : assignation d'une page

 

Nous arrivons dans cette étape s'il n'y a plus de chunk libre dans la page courante. A ce moment Memcached vérifie s'il lui reste des pages mémoire de 1 Mio non affectée au slab courant et si c'est le cas alors il assigne une plage libre au slab courant.
En faisant cela il découpe également cette page en chunk de même taille et utilise un de ces chunk pour stocker l'élément à insérer.


Attention : une fois qu'une page est assignée à un slab cette page ne peut plus être affectée à un autre slab.


Étape 3 : LRU et éviction

 

S'il n'y a plus de chunk ni de page disponibles alors Memcached va commencer à libérer de l'espace en utilisant un algorithme de type LRU (Least Recently Used). Le principe de cet algorithme est de maintenir une liste d'éléments par date d'utilisation. Ainsi un élément peu utilisé apparaîtra dès le début de cette liste. Memcached va alors parcourir les premiers éléments de la liste et libérer l'espace utilisé par un élément expiré.


La particularité de Memcached est qu'il ne maintient pas une liste globale listant l'ensemble des éléments mais une liste par slab. Ainsi l'algorithme LRU n'est pas global mais local par slab. Memcached conserve une liste d'éléments par slab:




Ainsi dans le scénario 1 l'algorithme LRU va parcourir le début de liste et supprimer l'élément 2 car il est expiré. Dans le scénario 2 au contraire il n'y a pas d'élément expiré dans les premiers éléments de la liste, Memcached va alors "évincer" le premier élément même si celui-ci n'est pas encore expiré. Cette action se nomme une eviction.


Habituellement on n'aime pas trop les évictions car elles correspondent à la suppression d'un élément encore valide dans Memcached. Néanmoins sur certains environnements où la mémoire est limitée ou la quantité d'éléments à stocker est très important il est intéressant de s'appuyer sur ce mécanisme pour conserver dans le Memcached les éléments les plus couramment utilisés et supprimer les autres.


Ce mécanisme fonctionne bien en général mais il peut arriver que malgré tout Memcached manque de mémoire et soit incapable d'en retrouver:
Supposons que l'on dispose de 3 slabs : slab1, slab2 et slab3.
Au démarrage du processus memcached tous les éléments sont insérés dans le slab1 et le slab3 et toute la mémoire allouée à Memcached est utilisée. A ce moment si l'on insère un nouvel élément dans le slab1 ou le slab3 le mécanisme de LRU va se déclencher pour libérer de la mémoire et donc stocker notre élément.






Mais imaginons que l'on souhaite insérer un élément dont la taille le destine à être stocké dans le slab2. Comme il n'est pas possible de réaffecter une page à un autre slab, nous ne pourrons jamais insérer notre nouvel élément dans Memcached et une erreur est renvoyée:




Cette exemple montre bien qu'il est primordial de bien configurer son serveur Memcached afin d'en tirer le maximum. C'est ce que nous allons voir dans la troisième et dernière partie: "Memcached: optimisation".

Posts  5/52 

mercredi 6 mars 2013

Memcached: principe de fonctionnement


Cette article est le premier d'une série de trois qui a pour but de présenter Memcached, la gestion de la mémoire et les optimisations possibles.


Présentation

Comme le dit si bien Wikipedia:
"Memcached est un système d'usage général servant à gérer la mémoire cache distribuée. Il est souvent utilisé pour augmenter la vitesse de réponse des sites web créés à partir de bases de données."


Le principe ici est que plutôt que d'aller chercher régulièrement certaines données en base il vaut mieux conserver cette donnée dans la mémoire afin de pouvoir y accéder plus rapidement. De la même façon on peut stocker ainsi le résultat de calculs couteux , des données à écrire en base (pour de l'écriture asynchrone) ou encore des pages web.


Comme indiqué précédemment Memcached est un outil de stockage des données en mémoire de type clé - valeur. La principale conséquence de cela est que si la machine s'arrête on perd l'ensemble des données stockées dans Memcached. Il ne faut donc pas stocker les données importantes uniquement à cet endroit.


Ceci étant dit, Memcached est un outil fantastique pour améliorer la vitesse d'un site pour la bonne et simple raison qu'il est beaucoup beaucoup plus rapide d'accéder à de la mémoire qu'à un disque dur. Voici quelques ordres de grandeurs de temps d'accès:

  • 100 ns (10-7 s): temps d'accès à la mémoire
  • 10 000 000 ns (10-2 s): temps d'accès à un disque dur
Et tout de suite on voit que la mémoire est 100 000 fois plus lente qu'un accès disque disque... Bingo plein de perf' !


L'idée générale de Memcached est d'offrir un outil simple mais très performant afin de profiter au maximum de la vitesse de la mémoire. Il est possible d'accéder à Memcached via la majorité des langages utilisés à l'heure actuelle.

Principe de fonctionnement

Au moment du lancement du processus memcached on lui assigne une taille maximale (via le paramètre -m). Cet espace mémoire est ensuite découpé en page d'une taille fixe de 1 Mio (par défaut). La première conséquence de ce découpage est que l'on ne peut pas stocker dans Memcached des éléments de plus de 1Mio.


Ensuite Memcached découpe ses pages de 1 Mio en éléments appelés des chunks. Un chunk est un espace mémoire de taille fixe qui va stocker la clé, la donnée associée et quelques infos destinées à Memcached. Si l'on spécifie par exemple une taille de chunk de 96 octets (paramètre -n) alors tous les éléments d'une taille (taille de la clé + taille de la donnée + métadonnée Memcached) inférieure à 96 octets occuperont un espace de 96 octets en mémoire.


Tous les éléments d'une même taille sont stockés dans une classe slab. Ainsi notre premier slab contient tous les éléments d'une taille comprise entre 1 et 96 octets.

Lors de l'insertion de la première donnée dans Memcached celui-ci vérifie d'abord à quelle classe appartient l'élément inséré puis décompose une page de 1Mio en chunks de la taille des éléments du slab.
Par exemple avec notre slab contenant des éléments de 96 octets, Memcached découpe sa page de 1 Mio en 10 922 chunks. Une fois les 10 922 chunks remplis Memcached assigne une nouvelle page de 1Mio au slab.


Dans le cas où l'élément fait plus de 96 octets Memcached détermine la taille du slab suivant en utilisant le facteur d'augmentation (paramètre -f). Par exemple avec un facteur de 2 le deuxième slab hébergera des éléments d'une taille maximale de 192 octets mais ne pourra plus héberger que 5461 chunks.


En lançant Memcached avec le paramètre -vv on obtient la taille des différents slabs ainsi que le nombre de chunks pouvant être stocké par page:


~ $ memcached -vv -f 2 -m 512
slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       192 perslab    5461
slab class   3: chunk size       384 perslab    2730
slab class   4: chunk size       768 perslab    1365
slab class   5: chunk size      1536 perslab     682
slab class   6: chunk size      3072 perslab     341
slab class   7: chunk size      6144 perslab     170
slab class   8: chunk size     12288 perslab      85
slab class   9: chunk size     24576 perslab      42
slab class  10: chunk size     49152 perslab      21
slab class  11: chunk size     98304 perslab      10
slab class  12: chunk size    196608 perslab       5
slab class  13: chunk size    393216 perslab       2
slab class  14: chunk size   1048576 perslab       1
 
On obtient donc 14 classes dont la taille varie entre 96 octets et 1 Mio et pouvant stocker entre 10 922 et 1 élément(s).


Nous avons donc notre espace de stockage mémoire qui écoute par défaut sur le port 11211. Pour insérer et lire des données il suffit d'utiliser l'un des nombreux bindings disponibles dans tous les langages, par exemple l'extension PHP Memcache:


<?php

$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");

// Insert 'data' for 10 seconds in Memcached
$memcache->set('key', 'data', false, 10) or die ("Failed to save data");

$get_result = $memcache->get('key');

var_dump($get_result);

?>
 
Comme on peut le voir on insère des données pour une durée déterminée dans Memcached (maximum 30 jours). Mais que se passe-t-il si malgré tout Memcached vient à manquer de mémoire ?


Il existe alors un ensemble de mécanisme destiné à libérer de la mémoire. C'est ce que nous allons voir dans la deuxième partie: "Memcached: gestion de la mémoire".

Posts  4/52

vendredi 25 janvier 2013

Collection de flux


Pour se tenir au courant des dernières nouveautés je trouve que les flux RSS (ou Atom) n'ont pas pris une ride surtout avec l'essor des tablettes qui permettent de les consulter de manière bien plus lisible que sur smartphone et plus pratique sur sur PC.

Voici une liste de flux que je suis régulièrement afin de me tenir au courant des différentes news:
  • Le train de 13h37: une publication chaque mardi d'articles de qualités sur le développement web. C'est frais et français, François Bayrou approuve !
  • Highscalability : le blog de référence pour tout ce qui concerne le Big Data, la scalabilité et les performances. En anglais.
  • The H: le site que je préfère pour les news générales sur l'open-source et les sorties de logiciels. Publication très fréquentes (une dizaine par jour) et en anglais.
  • Mageekblog: l'histoire d'un gars sympa qui pratique le PHP et aime ça ! C'est aussi le développeur principal d'atoum (un framework de test unitaires PHP). En français
  • OCTO : le flux de l'entreprise du même nom spécialisé dans l'Agile, le Web, le Big Data bref tous les gros noms qui font vendre en ce moment. En français.
 Malheureusement certains de ces sites ne publient pas les articles complets dans les flux RSS ce qui limite énormément leurs intérêts (qui aime devoir cliquer sur chaque article pour avoir le détail ?). Pour cela j'ai la solution : http://fulltextrssfeed.com ; c'est un site magique qui transforme un flux tronqué en un flux complet ! Génial !
Bon par contre je ne sais pas ce qui se passera quand le site fermera car le code source n'est pas disponible mais en attendant c'est bien pratique!

post 3/52

mardi 22 janvier 2013

Beamer: une présentation soignée





Quoi de plus énervant que les traitements de texte pour faire une présentation, c'est lourd, les éléments ne se mettent jamais où il faut et ça ne se lit que sur le logiciel qu'il l'a créé...
Bref rien de très sympathique !

Du coup quand j'ai eu une présentation à faire pour mon boulot je me suis dit que j'allais tester Beamer.

D'après Wikipedia:
"Beamer est une classe LATEX adaptée à la création de présentations. [...] Beamer gère un système de thèmes, qui permettent de donner à sa présentation une apparence soignée et agréable."

Trop bien, à moi la classe et le style en codant !

Je commence comme d'habitude par aller fouiller le grand Internet et là c'est un peu la douche froide, tous les thèmes sont moches...

Jusqu'à ce que je tombe sur le thème utilisé pour les présentations KDE et basé sur Oxygen:



C'est pas mal mais je trouve ça encore un peu lourd pour moi. J'aimerai supprimer et/ou modifier quelques éléments:
  1. Les boutons de navigation en bas à droite, pas très utile je trouve
  2. Le plan principal tout en haut à gauche
  3. Changer l'interligne entre les puces
  4. Inclure un pdf dans ma présentation
  5. Ne pas faire évoluer les numéros de pages pour les slides annexes

On récupère le code source du thème kde et en route !

Supprimer les boutons de navigation

 On commence par une facile, pour supprimer les boutons de navigation dans Beamer il suffit d'ajouter dans votre fichier tex la ligne suivante (en général juste après les usepackage):

\setbeamertemplate{navigation symbols}{}

Un coup de pdflatex et on peut déjà voir le résultat ! On passe au point 2:

Supprimer le plan dans l'entête

Ici il ne faudra pas modifier son fichier tex mais plutôt le thème de la présentation (donc le fichier nommé beamerthemeOxygen.sty) en supprimant la ligne suivante:

\setbeamertemplate{headline}

Toujours un coup (ou deux, ça ne fait pas de mal) et voila pour le point 2. Le point 3 est tout aussi simple.

Changer l'interligne entre les puces

Beamer en général fonctionne bien et se débrouille pour placer les différents éléments au meilleur endroit. Mais parfois on aimerait laisser un peu plus d'espace entre les différentes lignes de nos listes à puces pour camoufler un slide un peu vide (on l'a tous fait!).

Pour cela il suffit de rajouter la commande suivante après le début de la liste à puces:

  \begin{itemize}
  \itemsep1em
    \item item1
    \item item2
    \item item3
  \end{itemize}

Et voila plein de place entre les puces et un slide de plus dans la présentation !

Inclure un pdf dans une présentation Beamer

J'ai eu besoin d'inclure un pdf particulier dans ma présentation mais en utilisant uniquement "includepdf" cela abimait légèrement la mise en forme.

Du coup, truc et astuce pour ajouter un pdf à une présentation Beamer il faut ajouter une commande:
{
\setbeamercolor{background canvas}{bg=}
\includepdf{toto.pdf}
}

Et voilà plus de problème !

Ne pas inclure les annexes dans la numérotation des pages

On garde le meilleur pour la fin, la numérotation des pages qui est automatique sous Beamer peut se révéler un peu chiante quand on ne veut pas numéroter certaines pages.
Je pense en particulier aux pages annexes qu'on garde toujours tout à la fin pour répondre au petit malin qui a toujours une question tordue.

On ne peut pas laisser la numérotation se poursuive car sinon cela déprime les autres participants qui pense qu'il y a encore 32 slides avant la fin de la présentation alors qu'il n'en reste que 2 (je suis un homme prévoyant pour mes annexes :).

Pour ne pas numéroter ces pages il faut ruser un peu:

On va tout d'abord définir un compteur représentant notre dernier numéro de slide (en dehors d'un élément "frame", par exemple jsute après "\appendix"):

\appendix
\newcounter{finalframe}
\setcounter{finalframe}{\value{framenumber}}


Voilà on a un beau compteur qui se nomme finalframe et qui vaut le numéro de la dernière frame numérotable.
Quand on ajoute une nouvelle frame on assigne ensuite à cette frame la valeur de notre nouveau compteur à savoir finalframe:
\begin{frame}
  \frametitle{Liens utiles}
  \setcounter{framenumber}{\value{finalframe}}
\end{frame}

Et voilà, c'est tout pour ce soir !

Quand même, le résultat final (j'ai aussi changé l'image d'entête):




Post 2/52

Image

dimanche 20 janvier 2013

Résolution 2013



Bonne année ! (presque dans les temps)

Comme tous les ans on prend des résolutions que, comme tous les ans, on ne tiendra pas !

Pour moi on va en citer trois, qui concerne ce blog:
  1. Publier en français, d'une part car il y a déjà suffisamment de blog en anglais et d'autre part car je suis plus à l'aise avec cette langue ce qui devrait aider pour mon point 2.
  2. Publier un article par semaine, il y a 52 semaines dans l'année ça fait 52 posts (ça va être dur). Au programme, toujours la même chose du geek, du geek et encore un peu de geek ! Après tout je fais pas mal de chose et je suis même payé pour faire le geek alors autant que ça profite à d'autre !
  3. Pfiou, rien que de penser aux deux premiers je suis déjà claqué, on va s'arrêter là pour cette année. On verra l'an prochain pour la suite !

Pour le point 2 c'est déjà mal barré vu qu'on est à la troisième semaine et que ce n'est que le premier post de l'année (oui ça compte, y a pas de petit bénef' :)

A très bientôt (j'y crois !)


post 1/52

photo