diff --git a/attributs.py b/attributs.py index 5a0ff85..1f7af71 100644 --- a/attributs.py +++ b/attributs.py @@ -45,6 +45,7 @@ import random import string from unicodedata import normalize from crans_utils import format_tel, format_mac, mailexist, validate_name, ip4_of_rid, ip6_of_mac +import itertools sys.path.append("/usr/scripts/") import cranslib.deprecated @@ -682,7 +683,7 @@ class ipHostNumber(Attr): def parse_value(self, ip): if ip == '': ip = ip4_of_rid(str(self.parent['rid'][0])) - self.value = netaddr.ip.IPAddress(ip) + self.value = netaddr.IPAddress(ip) def __unicode__(self): return unicode(self.value) @@ -735,7 +736,7 @@ class rid(Attr): # On veut éviter les rid qui recoupent les ipv4 finissant par # .0 ou .255 - plages = [xrange(config.rid[a][0], config.rid[a][1]+1) for a in config.rid.keys() if ('v6' not in a) and ('special' not in a)] + plages = [itertools.chain(*[xrange(plage[0], plage[1]+1) for plage in value]) for (key, value) in config.rid_primaires.iteritems() if ('v6' not in key) and ('special' not in key)] for plage in plages: if rid in plage: diff --git a/crans_utils.py b/crans_utils.py index e6f839c..5435a2a 100644 --- a/crans_utils.py +++ b/crans_utils.py @@ -44,24 +44,57 @@ from unicodedata import normalize DEVNULL = open(os.devnull, 'w') +def find_rid_plage(rid): + """Trouve la plage du rid fourni""" + for (tp, plages) in config.rid_primaires.iteritems(): + if isinstance(plages, list): + for begin, end in plages: + if begin <= rid <= end: + return tp, (begin, end) + else: + (begin, end) = plages + if begin <= rid <= end: + return tp, (begin, end) + else: + return 'Inconnu', (0, 0) + +def find_ipv4_plage(ipv4): + """Trouve la plage de l'ipv4 fournie""" + for (tp, plage) in config.NETs_primaires.iteritems(): + for sousplage in map(netaddr.IPNetwork, plage): + if ipv4 in sousplage: + return tp, sousplage + def ip4_of_rid(rid): """Convertit un rid en son IP associée""" # Au cas où rid = int(rid) - for net, plage in config.rid.items(): - if rid >= plage[0] and rid <= plage[1]: - break - else: + net, plage = find_rid_plage(rid) + if net == 'Inconnu': raise ValueError("Rid dans aucune plage: %d" % rid) if net == 'special': try: return netaddr.IPAddress(config.rid_machines_speciales[rid]) except KeyError: - return ValueError("Machine speciale inconnue: %d" % rid) + raise ValueError(u"Machine speciale inconnue: %d" % rid) + try: + return netaddr.IPAddress(netaddr.IPNetwork(config.NETs[net][0]).first + rid - plage[0]) + except KeyError: + raise EnvironmentError("Les machines v6-only ne peuvent pas avoir d'ipv4 (%s)" % (net)) - return netaddr.IPAddress(netaddr.IPNetwork(config.NETs[net][0]).first + rid - plage[0]) +def rid_of_ip4(ipv4): + """Convertit une ipv4 en rid, si possible""" + # Est-ce une machine spéciale ? + for (rid, ip) in config.rid_machines_speciales.iteritems(): + if str(ipv4) == ip: + return rid + + # Le cas non-échéant, on va devoir faire de la deep NETs inspection + realm, sousplage = find_ipv4_plage(ipv4) + + return config.rid[realm][0][0] + int(ipv4 - sousplage.first) def prefixev6_of_rid(rid): """ @@ -73,10 +106,8 @@ def prefixev6_of_rid(rid): # Au cas où rid = int(rid) - for net, plage in config.rid.items(): - if rid >= plage[0] and rid <= plage[1]: - break - else: + net, plage = find_rid_plage(rid) + if net == 'Inconnu': raise ValueError("Rid dans aucune plage: %d" % rid) # fil-v6 ou wifi-v6, we don't care @@ -89,10 +120,8 @@ def ip6_of_mac(mac, rid): # Au cas où rid = int(rid) - for net, plage in config.rid.items(): - if rid >= plage[0] and rid <= plage[1]: - break - else: + net, plage = find_rid_plage(rid) + if net == 'Inconnu': raise ValueError("Rid dans aucune plage: %d" % rid) # En théorie, format_mac est inutile, car on ne devrait avoir diff --git a/lc_ldap.py b/lc_ldap.py index 27c8d2f..674e553 100644 --- a/lc_ldap.py +++ b/lc_ldap.py @@ -47,6 +47,7 @@ import attributs import objets import ldap_locks import variables +import itertools ## import de /usr/scripts/ if not "/usr/scripts/" in sys.path: @@ -232,8 +233,8 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object): uldif['objectClass'] = [u'borneWifi'] assert isinstance(owner, objets.AssociationCrans) - elif realm in ["wifi", "wifi-v6"]: - uldif['objectClass'] = [u'machineWifi'] + elif realm in ["wifi-adh", "wifi-v6"]: + ldif['objectClass'] = [u'machineWifi'] assert isinstance(owner, objets.adherent) or isinstance(owner, objets.club) elif realm in ["adherents", "adherents-v6", "personnel-ens"]: @@ -244,7 +245,7 @@ class lc_ldap(ldap.ldapobject.LDAPObject, object): raise ValueError("Realm inconnu: %r" % realm) # On récupère la plage des mids - plage = xrange( *(config.rid[realm])) + plage = itertools.chain(*[xrange(a,b+1) for (a,b) in config.rid_primaires[realm]]) # On récupère le premier id libre dans la plages s'il n'est pas # déjà précisé dans le ldiff rid = uldif.setdefault('rid', [unicode(self._find_id('rid', plage)) ]) diff --git a/objets.py b/objets.py index 36a5b7e..729380d 100644 --- a/objets.py +++ b/objets.py @@ -708,20 +708,20 @@ class machineWifi(machine): attribs = machine.attribs + [attributs.ipsec] ldap_name = "machineWifi" - def set_ipv4(self, login=None): - u"""Définie une ipv4 à la machine si elle n'est possède pas déjà une.""" - if login is None: - login = self.conn.current_login - if not 'ipHostNumber' in self.attrs.keys() or not self['ipHostNumber']: - rid = self['rid']=[ unicode(self.conn._find_id('rid', range(config.rid['wifi'][0], config.rid['wifi'][1]))) ] - ip = self['ipHostNumber'] = [ unicode(crans_utils.ip4_of_rid(int(rid[0]))) ] - self.history_add(login, u"rid") - self.history_add(login, u"ipHostNumber (N/A -> %s)" % ip[0]) - self.save() - - for server in config.dhcp_servers: - dhcp=dydhcp(server) - dhcp.add_host(str(self['ipHostNumber'][0]), str(self['macAddress'][0]), str(self['host'][0])) +# À passer là où il faut +# def set_ipv4(self, login=None): +# u"""Définie une ipv4 à la machine si elle n'est possède pas déjà une.""" +# if login is None: +# login = self.conn.current_login +# if not 'ipHostNumber' in self.attrs.keys() or not self['ipHostNumber']: +# rid = self['rid']=[ unicode(self.conn._find_id('rid', range(config.rid['wifi'][0], config.rid['wifi'][1]+1))) ] +# ip = self['ipHostNumber'] = [ unicode(crans_utils.ip4_of_rid(int(rid[0]))) ] +# self.history_add(login, u"rid") +# self.history_add(login, u"ipHostNumber (N/A -> %s)" % ip[0]) +# self.save() +# from gen_confs.dhcpd_new import dydhcp +# dhcp=dydhcp() +# dhcp.add_host(str(self['ipHostNumber'][0]), str(self['macAddress'][0]), str(self['host'][0])) @crans_object class machineCrans(machine): diff --git a/test.py b/test.py index 88c2df3..3bb6bba 100755 --- a/test.py +++ b/test.py @@ -49,6 +49,13 @@ machine_ldif = { 'host' : [u"autotest-%s.crans.org" % randomStr() ] } +borne_ldif = { + 'macAddress' : [randomMAC()], + 'host' : ["autotest-%s.crans.org" % randomStr() ], + 'canal' : ["11"], + 'puissance' : ["52 khz"], +} + club_ldif = { 'nom' : [ u'autotest-club' ], 'chbre' : [ u'EXT' ], @@ -90,6 +97,8 @@ def test_list_of_dict(keys, list): anim("\tTest de l'attribut %s" % key) ok = True for item in list: + if key == "chbre": + print item['aid'][0] try: item.get(key, []) except psycopg2.OperationalError as error: print ERREUR @@ -108,7 +117,11 @@ def tests_machines(parent_dn, realm_list, ipsec=False): for realm in realm_list: anim("Creation de machines %s" % realm) try: - machine = conn.newMachine(parent_dn, realm, machine_ldif) + if realm == 'bornes': + mldif = borne_ldif + else: + mldif = machine_ldif + machine = conn.newMachine(parent_dn, realm, mldif) if ipsec: machine['ipsec'] = u'auto' machine.create() except Exception as error: @@ -189,7 +202,7 @@ else: print OK tests_machines(adherent.dn, ["adherents", "fil-v6", "personnel-ens"]) - tests_machines(adherent.dn, ["wifi", "wifi-v6"], ipsec=True) + tests_machines(adherent.dn, ["wifi-adh", "wifi-v6"], ipsec=True)