From cb4f9c2572cca05a08b7121d862f5162e4b6be5e Mon Sep 17 00:00:00 2001 From: Nicolas Dandrimont Date: Wed, 3 Mar 2010 05:51:33 +0100 Subject: [PATCH] [midtools] Nettoyage, utilisation de netaddr darcs-hash:20100303045133-ffbb2-4ea9016a286477205b5102f47bd8050b5a19c9ac.gz --- gestion/config.py | 45 +++++++------- gestion/midtools.py | 141 +++++++++++++++++++++++++++----------------- 2 files changed, 111 insertions(+), 75 deletions(-) diff --git a/gestion/config.py b/gestion/config.py index 6009133b..e220fbf3 100644 --- a/gestion/config.py +++ b/gestion/config.py @@ -389,7 +389,29 @@ NETs = { 'serveurs' : [ '138.231.136.0/28' ], NETs_regexp = { 'all' : '^138\.231\.1(3[6789]|4[0123456789]|5[01])\.\d+$' } -# Les préfix ipv6 +# Classes de mid +# Merci d'essayer de les faire correspondre avec les réseaux +# ci-dessus... +mid = { + # Mid pour les machines fixes + 'fil' : (0, 2047), + # Mid pour les machines fixes ipv6-only + 'fil-v6' : (32768, 34815), + # Mid pour les machines wifi + 'wifi' : (2048, 4095), + # Mid pour les machines wifi ipv6-only + 'wifi-v6' : (34816, 36863), + # Mid pour les machines du vlan adm + 'adm' : (51200, 53247), + # Mid pour les machines du vlan gratuit + 'gratuit' : (53248, 55295), + # Mid pour les machines des personnels ens + 'personnel-ens' : (55296, 55551), + # Mid pour machines spéciales + 'special' : (4096, 6143), + } + +# Les préfixes ipv6 prefix = { 'subnet' : [ '2a01:240:fe3d::/48' ], 'serveurs' : [ '2a01:240:fe3d:0::/64'], 'fil' : [ '2a01:240:fe3d:4::/64' ], @@ -427,27 +449,6 @@ vlans = { 'appts': 21 } -mid = { - # Mid pour les machines fixes - 'fil' : [0, 2047], - # Mid pour les machines fixes ipv6-only - 'fil-v6' : [32768, 34815], - # Mid pour les machines wifi - 'wifi' : [2048, 4095], - # Mid pour les machines wifi ipv6-only - 'wifi-v6' : [34816, 36863], - # Mid pour les machines du vlan adm - 'adm' : [51200, 53247], - # Mid pour les machines du vlan gratuit - 'gratuit' : [53248, 55295], - # Mid pour les machines des personnels ens - 'ens' : [55296, 55551], - # Mid pour les machines du G - 'g' : [8192, 8447], - # Mid pour machines spéciales - 'special' : [4096, 6143] - } - # a faire générer par bcfg2 ? # Les noms des attributs peuvent être changé. role = { 'komaz' : ['main-router'], diff --git a/gestion/midtools.py b/gestion/midtools.py index e0f429d7..ec3fba88 100755 --- a/gestion/midtools.py +++ b/gestion/midtools.py @@ -4,7 +4,9 @@ # MIDTOOLS.PY -- Gestion de la conversion mid <-> IP # # Copyright (C) 2010 Olivier Iffrig +# (c) 2010 Nicolas Dandrimont # Authors: Olivier Iffrig +# Nicolas Dandrimont # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -19,86 +21,119 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import config +import netaddr -import iptools +import config class Mid(object): """ Permet de décortiquer un mid et d'obtenir les IP correspondantes + + Variables d'instance : + - mid : le mid + - type : type de mid (cf. config.mid et [1]) + - reste : le "reste" du mid (permettant de calculer l'IP par exemple) + - ipv4_dispo : une IPv4 existe pour ce mid + - priv : cette machine ne doit pas être accessible de l'extérieur + + [1] http://wiki.crans.org/CransTechnique/PlanAdressage#Machines """ - def __init__(self, mid=None): - if mid is not None: - self.parse(mid) - else: - self.mid = None - self.reste = False - self.type = None - self.ipv4_dispo = False - self.priv = False - - def parse(self, mid): - self.mid = mid + def __init__(self, mid=None, ipv4=None): + self.mid = None + self.reste = False self.type = None - for tp in config.mid.keys(): - if mid <= config.mid[tp][1] and mid >= config.mid[tp][0]: + self.ipv4_dispo = False + self.priv = False + + if mid is not None: + self.__parse(mid) + elif ipv4 is not None: + self.__from_ipv4(ipv4) + else: + raise ValueError("Un des champs mid et ipv4 doit être défini") + + def __parse(self, mid): + """Peuple les champs de l'instance par rapport au mid""" + self.mid = mid + + for tp, (start, end) in config.mid.iteritems(): + if start <= mid <= end: self.type = tp - if self.type is None: + else: raise ValueError("mid inconnu : %d" % mid) - self.ipv4_dispo = False - if (mid & (1 << 15)) == 0 and self.type != 'special': - self.ipv4_dispo = True + self.ipv4_dispo = (mid & (1 << 15)) == 0 and self.type != 'special' - self.priv = True - if (mid & (1 << 14)) == 0: - self.priv = False + self.priv = (mid & (1 << 14)) != 0 - self.reste = mid & 0x7ff -# if self.type == 'ens': # Inutile pour l'instant -# self.reste &= 0xff + if self.type == 'personnel-ens': + self.reste = mid & 0xff + else: + self.reste = mid & 0x7ff + + def __from_ipv4(self, ip): + """Peuple les champs à partir de l'ipv4 donnée""" + if not isinstance(ip, netaddr.IPAddress): + ip = netaddr.IPAddress(ip) + try: + ip.ipv4() + except netaddr.AddrConversionError: + raise ValueError("Ceci n'est pas une IPv4... %s" % ip) - def from_ipv4(self, ip): - """ - Met à jour l' instance pour correspondre à l'IPv4 donnée - """ self.ipv4_dispo = True - self.priv = ip.startswith('10.') - for tp in ['fil', 'wifi', 'adm', 'gratuit', 'ens']: - if iptools.AddrInNet(ip, config.NETs[tp]): - self.type = tp + self.priv = ip.is_private() + + for tp in ['fil', 'wifi', 'adm', 'gratuit', 'personnel-ens']: + for net in config.NETs[tp]: + if ip in netaddr.IPNetwork(net): + self.type = tp + break + if self.type: break - if self.type is None: - raise ValueError("Impossible de convertir l'adresse IP") + else: + raise ValueError("%s dans aucun des réseaux gérés par le Cr@ns..." % ip) - self.mid = int(iptools.QuadToDec(ip)) - self.mid -= int(iptools.param(config.NETs[self.type][0], - True)['network']) - self.reste = self.mid & 0x7ff + self.mid = config.mid[self.type][0] + ip.value - netaddr.IPNetwork(config.NETs[self.type][0]).value + + if self.mid > config.mid[self.type][1]: + raise ValueError("%s trop élevée pour le réseau '%s'" % (ip, self.type)) + + if self.type == 'personnel-ens': + self.reste = self.mid & 0xff + else: + self.reste = self.mid & 0x7ff return self.mid - # if self.type == 'ens': # Inutile pour l'instant - # self.reste &= 0xff - def to_ipv4(self): + def ipv4(self): """ Génère l'IPv4 associée à la machine """ if not self.ipv4_dispo: - raise ValueError("Pas d'adresse ipv4 disponible pour la machine") + raise ValueError("Pas d'adresse IPv4 disponible pour la machine %r" % self) - ip = iptools.param(config.NETs[self.type][0], True)['network'] - ip += self.reste - return iptools.DecToQuad(ip) + if not hasattr(self, '__ipv4'): + net = netaddr.IPNetwork(config.NETs[self.type][0]) + self.__ipv4 = netaddr.IPAddress(net.first + self.reste) - def to_ipv6_vlan(self): + return self.__ipv4 + + def ipv6_network(self): """ - Génère le préfix IPv6 associé à la machine + Génère le réseau /64 IPv6 associé à la machine """ if self.priv: raise ValueError("Pas de prefix ipv6 disponible pour cette machine") - ip = config.prefix['subnet'][0].split(":/")[0] - ip += hex(self.mid)[2:] - ip += "::/64" - return ip + global_net = netaddr.IPNetwork(config.prefix["subnet"][0]) + global_net.prefixlen = 64 + return global_net.next(self.mid) + + def __repr__(self): + if self.ipv4_dispo: + return "" % (self.mid, self.ipv4()) + else: + return "" % self.mid + + def __int__(self): + return self.mid