Retour d’expérience sur une upgrade proxmox  4.4 => 5 qui tourne mal sur une machine munie de plusieurs interfaces réseaux.

Symptôme:

Au reboot, après mise à jour, le quorum ne démarre plus un problème cmap.
toutes les commandes pvecm renvoi l’erreur « cannot initialize CMAP », le répertoire /etc/pve semble ne plus contenir qu’une partie des fichiers, et ce, en lecture seule. bref catastrophique.

Le détail indique des défaillances multiples de telle que celle-ci:

[libqb] debug: qb_ipcc_disconnect() (ipcc.c:398:qb_ipcc_disconnect)
[quorum] crit: quorum_initialize failed: 2 (quorum.c:112:service_quorum_initialize)
[libqb] debug: qb_ipcc_disconnect() (ipcc.c:398:qb_ipcc_disconnect)
[confdb] crit: cmap_initialize failed: 2 (confdb.c:239:service_cmap_initialize)
[main] debug: dfsm_set_mode – set mode to 0 (dfsm.c:520:dfsm_set_mode)
[libqb] debug: qb_ipcc_disconnect() (ipcc.c:398:qb_ipcc_disconnect)
[dcdb] crit: cpg_initialize failed: 2 (dfsm.c:1382:dfsm_initialize)
[main] debug: dfsm_set_mode – set mode to 0 (dfsm.c:520:dfsm_set_mode)
[libqb] debug: qb_ipcc_disconnect() (ipcc.c:398:qb_ipcc_disconnect)
[status] crit: cpg_initialize failed: 2 (dfsm.c:1382:dfsm_initialize)
[main] debug: enter cfs_fuse_getattr / (pmxcfs.c:126:cfs_fuse_getattr)

 

Après avoir vainement cherché un problème de fichiers de config perdus, en fait,  il s’agissait d’un problème réseau assez sournois car pourtant tout les tests effectués (ping du nom, ssh et test multicast vers les autres proxmox) fonctionnaient sans soucis dans les deux sens.

Si, comme moi,  vous disposez de plusieurs interface réseaux, vous aurez peut-être opté pour l’idée de « dédier » l’interface vmbr0 pour l’accès à l’interface, les sauvegardes et le quorum, et fait un agrégat (bond) sur vmbr1 afin d’optimiser les performances réseaux des VM.

Pourtant, c’est en supprimant l’agrégat que tout c’est remis à fonctionner.

=> Donc =>

Une solution possible:

Si, après mise à jour, vous rencontrez ce problème, vous pouvez tenter la désactivation ou la suppression / recréation de cette seconde interface (vmbr1).

 

Ps: Après cette remise en marche, un problème de certificat est apparu, (probablement lié aux nombreuses tentatives de remise en état durant plusieurs heures) réglé par

pvecm updatecerts –force

suivi d’un reboot.

Bon courage à vous si vous êtes dans cette situation, en espérant avoir pu vous aider.

Bonjour,

Ceci n’est pas un tutoriel mais plus un retour d’expérience car je n’ai pas la prétention de connaitre tout les mécanismes en place dans l’IPv6.

Suite a quelque méli-mélo  un problème commercial avec OVH, je me suis retrouvé avec un serveur en housing chez eux, mais sans IPv4 pour mes VM.

J’ai donc profité de cette latence commerciale pour tenter le faire un point sur l’avancement de l’IPv6.

Afin de pouvoir accrocher des nom d’hote sur mon domaine, j’ai décidé d’affecter des IPv6 statiques sur mes différentes VM.

Attribution:

En IPv6, le fournisseur vous fourni un sous réseau IPv6, généralement de classe /64 et vous laisse donc les 64 autres bits a votre disposition soit 18 milliards de milliards d’adresses !

Passerelle:

Chez FREE, l’adresse de la freebox est généralement la 1ere IP de la plage  donc l’adresse 2001:xxxx:xxxx:xxxx::1
Chez OVH, selon leur documentation, les octets bas des 5 derniers nombres sont a ff cela donne donc quelque chose du genre
2001:xxxx:xxxx:xxff:ff:ff:ff:ff   c’est a dire en affichant l’adresse avec les zero non significatifs cela donne 2001:xxxx:xxxx:xxff:00ff:00ff:00ff:0ff …

=> Oups !!! OVH semble avoir oublié le but d’un masque de sous réseau => Tout ce qui est en dehors du masque est défini comme extérieur et donc à la passerelle située OBLIGATOIREMENT dans le sous réseau…
Le masque réellement fonctionnel avec une telle passerelle est donc /56

Expérimentation sous Windows:

Depuis ma machine virtuelle équipée d’un Windows 2008 Sp2, l’IPv6 se configure sans difficulté. Microsoft n’est pas regardant sur le fait que la passerelle ne se trouve pas dans le même sous réseau…
En faisant pointer les DNS IPv6 vers ceux de Google dont je le rappel les ip sont:

2001:4860:4860::8888 et
2001:4860:4860::8844

L’accès à google est immédiat. Un petit test sur www.ipv6-test.com confirme que tout vas bien.

1ère observation: Sur un poste uniquement IPv6, on n’a accès a aucun site dont le serveur n’est qu’en IPv4.
2ème observation, plus curieuse: Windows Update ne fonctionne pas… il n’est pas IPv6 ready en 2015 alors qu’ils intègrent pourtant l’IPv6 depuis 2008 dans leurs logiciels ?!

Hormis ce problème de défaut de préparation du système de mise à jour, le système s’accoutume bien de l’IPv6 statique, et fonctionne de façon stable, même en désactivant totalement l’IPv4.
La connexion au bureau distant par exemple fonctionne très bien, ainsi qu’un serveur web IIS situé sur ce poste.
En revanche les petits logiciels annexes, une très vieille version de Serv-U (version 6.4) et freeFTPd ne fonctionnent pas mais cela parait assez logique.

Expérimentation sous Ubuntu 14.04.2

L’installation de l’IPv6 statique se fait dans le fichier /etc/network/interfaces

1ère observation: La mise à jour via apt-get update && apt-get upgrade -y fonctionne nickel. Preuve que les dépôts Ubuntu ont une longueur d’avance sur leurs alter-égo de Microsoft.
2ème observation: SSH fonctionne nickel. La connexion réalisée avec Winscp et Putty depuis mon poste abouti parfaitement.
3ème observation: La suppression de la config de l’IPv4 mène a un dysfonctionnement et a plus de 2 mn d’attente a chaque redémarrage. Donc j’ai laisser un config réseau bidon pour qu’il passe outre ce problème.

Sauf qu’Ubuntu, contrairement a Microsoft, ne tolère pas cette erreur de masque… Et au bout d’un délai aléatoire se plante, perte de connectivité totale du serveur jusqu’au reboot.

L’incohérence a pour effet de lui faire perdre sa route par défaut … Donc seul les postes dans le même sous réseau que lui peuvent continuer a dialoguer avec lui… et … c’est bête pour un serveur situé dans un datacentre !

conclusions

Même les grands de l’informatique tel qu’OVH peuvent se perdre dans la complexité de l’IPv6.
Les choses avances tout doucement sur cette évolution inévitable. Il y’a plein de pièges a connaitre, les mécanismes sont beaucoup plus complexes qu’en IPv4 et on est encore loin de pouvoir faire du FULL IPv6 sous peine de ce couper d’une grande partie du monde…

A bientôt

 

Récupérer les dimensions d’un fichier PDF en PHP

Stockage de l’information de dimension

Les dimensions d’un fichier PDF sont stockées dans une unité nommé le « point pica » ou DTP .
Pour résumer, un point pica correspond à 1/72 de pouce. Pour plus d’information, lire ce lien

Conversion de la taille de point pica en millimètre

Un pouce correspond à 25,4 mm

La conversion en millimètre s’obtient donc en multipliant la taille en point pica par 25,4/72
donc, par exemple, si dans un fichier PDF on trouve une taille de 595×842

cela donnera:
595×25,4/72 = 209,90 mm
842×25,4/72 = 297,04 mm

=> Ce qui correspond a un format A4 portrait.

On observera que selon le logiciel utilisé pour la génération du fichier, on aura un variation dans la précision de cette mesure. de même, certains logiciels ajoute derrière ces mesures le format normé (A4 ou autre) correspondant et d’autres non. D’où la difficulté de l’opération.

D’autre part un fichier PDF peut comporter des pages de différentes tailles et/ou orientations.

Récupération de ces information depuis PHP

PHP peut récupérer ces informations via différents outils Linux. Certains donnent une dimension globale, bien souvent la taille de la 1ère page, d’autres au contraire sont capable de vous donner la taille page par page.
Dans presque tout les cas, il faudra filtrer le résultat pour récupérer les informations de hauteur et de largeur.

Plusieurs solutions sont possibles, j’ai choisi pdfinfo pour sa vélocité et ses fonctionnalités.

pdfinfo s’installe avec la commande

sudo apt-get install poppler-utils

ce logiciel, lancé sans parametre renvoi par défaut la taille de la 1ère page ainsi que d’autres informations dont le nombre de pages.
exemple:

pdfinfo test.pdf

nous renvoi:

Title: fichier de test
Subject:
Keywords:
Author: D.FERET
Creator: PDFCreator Version 0.9.9
Producer: GPL Ghostscript 8.70
CreationDate: Fri Sep 27 14:24:08 2013
ModDate: Fri Sep 27 14:24:08 2013
Tagged: no
Form: none
Pages: 3
Encrypted: no
Page size: 595 x 842 pts (A4)
Page rot: 0
File size: 33923 bytes Optimized: no PDF version: 1.4

Ce qui est insuffisant car on récupère que la taille de la 1ère page. Pour demander des informations plus détaillées, on spécifiera la plage de pages a analyser ( donc de 1 à -1 puisque, normalement, on ne connait pas a l’avance le nombre de pages du fichier ):

pdfinfo test.pdf -f 1 -l -1

nous renvoi:

Title: fichier de test
Subject:
Keywords:
Author: D.FERET
Creator:        PDFCreator Version 0.9.9
Producer:       GPL Ghostscript 8.70
CreationDate:   Fri Sep 27 14:24:08 2013
ModDate:        Fri Sep 27 14:24:08 2013
Tagged:         no
Form:           none
Pages:          3
Encrypted:      no
Page    1 size: 595 x 842 pts (A4)
Page    1 rot:  0
Page    2 size: 595 x 842 pts (A4)
Page    2 rot:  0
Page    3 size: 595 x 842 pts (A4)
Page    3 rot:  0
File size: 33923 bytes
Optimized: no
PDF version: 1.4

On observe que les résultats utiles sont noyés dans le texte et il va devoir les extraire grâce a des expressions régulières pour garantir le résultat.

Le script PHP

Au début du script, on lancera la commande avec la commande exec qui permet de récupérer le résultat dans un tableau $lignes:

// série de constante pour constituer plus facilement nos expressions régulières.
CONST ER_SEP = '.*?'; // Séparateur (espace et autre)
CONST ER_FLOAT = '([+-]?\\d*\\.?\\d+)(?![-+0-9\\.])';  // chiffre a virgule ou entier
CONST ER_ENTIER = '(\\d+)';  //nombre entier
CONST ER_ENTIERSIGNE = '([+-]?\\d+)'; //nombre entier avec ou sans signe + ou -

function getDimensionsPDF($nom_du_fichier_pdf){
   $commande = escapeshellcmd('pdfinfo "' . $nom_du_fichier_pdf . '" -f 1 -l -1');
   $lignes = array(); exec($commande,$lignes);

Ensuite 3 cas seront possibles:
La ligne comportant la dimension ET la taille normé
La ligne comportant la dimension SANS la taille normé
La ligne comportant l’information de rotation.

On aura donc besoin de 3 expressions régulières pour récupérer les informations. On passera en revu chaque ligne pour savoir si elle répondent à l’une des 3 expressions.

    // composition des 3 expressions régulières permettant de récupérer les lignes utiles.
    $expRegLigneAvecFormatNorme = "/^Page " . ER_SEP . ER_ENTIER . ER_SEP ."size:" . ER_SEP . ER_FLOAT . ER_SEP . ER_FLOAT . ER_SEP . "pts". ER_SEP . $Format . "$/";
    $expRegLigneSansNorme = "/^Page " . ER_SEP . ER_ENTIER . ER_SEP . "size:" . ER_SEP . ER_FLOAT . ER_SEP . ER_FLOAT . ER_SEP . "pts$/";
    $expRegLigneRotation = "/^Page " .  ER_SEP . ER_ENTIER . ER_SEP . "rot:" . ER_SEP . ER_ENTIERSIGNE . "$/";$pages = [];
    foreach ($lignes as $ligne) {

        if (preg_match($expRegLigneAvecFormatNorme, $ligne, $resultats)) { // ligne avec format normé en bout de ligne
        list(,$numeroPage,$largeur,$hauteur,$format)=$resultats;
        $pages[$numeroPage]["Largeur"] = $this->pts2mm($largeur);
        $pages[$numeroPage]["Hauteur"] = $this->pts2mm($hauteur);
        $pages[$numeroPage]["Format"] = trim($format, '()');

    } elseif (preg_match($expRegLigneSansNorme, $ligne, $resultats)) { // ligne sans format normé
        list(,$numeroPage,$largeur,$hauteur)=$resultats;
        $pages[$numeroPage]["Largeur"] = $this->pts2mm($largeur);
        $pages[$numeroPage]["Hauteur"] = $this->pts2mm($hauteur);

    } elseif (preg_match($expRegLigneRotation, $ligne, $resultats)) { // ligne contenant le numéro de page et la rotation
        list(,$numeroPage,$rotation)=$resultats;
        $pages[$numeroPage]["Rotation"] = $rotation;
    }    
 }
 return $pages;
}

function pts2mm($valeur)
{ //petite fonction qui converti un taille de pts pica en mm
    if (is_numeric($valeur)) {
        return round((float)$valeur * 25.4 / 72);
    }
    return 0;
}

Voila, j’espère que cette méthode pourra vous être utile. A bientôt.

Trouver les derniers enregistrements dans un groupement sans LAST en MySQL

logo-mysql-110x57Mysql ne comporte pas fonction last et lorsque l’on fait un groupement, on ne peut récupérer les derniers enregistrements sur la base d’un regroupement.

 

Dans un de mes développement, j’avais les coordonnées de destinataire intégrée dans une table nommée commandes. (pour éviter une table supplémentaire dans un schéma déjà complexe)

La difficulté était de récupérer la liste des destinataires avec leurs coordonnées les plus récente. Ces dernières se trouvent dans la dernière commande passée pour chaques destinataires.

Une requête SQL telle que:

select numero_client, nom,prenom,adresse,codepostal, ville from commandes group by numero_client

ne récupère pas le dernier enregistrement.Hors si le destinataire a changé de nom ou d’adresse, cela pose problème.

On peut contourner le problème par une requête en deux temps:

select numero_client, nom,prenom,adresse,codepostal, ville from commandes where id in (select max(id) from commandes group by numero_client)

La 1ere partie de la requête select max(id) from commandes group by numero_client va établir une liste des id de la dernière commande pour chaque client.Ensuite la seconde partie de la requête va sélectionner les lignes correspondantes à la liste d’id précédemment créé.

Cela permet de contourner le problème de l’absence de l’instruction last.

 

 

 

 

 

Récuperer le modèle et le numéro de série d’un ordinateur

Si par exemple lors d’une télémaintenance vous devez récupérer le numéro de série d’un ordinateur, pour faire appel au constructeur ou pour commandé une pièce détachée, il n’est pas toujours évident de demander au client de vous le dicter si vous ne l’avez pas sur la facture de vente. Il existe une façon de l’obtenir en commande msdos:

Pour le modèle:

wmic csproduct get name,vendor,identifyingNumber

Pour le numéro de série

wmic bios get serialnumber

Pour la liste des adresses mac (bien qu’on peu aussi les obtenir avec ipconfig /all)

wmic nic get macaddress,description