[midtools] Nettoyage, utilisation de netaddr

darcs-hash:20100303045133-ffbb2-4ea9016a286477205b5102f47bd8050b5a19c9ac.gz
This commit is contained in:
Nicolas Dandrimont 2010-03-03 05:51:33 +01:00
parent 293870c436
commit cb4f9c2572
2 changed files with 111 additions and 75 deletions

View file

@ -389,7 +389,29 @@ NETs = { 'serveurs' : [ '138.231.136.0/28' ],
NETs_regexp = { 'all' : '^138\.231\.1(3[6789]|4[0123456789]|5[01])\.\d+$' } 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' ], prefix = { 'subnet' : [ '2a01:240:fe3d::/48' ],
'serveurs' : [ '2a01:240:fe3d:0::/64'], 'serveurs' : [ '2a01:240:fe3d:0::/64'],
'fil' : [ '2a01:240:fe3d:4::/64' ], 'fil' : [ '2a01:240:fe3d:4::/64' ],
@ -427,27 +449,6 @@ vlans = {
'appts': 21 '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 ? # a faire générer par bcfg2 ?
# Les noms des attributs peuvent être changé. # Les noms des attributs peuvent être changé.
role = { 'komaz' : ['main-router'], role = { 'komaz' : ['main-router'],

View file

@ -4,7 +4,9 @@
# MIDTOOLS.PY -- Gestion de la conversion mid <-> IP # MIDTOOLS.PY -- Gestion de la conversion mid <-> IP
# #
# Copyright (C) 2010 Olivier Iffrig # Copyright (C) 2010 Olivier Iffrig
# (c) 2010 Nicolas Dandrimont
# Authors: Olivier Iffrig <iffrig@crans.org> # Authors: Olivier Iffrig <iffrig@crans.org>
# Nicolas Dandrimont <olasd@crans.org>
# #
# This program is free software: you can redistribute it and/or modify # 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 # 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 # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import config import netaddr
import iptools import config
class Mid(object): class Mid(object):
""" """
Permet de décortiquer un mid et d'obtenir les IP correspondantes 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): def __init__(self, mid=None, ipv4=None):
if mid is not None: self.mid = None
self.parse(mid) self.reste = False
else:
self.mid = None
self.reste = False
self.type = None
self.ipv4_dispo = False
self.priv = False
def parse(self, mid):
self.mid = mid
self.type = None self.type = None
for tp in config.mid.keys(): self.ipv4_dispo = False
if mid <= config.mid[tp][1] and mid >= config.mid[tp][0]: 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 self.type = tp
if self.type is None: else:
raise ValueError("mid inconnu : %d" % mid) raise ValueError("mid inconnu : %d" % mid)
self.ipv4_dispo = False self.ipv4_dispo = (mid & (1 << 15)) == 0 and self.type != 'special'
if (mid & (1 << 15)) == 0 and self.type != 'special':
self.ipv4_dispo = True
self.priv = True self.priv = (mid & (1 << 14)) != 0
if (mid & (1 << 14)) == 0:
self.priv = False
self.reste = mid & 0x7ff if self.type == 'personnel-ens':
# if self.type == 'ens': # Inutile pour l'instant self.reste = mid & 0xff
# self.reste &= 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.ipv4_dispo = True
self.priv = ip.startswith('10.') self.priv = ip.is_private()
for tp in ['fil', 'wifi', 'adm', 'gratuit', 'ens']:
if iptools.AddrInNet(ip, config.NETs[tp]): for tp in ['fil', 'wifi', 'adm', 'gratuit', 'personnel-ens']:
self.type = tp for net in config.NETs[tp]:
if ip in netaddr.IPNetwork(net):
self.type = tp
break
if self.type:
break break
if self.type is None: else:
raise ValueError("Impossible de convertir l'adresse IP") raise ValueError("%s dans aucun des réseaux gérés par le Cr@ns..." % ip)
self.mid = int(iptools.QuadToDec(ip)) self.mid = config.mid[self.type][0] + ip.value - netaddr.IPNetwork(config.NETs[self.type][0]).value
self.mid -= int(iptools.param(config.NETs[self.type][0],
True)['network']) if self.mid > config.mid[self.type][1]:
self.reste = self.mid & 0x7ff 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 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 Génère l'IPv4 associée à la machine
""" """
if not self.ipv4_dispo: 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'] if not hasattr(self, '__ipv4'):
ip += self.reste net = netaddr.IPNetwork(config.NETs[self.type][0])
return iptools.DecToQuad(ip) 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: if self.priv:
raise ValueError("Pas de prefix ipv6 disponible pour cette machine") raise ValueError("Pas de prefix ipv6 disponible pour cette machine")
ip = config.prefix['subnet'][0].split(":/")[0] global_net = netaddr.IPNetwork(config.prefix["subnet"][0])
ip += hex(self.mid)[2:] global_net.prefixlen = 64
ip += "::/64" return global_net.next(self.mid)
return ip
def __repr__(self):
if self.ipv4_dispo:
return "<Mid(mid=%s, ipv4='%s')>" % (self.mid, self.ipv4())
else:
return "<Mid(%s)>" % self.mid
def __int__(self):
return self.mid