Skip to content

socat permitting MySQL migration

Fast idea using socat (loosed as draft since 2013-02-01) to quickly migrate a tcp and/or unix socket MySQL installation. (socat-1.7.2.0 used for the test).

If the need is temporary, this avoid a MySQL Proxy setup.

Launch that as a daemontools service (for example):

1. /service/socat-mysql-tcp/run

#!/bin/bash
bind_port=3306
bind_addr=127.0.0.1
forward_port=3304
forward_host=sql.dedicated
exec setuidgid mysql socat -d TCP4-LISTEN:${bind_port},bind=${bind_addr},fork TCP4:${forward_host}:${forward_port}

2. /service/socat-mysql-unixsocket/run

#!/bin/bash
sock=/tmp/mysql.sock
forward_port=3304
forward_host=sql.dedicated
exec setuidgid mysql socat UNIX-LISTEN:${sock},fork TCP4:${forward_host}:${forward_port}

gentoo atom regexps (ebuild name and versions)

Working on the Ansible Gentoo Portage emerge module, i’m testing some regexp for matching an atom string.

Atom is a Gentoo Portage pkgcore term.
An atom is a string representing a package name, and, optionally, it version range or version, the ebuild revision, the slot or slot and subslot.

To permit the future ansible module to handle the atom to be a parameter, i have to write some regexp for matching different atom alternative.

The first cases are simply to list, by parsing /usr/portage for avaiables packages, and atom : (here a simple bash/gawk/perl script to check the regexp)

#!/bin/bash

reg_ebuild_without_version='/^([a-z0-9\-]+)\/([a-zA-Z0-9\_\+\-]+)$/'
reg_ebuild_with_version='/^=?([a-z0-9\-]+)\/([a-zA-Z0-9\_\+\-]+)\-([^\-]+(\-r\d+)?)$/'

# this re
find /usr/portage/ -mindepth 2 -maxdepth 2 -type d | \
        gawk -F '/usr/portage/' '{ print $2; }' | \
        perl -pi -e "while(){ next if(${reg_ebuild_without_version}); print; }"

# this regexp must match a app-category/ebuild-name-X.Y.Z-rN
find /usr/portage/ -mindepth 3 -maxdepth 3 -type f -name '*.ebuild' | \
        perl -pi -e 's/\.ebuild$//g;' | \
        gawk -F '/usr/portage/' '{ print $2; }' | \
        gawk -F '/' '{ printf "%s/%s\n",$1,$3 }' | \
        perl -pi -e "while(){ next if(${reg_ebuild_with_version}); print; }"

Thoses regexp are not enougth to match any differents atom.

Some on the missing ones are already testing in the non-finished first version of the emerge module :

davixx/ansible/library/emerge (2013-01-20 version)

I hope, within 7 days, to finish the emerge_parse_atom function for handling successfully  almost 5-6 atom string cases.

ansible – sysctl module

The first version of my sysctl module for ansible have been merged to the devel tree of the mainstream ansible projet (on github) by mpdehaan.

You can now use easily this sysctl module :

  • by using git pull, if you have installed ansible by a simple git clone
  • by downloading manually sysctl in the library subdirectory of your playbooks :
cd /path/to/my/playbooks
[ -d "library" ] || mkdir -v library
wget https://raw.github.com/ansible/ansible/devel/library/sysctl -O library/sysctl
Ansible Servers Orchestration
Ansible is the easiest way to deploy, manage, and orchestrate computer systems you’ve ever seen. You can get started in minutes

After that, you can now use the sysctl module in your playbooks (extracted from the embedded documentation) :

  • Set vm.swappiness to 5 in /etc/sysctl.conf
    (first, check if /proc/sys/vm/swappiness file exist and is writteable, and after change, call sysctl -p and verify if /proc/sys/vm/swappiness file content is now 5) :
sysctl: name=vm.swappiness value=5 state=present
  • Remove kernel.panic entry from /etc/sysctl.conf
sysctl: name=kernel.panic state=absent sysctl_file=/etc/sysctl.conf
  • Set kernel.panic to 3 in /tmp/test_sysctl.conf, check if the sysctl key seems writable, but do not reload sysctl, and do not check kernel value after (not needed, because it is not the real /etc/sysctl.conf updated) :
sysctl: name=kernel.panic value=3 sysctl_file=/tmp/test_sysctl.conf check=before reload=no

gentoo fcron and system crontab

After a new install of gentoo with fcron-3 :

  • there is no /etc/crontab file ; and is it wanted (by default).
  • also, system crontab must not be setup in root crontab’s, but in systab  crontab, using the check_system_crontabs tool.
  • finally, note that by default, /etc/cron.* is not handled by fcron.

So, if you wanna to add support for /etc/cron.* you can :

  • Add this line in a new /etc/crontab (or in an existing if there is no equivalent lines already) :
%hourly * /bin/run-parts /etc/cron.hourly
%daily * * /bin/run-parts /etc/cron.daily
%weekly * * /bin/run-parts /etc/cron.weekly
%monthly * * * /bin/run-parts /etc/cron.monthly
  • Last point do nothing, just a file is updated, not any crontab.
  • Now you call the tool :
check_system_crontabs -v -i -f
  • This command will create or update dynamically the crontab of the systab user (needed by fcron for system crontab, created by the gentoo ebuild)
  • You can after check that the generated systab crontab is the concatenation of your /etc/crontab, any /etc/cron.d/ entry, and a call to the check_system_crontabs tool himself to update – if needed – the crontab – every ten minutes (in fact, for this laspoint, he use the content of /etc/fcron/fcrontab file) :
fcrontab -usystab -l

memcached – List keys in PHP

According to :

There is no official way to list avaiables keys in a memcache process.

The second link show a way, within the debug interface to list them by hundred’s blocks. You can find a modest PHP implementation here :

function getMemcacheKeys($host = '127.0.0.1', $port = 11211){

        $mem = @fsockopen($host, $port);
        if($mem === FALSE) return -1;

        // retrieve distinct slab
        $r = @fwrite($mem, 'stats items' . chr(10));
        if($r === FALSE) return -2;

        $slab = array();
        while( ($l = @fgets($mem, 1024)) !== FALSE){
                // sortie ?
                $l = trim($l);
                if($l=='END') break;

                $m = array();
                // <STAT items:22:evicted_nonzero 0>
                $r = preg_match('/^STAT\sitems\:(\d+)\:/', $l, $m);
                if($r!=1) return -3;
                $a_slab = $m[1];

                if(!array_key_exists($a_slab, $slab)) $slab[$a_slab] = array();
        }

        // recuperer les items
        reset($slab);
        foreach($slab AS $a_slab_key => &$a_slab){
                $r = @fwrite($mem, 'stats cachedump ' . $a_slab_key . ' 100' . chr(10));
                if($r === FALSE) return -4;

                while( ($l = @fgets($mem, 1024)) !== FALSE){
                        // sortie ?
                        $l = trim($l);
                        if($l=='END') break;

                        $m = array();
                        // ITEM 42 [118 b; 1354717302 s]
                        $r = preg_match('/^ITEM\s([^\s]+)\s/', $l, $m);
                        if($r!=1) return -5;
                        $a_key = $m[1];

                        $a_slab[] = $a_key;
                }
        }

        // close
        @fclose($mem);
        unset($mem);

        // transform it;
        $keys = array();
        reset($slab);
        foreach($slab AS &$a_slab){
                reset($a_slab);
                foreach($a_slab AS &$a_key) $keys[] = $a_key;
        }
        unset($slab);

        return $keys;
}

Découverte d’ansible – Orchestration de serveurs

Bonjour !

Je viens de découvrir ansible, et j’ai décidé de tenter de l’utiliser, pendant quelques mois, pour mes besoins personnels et pour certains clients.

Pourquoi ansible au lieu de Opscode Chef  ou Puppet ou CFEngine pour gérer le parc de configuration, le déploiement de logiciels, et autres ?

Sincèrement je n’ai pas de raisons majeures à ce stade, je fais les choses au feeling, je n’ai pas assez d’expérience dans les alternatives citées pour les juger.

Ansible Servers Orchestration powerfull tools
Ansible Servers Orchestration powerfull tools

Par contre, voici les premiers plus qui m’ont attirés et qui m’ont menés là : (sans pour autant sous-entendre que les alternatives ne peuvent pas, dans certains cas, en faire autant)

  • une architecture reposant sur ssh, l’installation d’aucun agent sur chacun des nodes n’est nécessaire.
  • une architecture modulaire, dans laquelle un script bash, python, php, ou encore un binaire peuvent être utilisés de manière transparente.
  • un mode had-hoc, avec lequel je peux – par exemple – déployer en une seule ligne de commande, propager un nouveau réglage pour la conntrack sur un pool de 45 serveurs.
  • un mode playbook, avec lequel je modélise des configurations idempotentes partielles et/ou totales de serveurs que je peux ensuite appliquer sans avoir la nécessité d’être un développeur, le playbook ressemble plus à une documentation rédigé au format yaml plutôt qu’un script en ruby.
  • pas d’abstraction sur le système d’exploitation des nodes et de son gestionnaire de paquets ; et cela volontairement ; pourquoi ? la pluralité des OS fait que certaines distributions Linux par exemple, ont des particularités qui sont valorisables. Reposer sur un outil qui ne retiendrait que le plus petit dénominateur de chaque distribution serait une sorte de gaspillage.

Et donc ?

Le projet ansible est récent (environ 1 an) initié – entre autres – par Michael DeHaan (un développeur ayant un historique dans les outils d’orchestration/industrialisation)

Ansible est disponible sur GitHub, je l’ai forké pour pouvoir contribuer en développant le module sysctl en un premier temps, et pour le module emerge (gestionnaire de paquet de Gentoo) en un second temps.

mod_uploadchk : workspace et devspace – part 2

Bonsoir,

Le temps passe vite, The 2nd Law est sorti, et il faudrait peut-être que j’avance sur ce module avant de pouvoir me pencher sur une autre geekerie.

Pour commencer, j’ai voulu reprendre ce projet C en essayant de le développer dans Xcode. Je suis très satisfait de cet IDE pour Objective-C je me dis qu’il me sera peut-être aussi pratique que VIM pour du code C. Nous verrons bien… (nota ; créer un Workspace simplement au lieu de créer un project)

Je n’arrive pas à mettre la main sur “The Apache Modules Book”, Google sera donc mon ami ce soir. Commençons par remonter un apache de test, je viens de mettre à jour un vieux script d’install d’httpd : http://davixx.fr/pub/20100212_setup_httpd.sh.txt avec un téléchargement sur un miroir officiel plutôt que sur mon petit serveur : http://davixx.fr/pub/20121013_setup_httpd.sh.txt :

#!/bin/bash

httpd_ver="2.2.23"
httpd_dir="httpd-${httpd_ver}"
arch_url="http://apache.crihan.fr/dist/httpd/${httpd_dir}.tar.bz2"

# ca peux servir
function echec() {
	echo "fatal error [$1]";
	exit 127
}

# port a ecouter
proposed_httpd_port="3000"
echo -n "Sur quel port TCP faut-il binder httpd [${proposed_httpd_port}] ? "
read httpd_port
[ -z "${httpd_port}" ] && httpd_port="${proposed_httpd_port}"
if netstat -lpn 2>/dev/null | grep ":${httpd_port}"; then
	echo "le port <${httpd_port}> ne semble pas libre, vous etes sur (si oui : OK) ? "
	read confirm
	[ "${confirm}" != "OK" ] && echec "cancelled"
fi

# directory
cur_dir=`pwd`
proposed_httpd_fdir="${cur_dir}/${httpd_dir}-${httpd_port}"
echo -n "Dans quel repertoire mettre tout ca [${proposed_httpd_fdir}] ? "
read httpd_fdir
[ -z "${httpd_fdir}" ] && httpd_fdir="${proposed_httpd_fdir}"

# check
tfile="/tmp/${httpd_dir}"; [ -e "${tfile}" ] && echec "<${tfile}> exist"
tfile="${httpd_fdir}"; [ -e "${tfile}" ] && echec "<${tfile}> exist"

# go
cd /tmp || echec "cd /tmp"
[ -e "${httpd_dir}.tar.bz2" ] || wget "${arch_url}"
[ -e "${httpd_dir}.tar.bz2" ] || echec "download of <${arch_url}> failed"
tar xjvf ${httpd_dir}.tar.bz2 || echec "untar"
mv "${httpd_dir}" "${httpd_fdir}" || echec "mv"
cd "${httpd_fdir}" || echec "cd <${httpd_fdir}>"
./configure --prefix="${httpd_fdir}/apache2" --enable-so || echec "configure"
make || echec "make"
make install || echec "make install"
cd "${httpd_fdir}/apache2/conf" || echec "cd"
cat httpd.conf | sed 's/#ServerName new.host.name:80/ServerName localhost/' > _httpd_conf_1
mv -vf _httpd_conf_1 httpd.conf || echec "mv"
cat httpd.conf | sed "s/^Listen 80/Listen ${httpd_port}/" > _httpd_conf_1
mv -vf _httpd_conf_1 httpd.conf || echec "mv"
cd "${httpd_fdir}"
"${httpd_fdir}/apache2/bin/apachectl" configtest || echec "configtest"
echo
echo "c'est normalement fini"
echo "\"${httpd_fdir}/apache2/bin/apachectl\" start|stop"
echo

Je constate qu’il fonctionne toujours aussi bien pour http-2.2 ; au passage je constate que httpd-2.4 est disponibles, mais les distributions telle que Gentoo ne le mettent pas encore à disposition comme stable ; je vais donc me contenter de 2.2 pour le moment…

Je reviens dans un prochain post pour une alpha du module et du script de publication sur le httpd de tests ; en attendant jettez un oeil aux URL suivantes :

NSTableView, NSArrayController and Bindings : smart resizing columns

Après recherche, impossible de trouver le moyen facile de demander à un NSTableView de redimensionner intelligemment ses NSTableColumn de manière à ce que leur taille soit la même que si l’on double-cliquait directement sur la bordure à droite de la colonne.

Etant donné que les méthodes divergent en fonction des manières d’alimenter le NSTableView (via un dataSource, ou via les Cocoa Bindings sur les NSTableColumn), je précise qu’ici il s’agit de ce dernier cas, avec un NSArrayController.

Voici donc une Category pour NSTableView, il s’agit d’une V1, il lui manque notamment les points suivants :

  • Elargir proportionnellement les colonnes avec l’espace libre
  • Appeller si nécessaire setMinWidth et/ou setMaxWidth sur les colonnes

Mais cela vous apportera un point de départ ; le header :

//  NSTableView+autoColumnSizingForBindingWithNSArrayController.h
//  extramol
//  Created by David CHANIAL on 04/08/12.

#import <Cocoa/Cocoa.h>

@interface NSTableView (autoColumnSizingForBindingWithNSArrayController)
- (void)autoColumnSizingForBindingWithNSArrayController;
@end

Et pour l’implémentation :

//  NSTableView+autoColumnSizingForBindingWithNSArrayController.m
//  extramol
//  Created by David CHANIAL on 04/08/12.

#import "NSTableView+autoColumnSizingForBindingWithNSArrayController.h"

@implementation NSTableView (autoColumnSizingForBindingWithNSArrayController)

- (void)autoColumnSizingForBindingWithNSArrayController {
    NSArray *tableColumns = [self tableColumns];

    for (NSTableColumn *column in tableColumns){
        // init
        NSDictionary *bindingInformations = [column infoForBinding:@"value"];
        if(bindingInformations == nil) continue;
        id observedObject = [bindingInformations valueForKey:NSObservedObjectKey];
        if(observedObject == nil) continue;
        // Get Array
        NSArray *items = [observedObject valueForKeyPath:[bindingInformations valueForKey:NSObservedKeyPathKey]];
        if(items == nil) continue;
        // Get DataCell
        NSCell *columnDataCell = [column dataCell];
        NSMutableDictionary *att = [[NSMutableDictionary alloc] init];
        [att setValue:[columnDataCell font] forKey:NSFontAttributeName];
        CGFloat width = 5;
        // parse items
        for(NSString *v in items){
            CGFloat w = [[NSString stringWithFormat:@"%@", v] sizeWithAttributes:att].width;
            if(w>width) width = w;
        }
        // end
        width *= 1.1;
        width += [self intercellSpacing].width;
        // width += 1;
        // DCHLog(@"%@ width: %f", att, width);
        [att release];
        [column setWidth:width];
    }
}

@end
Nick Kew : "The Apache Modules Book" (ISBN 0-13-240967-4)

mod_uploadchk : Détecter coté serveur le filetype dès le début de l’upload – part 1

Dans le cas où l’on souhaite faire pouvoir uploader de gros fichier, sans avoir un client lourd en java ou flash, il n’y a pas – à ma connaissance – de moyen de faire échouer l’upload aussitôt que le filetype est détecté ; ceci permettrait pourtant de ne pas faire attendre à l’utilisateur la fin de la longue opération pour lui dire :

Le type de fichier que vous tentez d’uploader n’est pas celui attendu

C’est l’occasion pour moi de m’aventurer dans la création d’un nouveau module apache. Je ne sais pas si j’arriverais au (meilleur) résultat voulu, mais quoi qu’il en soit ce sera toujours une expérience d’acquise que j’ai plaisir à partager avec les lecteurs de ce post.

Nick Kew : "The Apache Modules Book" (ISBN 0-13-240967-4)Pour commencer, je me suis penché une bonne heure sur l’excellent livre de Nick Kew : “The Apache Modules Book” (ISBN 0-13-240967-4)

Il à été donc clair qu’il fallait coder un “(input) filter” et non un “handler”. Une fois les premiers octets reçus, il identifiera le “Magic Number” et agira en  fonction de la configuration du module.

J’avais déjà cherché il y a plusieurs mois si un module Apache existant pourrait satisfaire plus ou moins cette problématique, en vain,  mais je suis tout de même allé rejeter un oeil sur https://modules.apache.org/

Je n’ai trouvé aucun module satisfaisant mais, comme je suis assez fainéant, je suis content d’avoir trouvé un module qui pourrait me servir de base structurelle, et de modèle pour les opérations (hooks/filters, buckets/brigade) : mod_upload, développé – par coïncidence – par Nick Kew.

Pour cette première étape, je voulais poser les bases, nous avons donc la piste de travail, un module de référence, et je clôture sur le code du futur module dans sa version la plus light possible, ainsi que le Makefile associé :

#include <httpd.h>
#include <apr_strings.h>
#include <util_filter.h>
#include <http_config.h>
#include <http_log.h>

module AP_MODULE_DECLARE_DATA uploadchk_module ;

module AP_MODULE_DECLARE_DATA uploadchk_module = {
	STANDARD20_MODULE_STUFF,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL
} ;
all: mod_uploadchk install
mod_uploadchk:
        apxs2 -n uploadchk -c mod_uploadchk.c
install:
        apxs2 -n uploadchk -i -a mod_uploadchk.la
        /etc/init.d/apache2 restart
clean:
        rm -rf .libs
        rm -f mod_uploadchk.la mod_uploadchk.lo mod_uploadchk.o mod_uploadchk.slo

La suite dans un prochain post…