MindYourNeighbors

Posted on mar. 28 février 2017 in admin sys

J’ai écrit, packagé et finis de tester MindYourNeighbors, un programme qui permet de déclencher des scripts en fonction de son voisinage réseau.

Pourquoi ?

Il y a quelques années de ça, j’utilisais transmission sur une machine chez moi, qui tournait en permanence. Transmission possède un mode “lent” qui permet d’économiser les ressources du réseau quand il est activé, et via un script et deux cron, je m’arrangeais pour que transmission soit lent le soir quand il y avait du monde à la maison, et normal le reste du temps. Pour différentes raisons, il est devenu de plus en plus malaisé de prévoir les périodes creuses où transmission pourrait être en mode normal et il finissait par être en mode lent la plupart du temps.

Et donc, pourquoi ?

Donc, plutôt que d’utiliser cron, j’ai écrit un petit programme qui regarde la table des neighbors connus du kernel et décide si il peut, ou non, sortir transmission de son mode lent. Puis j’ai simplement ouvert le principe à l’exécution de n’importe quel exécutable selon une configuration.

Après l’avoir laissé tourné dans une version assez peu présentable pendant plutôt longtemps sur mon serveur, j’ai finis par nettoyer un peu tout ça, rajouter des tests, en faire une archive sur pypi et intégrer tout ça joliement sur github.

Comment ?

Le principe de fonctionnement est assez trivial, le script lance la commande ip neigh show et ligne par ligne analyse la sortie. Si une ligne a le status REACHABLE ou PERMANENT elle est considéré comme un voisin et elle passe ensuite au travers des filtres qui pourrait l’exclure ou l’inclure (sachant que l’exclusion prime).

Les filtres sont définit dans un fichier de configuration dont toutes les sections héritent de la section par défaut. Voici une version commenté de mon fichier de configuration :

[DEFAULT]
threshold = 4
# par défaut, seul mon_ordi sera considéré
filter_on_machines = mon_ordi
# on peut aussi faire des filtres plus large
# filter_on_regex = .*192\.168\.0\..*  # filtrera sur toutes les adresses IPv4 de classes B

# cette section sert juste à renseigner les machines par leurs
# adresses mac si c'est le mode de filtrage que vous choisissez
[known_machines]
mon_ordi = <mac>
mon_tel = <mac>

[transmission]
# activer le mode lent quand il y a des voisins
command_neighbor = /my/scripts/transmission-turtle true
# le désactiver quand il n'y en a pas
command_no_neighbor = /my/scripts/transmission-turtle false
# capturer la sortie sur une erreur
error_on_stderr = true

[bitcoind]
# Vous pouvez désactiver une section entière sans avoir à l'effacer de la conf
enabled = false
command_neighbor = killall bitcoind
command_no_neighbor = /opt/bitcoind -server -daemon

# pour les deux sections ci-dessus, les filtres sont hérités de la section par défaut

[wake_computer]
# mais ici on surcharge la valeur par défaut pour ne filtrer que sur mon_tel
filter_on_machines = mon_tel
# pareil, on veut que un réveil n'attendent pas 4 rotation alors on descends le seuil
threshold = 2
# on restreint les horraires d'exécution avec une syntaxe similaire à cron
cron = * 18-23 * * 1-5
command_neighbor = wake my machine

Un script executable à la main myn exécuter avec les options --output et --verbose permet de facilement debugger sont fichier de configuration en comparant les correspondance obtenue avec celle désirée.

# myn -o -v
MindYourNeighbors: INFO - MindYourNeighbors initialized
MindYourNeighbors: DEBUG - 'transmission' - processing section
MindYourNeighbors: DEBUG - EXCLUDED - <mac> - MACHINE: une_machine
MindYourNeighbors: DEBUG - MATCH - <mac> - MACHINE: mon_ordi
MindYourNeighbors: DEBUG - NO_MATCH - <mac> - MACHINE: mon_tel
MindYourNeighbors: DEBUG - cache/transmission/neighbor 2 => 2
MindYourNeighbors: INFO - 'transmission' - cache state: {'results': ['neighbor', 'no_neighbor', 'no_neighbor', 'neighbor'], 'last_command': '/home/jaes/bin/transmission-turtle false'}
MindYourNeighbors: INFO - 'transmission' - cache count hasn't reached threshold yet (2/4)
MindYourNeighbors: DEBUG - section <Section: bitcoind> not enabled
MindYourNeighbors: DEBUG - section <Section: wake_if> disabled for now

SystemD

Il est possible de faire que systemd se charge de la dæmonisation de MindYourNeighbors. Pour ce faire il faut placer ce fichier dans /etc/systemd/system/ et d’exécuter systemctl daemon-reload et service mind-your-neighbors start.

Malheureusement je n’ai pasa réussi à trouver comment packager de façon correct ce fichier avec l’archive pypi. En effet la mettre dans le setup.py dans l’option data_files résultera en une erreur si on tente une installation sans les droits root. (Oui c’est un appel à l’aide aux bonnes âmes qui me lisent !).

À venir

Quelques améliorations sont à venir comme le probing, une option pour exécuter en dry run ou juste rajouter assez de test pour avoir une couverture descente.

Malgré tout je considère le programme comme assez stable pour être publié tel quel.