#! /usr/bin/env python # -*- coding: iso-8859-15 -*- # $Id: secours.py,v 1.5 2007-08-27 12:22:07 salles Exp $ """ Script de reconfigure des services en connexion de secours Arguments : test : teste la connexion et passe en secours si besoin normal : force la connexion normale secours : force la connexion de secours auto : permet la modification automatique de l'état Sans argument configure les services comme indiqué dans etat_maitre Frédéric Pauget août 2005 """ import sys, sre, os, commands from socket import gethostname hostname = gethostname().split(".")[0] path = os.path.dirname(sys.argv[0]) ### Fichiers à modifier, chaine indiquant un commentaire dans ceux-ci ### et commandes à excécuter après édition if hostname == 'rouge' : fichiers = { '/etc/bind/named.conf.options' : '//' , '/etc/postfix/main.cf' : '#' } cmds = [ '/etc/init.d/postfix restart' , '/etc/init.d/bind9 reload' ] elif hostname == 'sila' : fichiers = { '/etc/bind/named.conf.options' : '//' , '/etc/squid/squid.conf' : '#' } cmds = [ '/etc/init.d/squid reload' , '/etc/init.d/bind9 reload' ] elif hostname == 'sable' : fichiers = { '/etc/squid/squid.conf' : '#' } cmds = [ '/etc/init.d/squid reload' ] elif hostname == 'zamok' : fichiers = { '/etc/postfix/main.cf' : '#' } cmds = [ '/etc/init.d/postfix restart' ] else : print "Script sans effet sur cette machine." sys.exit(1) # Machines à pinguer pour tester la connexion hosts = ( '91.121.84.138', '216.239.57.104', '213.228.0.42', '217.12.3.11') #################### # Fonctions utiles # #################### def normal_ok() : """ Teste le connexion normale à l'aide de pings Retourne False si il y a un problème sur la connexion normale Retourne True si la connexion normale est fonctionelle """ pings = commands.getoutput('/usr/sbin/fping %s' % ' '.join(hosts)) print pings if pings.count('is unreachable') == len(hosts) : return False else : return True def edit(file,comment,etat) : """ Edite le fichier fourni en commentant (mode normal) ou décommentant (mode secours) les lignes signalées : * celles se terminant avec #POUR SECOURS * ou les n lignes (<10)suivant une qui commande par #POUR SECOURS-n (si le -n est omis une seule ligne est affectée)""" signal = '#POUR SECOURS' l = len(signal) fd = open(file) line = fd.readline() new = '' reste = 0 # Nombre de lignes restant à traiter while line : l = line.rstrip() mo = sre.match('^(.*)'+signal+'(|-.)$',l) if (mo and len(mo.group(1)) > 1) or reste: # Ligne pour secours if not sre.match('^' + comment,l) and etat == 'normal': # On est actuellement configuré en secours # Il faut passer en normal new += comment + line elif sre.match('^' + comment,l) and etat == 'secours' : # On est actuellement configuré en normal # Il faut passer en secours new += line.replace(comment,'',1) else : # Rien à faire, on est bien configuré new += line if reste : reste -= 1 elif mo and len(mo.group(1)) == 0: # On a une ligne avec secours uniquement, c'est les n # prochaines lignes qui font foi try : reste = int(mo.group(2)[1:]) except : reste = 1 new += line else : # Ligne normale new += line line = fd.readline() fd.close() # Ecriture de la nouvelle version open(file,'w').write(new) if __name__ == '__main__' : # Etat dans lequel on devrai être etat_maitre, mode = map(str.strip,open(path+'/etat_maitre').readlines()) nouvel_etat = etat_maitre try: etat_actuel = open('%s/etat_%s' % (path,hostname)).readline().strip() except : etat_actuel = None if len(sys.argv) == 2 : if sys.argv[1] == 'secours' : print "Connexion de secours forcée." nouvel_etat = 'secours' mode = 'manuel' open(path+'/etat_maitre','w').write('%s\n%s'% (nouvel_etat,mode)) elif sys.argv[1] == 'normal' : print "Connexion normale forcée." nouvel_etat = 'normal' mode = 'manuel' open(path+'/etat_maitre','w').write('%s\n%s'% (nouvel_etat,mode)) elif sys.argv[1] in ( 'auto', 'test' ) : if sys.argv[1] == 'auto' : mode = 'auto' if mode != 'auto' : print 'Mode manuel, passer en mode auto pour tester' sys.exit(1) # On choisi le mode de connexion if normal_ok() : nouvel_etat = 'normal' else : nouvel_etat = 'secours' if nouvel_etat != etat_maitre or sys.argv[1] == 'auto' : open(path + '/etat_maitre','w').write('%s\n%s'% (nouvel_etat,mode)) print "Mode %s" % mode if nouvel_etat == etat_actuel : print etat_actuel else : # Il faut changer sys.stderr.write("Passage en mode %s\n" % nouvel_etat) # Ecriture sur stderr pour le cron for f, c in fichiers.items() : try: print 'Edition de %s' % f edit(f,c,nouvel_etat) except: import traceback traceback.print_exc() open('%s/etat_%s' % (path,hostname),'w').write(nouvel_etat) for c in cmds : os.system(c)