Commit cb70db69 authored by Gabriel Detraz's avatar Gabriel Detraz

Merge branch 'master' of https://gitlab.crans.org/nounous/scripts

parents 896bfbbe efee91b3
......@@ -45,6 +45,10 @@ DNSSEC_BACKEND = {
'silice': 'bind',
}
# noms (relatif) sur lequels on veux mettre les enregistrements MX
# utiliser @ pour l'apex des zone dns (crans.org, crans.fr, etc...)
MXs_NAMES = ['@', 'lists']
MXs = {
'redisdead.crans.org': {
'prio': 10,
......
......@@ -463,8 +463,8 @@ class Zone(ZoneBase):
to_nom = self.get_name(machine['host'][0])
# Si l'alias est sur le nom de la zone, il faut ajouter
# des entrées standard.
if alias in ['@', '%s.' % self.zone_name]:
# des entrées standard. Idem ii on veux également y mettre un enregistrment MX.
if alias in ['@', '%s.' % self.zone_name] + config.dns.MXs_NAMES:
self.add_a_record(alias, machine)
self.add_aaaa_record(alias, machine)
self.add_sshfp_record(alias, machine)
......@@ -625,8 +625,12 @@ class dns(gen_config):
DELEG = {}
### Serveurs de mail
# format : [ priorité serveur , .... ]
MXs = [MX('@', config.dns.MXs[_mx].get('prio', 25), "%s." %_mx) for _mx in config.dns.MXs]
# format : [ priorité serveur , .... ]. ON génère la liste a partir de config.dns
MXs = [
MX(name, config.dns.MXs[_mx].get('prio', 25), "%s." %_mx)
for _mx in config.dns.MXs
for name in config.dns.MXs_NAMES
]
SRVs = {
'crans.org': [
......
......@@ -154,7 +154,7 @@ class SequenceLoader(list):
return loader(name)
except SecretNotFound as exc:
notfound_error = notfound_error or exc
raise notfound_error
class ACLChecker(object):
......@@ -175,17 +175,17 @@ class ACLChecker(object):
def check(self, name):
"""Teste si ``name`` a le droit d'être lu"""
user = os.getenv('SUDO_USER')
# TODO Trigger et sa clé SSH !
if user == 'root':
return True
# radius a besoin des mdp clients (pour dynamic_clients),
# du ldap et du dhcp pour inscrire des gens
if user == 'freerad' and in_group('freeradius') and \
name.split('_', 1)[0] in ['radius', 'dhcp', 'ldap']:
return True
if user == 'www-data' and in_group('intranet2-service'):
logger.debug('ici: %s' % name.split('_', 1)[0])
if name.split('_', 1)[0] in [ 'comnpay', 'dhcp', 'digicode', 'intranet',
......@@ -202,6 +202,12 @@ class ACLChecker(object):
if user == 'gammu' and in_group('service-sms') and name == "rabbitmq_sms":
return True
# nagios a besoin de faire des recherches dans la base LDAP
if (user == 'nagios' and
in_group('icinga2-master') and
name in ['ldap_readonly_auth_dn', 'ldap_readonly_password']):
return True
# Rempli loader avec la variable qu'on veut
loader = SequenceLoader([python_loader, single_file_loader, json_loader])
......@@ -223,7 +229,7 @@ def get(name):
""" Récupère un secret. """
prog = os.path.basename(getattr(sys, 'argv', ['undefined'])[0])
logger.debug('%s (in %s) asked for %s' % (getpass.getuser(), prog, name))
try:
return loader(name)
except SecretNotFound:
......
#!/usr/scripts/python.sh
#-*- coding: utf-8 -*-
"""
Plugin Nagios récupérant l'état de certaines ressources de l'association
"""
from __future__ import print_function, unicode_literals
import os, sys
from argparse import ArgumentParser
from collections import OrderedDict
from lc_ldap import shortcuts, ldap as base_ldap
from gestion.config import NETs, rid_primaires
import nagiosplugin
# Définition des arguments que mange le script
parser = ArgumentParser(description=__doc__)
parser.add_argument('-B', '--buildings', action='store_true', help="Statistiques sur les bâtiments")
parser.add_argument('-N', '--networks', action='store_true', help="Statistiques sur les réseaux IP du Crans")
if __name__ == "__main__":
args = parser.parse_args()
# Connexion à la base LDAP
ldap = shortcuts.lc_ldap_readonly()
# Liste des bâtiments à regarder
BATS = [
"A", # Bâtiment A
"B", # Bâtiment B
"C", # Bâtiment C
"G", # Bâtiment G
"H", # Bâtiment H
"I", # Bâtiment I
"J", # Bâtiment J
"M", # Bâtiment M
"P", # Pavillon des Jardins
]
# Plages de RIDs utilisées pour compter les attributions d'IPs
RIDS = OrderedDict([
(name, rid_primaires[name]) for name in rid_primaires if name in NETs and
name != 'multicast'
])
def _count_segment(first, last):
"""
Compte le nombre de RIDs entre first et last (inclus) dans la base LDAP.
"""
return len(
ldap.search_ext_s('ou=data,dc=crans,dc=org',
scope=base_ldap.SCOPE_SUBTREE,
filterstr='(&(rid>=%d)(rid<=%d))' % (first, last),
attrsonly=0, attrlist=[b'rid']
)
)
def _count_rid(plages):
"""
Compte le nombre de RIDs d'une liste de plages, dans la base LDAP
"""
return sum(_count_segment(first, last) for (first, last) in plages)
def _total_rid(plages):
"""
Total théorique du nombre de RIDs, dans une liste de plages, sans les
éventuels .0 et .255 (si IPv4 dispo)
"""
tot = 0
for (first, last) in plages:
tot += last - first + 1
# En vrai, il faut retirer les rids d'IPs en .255 ou .0,
# si ipv4 publique (bit 15 pas à 1) ou privée dispos (bit 14 pas à 0).
if first >> 14 != 0b10:
for xxx in [0, 255]:
# On calcule l'indice de la première et dernière IP en .xxx
# dans l'intervalle [first, last], à coup de division entière
jlast = (last-xxx)/256 # arrondi inf
jfirst = -((-first+xxx)/256) #arrondi sup
# Et donc on retire le nombre d'ip finissant en .xxx dans
# l'intervale
tot -= jlast - jfirst + 1
return tot
class Association(nagiosplugin.Resource):
"""
Ressource représentant les ressources de l'association
"""
def __init__(self, buildings, networks):
self.buildings = buildings
self.networks = networks
def get_buildings(self):
"""
Compte le nombre d'adhérent par bâtiment
"""
bats_stats = OrderedDict()
for letter in BATS:
bats_stats[letter] = len(ldap.search(u"chbre=%s*" % letter))
return bats_stats
def get_networks(self):
"""
Calcule les proportions d'IP attribuées/restantes.
Basé sur le plugin Munin stats-ip.
"""
nets_stats = OrderedDict()
for subnet, plages in RIDS.items():
nets_stats[subnet] = (_count_rid(plages)*100)/_total_rid(plages)
return nets_stats
def probe(self):
probes = OrderedDict()
if self.buildings:
for bat, nb_adh in self.get_buildings().items():
yield nagiosplugin.Metric("Batiment %s" % bat,
nb_adh,
uom=None,
min=0,
max=None,
context="nb_adh"
)
if self.networks:
for subnet, value in self.get_networks().items():
yield nagiosplugin.Metric("Reseau %s" % subnet,
value,
uom='%',
min=0,
max=100,
context="subnets"
)
@nagiosplugin.guarded
def main():
check = nagiosplugin.Check(
Association(args.buildings, args.networks),
nagiosplugin.ScalarContext('nb_adh', '1000', '2000'),
nagiosplugin.ScalarContext('subnets', '90', '95'),
)
check.main()
if __name__ == '__main__':
main()
......@@ -105,7 +105,7 @@ class Supplies(nagiosplugin.Resource):
curr_levels = self.get_current_levels()
for desc, curr_level, uom, max_cap in zip(descs, curr_levels, uoms, max_capacities):
if "Agrafeuse" in desc:
if ("Agrafeuse" in desc) or ("Stapler" in desc):
if args.staplers:
pass
else:
......@@ -117,7 +117,7 @@ class Supplies(nagiosplugin.Resource):
else:
continue
if "Agrafeuse" in desc:
if ("Agrafeuse" in desc) or ("Stapler" in desc):
yield nagiosplugin.Metric(desc, curr_level, uom=uom, min=0, max=max_cap, context="staplers")
else:
if int(curr_level) < 0:
......
#!/usr/bin/python
#-*- coding: utf-8 -*-
"""
Plugin Nagios vérifiant l'état d'un onduleur via SNMP
Nécéssite python-netsnmp.
"""
from __future__ import print_function, unicode_literals
import os, sys
from argparse import ArgumentParser
from collections import namedtuple, OrderedDict
import re
import nagiosplugin
from netsnmp import snmpwalk, Varbind
# Définition des arguments que mange le script
parser = ArgumentParser(description=__doc__)
parser.add_argument('-H', '--hostname', type=unicode, required=True, help="Adresse IP ou nom de l'onduleur")
parser.add_argument('-w', '--warning', type=int, nargs='?', default=100, help="Seuil pour la génération d'un avertissement")
parser.add_argument('-c', '--critical', type=int, nargs='?', default=50, help="Seuil pour la génération d'une alerte")
parser.add_argument('-C', '--community', type=unicode, nargs='?', default="public", help="Paramètre 'community' utilisé pour l'authentification en SNMPv1/SNMPv2c")
parser.add_argument('-L', '--legacy', action='store_true', help="Utiliser les MIB legacy pour les onduleurs MGE plutôt que ceux de l'IETF")
parser.add_argument('-B', '--battery', action='store_true', help="Récupérer les informations de la batterie")
parser.add_argument('-I', '--input', action='store_true', help="Récupérer les informations sur l'alimentation électrique en entrée")
parser.add_argument('-O', '--output', action='store_true', help="Récupérer les informations sur l'alimentation électrique en sortie")
parser.add_argument('-E', '--environment', action='store_true', help="Récupérer les informations sur l'environnement de l'onduleur")
if __name__ == "__main__":
args = parser.parse_args()
# OIDs
OID_BATTERY = {
'IETF' : 'upsBattery',
'MGE' : 'SNMPv2-SMI::enterprises.705.1.5',
}
OID_INPUT = {
'IETF' : 'upsInput',
'MGE' : 'SNMPv2-SMI::enterprises.705.1.6',
}
OID_OUTPUT = {
'IETF' : 'upsOutput',
'MGE' : 'SNMPv2-SMI::enterprises.705.1.7',
}
OID_ENVIRONMENT = {
'IETF' : None,
'MGE' : 'SNMPv2-SMI::enterprises.705.1.8',
}
# État des batteries
BATTERY_STATUS = {
1 : 'Inconnu',
2 : 'Normal',
3 : 'Faible',
4 : 'Affabli',
}
# Sources possibles pour l'alimentation en sortie
OUTPUT_SOURCES = {
1 : 'Autre',
2 : 'Aucune',
3 : 'Normal',
4 : 'Mode Bypass',
5 : 'Batterie',
6 : 'Booster',
7 : 'Reducer',
}
# Classe resprésentant un résultat de mesure
Probe = namedtuple('Probe', ['value', 'uom', 'min', 'max', 'context'])
def get_status_from_OID(oid, hostname, community):
"""
Procède à un snmpwalk pour l'hôte spécifié et l'OID donné
"""
return snmpwalk(
Varbind(oid),
Version=1,
DestHost=hostname,
Community=community
)
def clean_snmp_output(iterable):
"""
Retire les caractères indésirables de la sortie de NetSNMP
"""
try:
return [x.replace(b"\x00", "") for x in iterable]
except TypeError:
return iterable
class StateContext(nagiosplugin.Context):
"""
Un contexte pour l'évaluation de l'état des batteries
"""
def evaluate(self, metric, resource):
if self.name == 'out_state':
if metric.value in [1, 2]:
state = nagiosplugin.Unknown
elif metric.value in [3, 4]:
state = nagiosplugin.Ok
elif metric.value in [6, 7]:
state = nagiosplugin.Warn
else:
state = nagiosplugin.Critical
elif self.name == 'batt_state':
if metric.value in [1]:
state = nagiosplugin.Unknown
elif metric.value in [2]:
state = nagiosplugin.Ok
elif metric.value in [3]:
state = nagiosplugin.Warn
else:
state = nagiosplugin.Critical
else:
state = nagiosplugin.Unknown
return self.result_cls(state, self.describe(metric), metric)
def describe(self, metric):
if self.name == 'batt_state':
return BATTERY_STATUS[metric.value]
elif self.name == 'out_state':
return OUTPUT_SOURCES[metric.value]
else:
return None
class UPS(nagiosplugin.Resource):
"""
Ressource représentant un onduleur
"""
def __init__(self, hostname, community,
legacy, battery, input,
output, environment):
self.hostname = hostname
self.community = community
self.oid_type = 'MGE' if legacy else 'IETF'
self.battery = battery
self.input = input
self.output = output
self.environment = environment
def _get(self, what):
return clean_snmp_output(
get_status_from_OID(
what, self.hostname, self.community
)
)
def get_battery_state(self):
b_state = self._get(OID_BATTERY[self.oid_type])
if self.oid_type == 'IETF':
res = OrderedDict({
'Etat' : Probe(int(b_state[0]), None, None, None, 'batt_state'),
'Autonomie' : Probe(int(b_state[2])*60, 's', 0, None, 'autonomy'),
'Niveau' : Probe(int(b_state[3]), '%', 0, 100, 'level'),
})
else:
res = OrderedDict({
'Autonomie' : Probe(int(b_state[0]), 's', 0, None, 'autonomy'),
'Niveau' : Probe(int(b_state[1]), '%', 0, 100, 'level'),
})
return res
def get_input_state(self):
in_state = self._get(OID_INPUT[self.oid_type])
if self.oid_type == 'IETF':
return OrderedDict({
'Frequence en entree' : Probe(int(in_state[2])*0.1, 'Hz', None, None, 'frequency'),
'Tension en entree' : Probe(int(in_state[3]), 'V', None, None, 'voltage'),
'Courant en entree' : Probe(int(in_state[4])*0.1, 'A', None, None, 'current'),
})
else:
return OrderedDict({
'Tension en entree' : Probe(int(in_state[1])*0.1, 'V', None, None, 'voltage'),
'Courant en entree' : Probe(int(in_state[9])*0.1, 'A', None, None, 'current'),
})
def get_output_state(self):
out_state = self._get(OID_OUTPUT[self.oid_type])
if self.oid_type == 'IETF':
return OrderedDict({
'Fonctionnement' : Probe(int(out_state[0]), None, None, None, 'out_state'),
'Frequence de sortie' : Probe(int(out_state[1])*0.1, 'Hz', None, None, 'frequency'),
'Tension de sortie' : Probe(int(out_state[3]), 'V', None, None, 'voltage'),
'Courant de sortie' : Probe(int(out_state[4])*0.1, 'A', None, None, 'current'),
'Charge' : Probe(int(out_state[6]), '%', 0, None, 'load'),
})
else:
return OrderedDict({
'Frequence de sortie' : Probe(int(out_state[3])*0.1, 'Hz', None, None, 'frequency'),
'Tension de sortie' : Probe(int(out_state[2])*0.1, 'V', None, None, 'voltage'),
'Courant de sortie' : Probe(int(out_state[5]), 'A', None, None, 'current'),
'Charge' : Probe(int(out_state[4]), '%', 0, None, 'load'),
})
def get_environment(self):
env_state = self._get(OID_ENVIRONMENT[self.oid_type])
if self.oid_type == 'IETF':
return {}
else:
return {
'Temperature' : Probe(int(env_state[0])*0.1, 'C', None, None, 'temperature'),
'Hygrometrie' : Probe(int(env_state[1])*0.1, '%', 0, 100, 'hygrometry'),
}
def probe(self):
probes = OrderedDict()
if self.battery:
probes.update(**self.get_battery_state())
if self.input:
probes.update(**self.get_input_state())
if self.output:
probes.update(**self.get_output_state())
if self.environment:
probes.update(**self.get_environment())
for desc, values in probes.items():
yield nagiosplugin.Metric(
desc,
values.value,
uom=values.uom,
min=values.min,
max=values.max,
context=values.context
)
@nagiosplugin.guarded
def main():
check = nagiosplugin.Check(
UPS(args.hostname, args.community, args.legacy, args.battery, args.input, args.output, args.environment),
nagiosplugin.ScalarContext('frequency', '48:52', '45:55'),
nagiosplugin.ScalarContext('voltage', '215:235', '200:250'),
nagiosplugin.ScalarContext('current', '~:', '~:'),
nagiosplugin.ScalarContext('load', '~:70', '~:90'),
nagiosplugin.ScalarContext('temperature', '10:20', '0:30'),
nagiosplugin.ScalarContext('hygrometry', '65', '85'),
nagiosplugin.ScalarContext('level', '20:', '5:'),
nagiosplugin.ScalarContext('autonomy', '1200:', '600:'),
StateContext('batt_state'),
StateContext('out_state'),
)
check.main()
if __name__ == '__main__':
os.environ['MIBS'] = 'UPS-MIB:SNMPv2-SMI'
main()
......@@ -14,7 +14,7 @@ GIT_REPOS="/usr/scripts /usr/scripts/lc_ldap"
PERIOD=5
check_repo () {
echo "vérification de $1"
echo "Vérification de $1"
cd $1
( git status | grep "# Your branch" -q ) && {
echo "...et dépôt pas à jour"
......@@ -24,29 +24,63 @@ check_repo () {
fetch_updates () {
cd $1
if [ ! -f ".git/FETCH_HEAD" ]; then
echo "Initial fetching of the repo"
git fetch
fi
if test ! "`find .git/FETCH_HEAD -mmin +$PERIOD`"; then
return
fi
umask 002
echo "fetching $1"
git fetch origin > /dev/null
if [ $hasmodules -eq 0 ]; then
echo "Fetching recursively"
git fetch --recurse-submodules origin > /dev/null
else
git fetch origin > /dev/null
fi
}
try_ff () {
cd $1
if git status | grep "^Your branch is behind.*can be fast-forwarded.$" -q; then
echo "Fast forward..."
git pull || exit 12
if [ $hasmodules -eq 0 ]; then
git pull --recurse-submodules origin master || exit 12
else
git pull || exit 12
fi
else
echo "Nothing to fast forward"
fi
}
has_submodules () {
cd $1
if (ls -al | grep ".gitmodules"); then
subdirs="$(cat .gitmodules | grep path | cut -d= -f2-)"
for subdir in $subdirs; do
cd $subdir
if [ `ls -lA | wc -l` -eq 1 ]; then
echo "Initializing submodule"
git submodule init
git submodule update
fi
return 0
done
fi
return 1
}
# Et on check que les repos sont ok
for dir in $GIT_REPOS; do
fetch_updates $dir
check_repo $dir
try_ff $dir
has_submodules $dir
hasmodules=$?
fetch_updates $dir
check_repo $dir
try_ff $dir
done
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment