[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+$' }
# 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'],

View file

@ -4,7 +4,9 @@
# MIDTOOLS.PY -- Gestion de la conversion mid <-> IP
#
# Copyright (C) 2010 Olivier Iffrig
# (c) 2010 Nicolas Dandrimont
# Authors: Olivier Iffrig <iffrig@crans.org>
# Nicolas Dandrimont <olasd@crans.org>
#
# 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 <http://www.gnu.org/licenses/>.
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 "<Mid(mid=%s, ipv4='%s')>" % (self.mid, self.ipv4())
else:
return "<Mid(%s)>" % self.mid
def __int__(self):
return self.mid