1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import os, re
17
19 """Erreur interne
20 """
21
23 """valeur hors de la plage
24 """
25
27 """classe représentant un ensemble d'identifiants spécifiques à un ENT
28 les ids ont la forme suivante: LxxCiiii
29 L/C : code ENT défini dans le SDET (cf annexes) et dépendant de l'entité porteuse du projet
30 xx/iiii : 2 lettres et 4 chiffres identifiant un utilisateur
31 """
32
33 digits = (26, 26, 10, 10, 10, 10)
34
36 max_id = 1
37 for digit in self.digits:
38 max_id = max_id * digit
39 self.max_id = max_id - 1
40 self.code_ent = code_ent
41 self.digit_vals = self._def_digit_vals()
42 self.regexp = re.compile('^\w[a-z]{2,2}\w\d{4,4}')
43
45 """définit le poids de chaque caractère dans un identifiant
46 """
47 digit_vals = []
48 for num_digit in range(len(self.digits)):
49 val = 1
50 for digit in self.digits[num_digit+1:]:
51 val = val * digit
52 digit_vals.append(val)
53 return digit_vals
54
56 """renvoie la représentation au format SDET d'un identifiant numérique
57 """
58 sdet_id = []
59 sdet_id.append(self.code_ent[0])
60 if type(num_id) != int:
61 raise TypeError("type integer requis : %s" % str(num_id))
62 if 0 > num_id or num_id > self.max_id:
63 raise OutOfRangeError("Valeur incompatible : %s" % str(num_id))
64 for car in range(2):
65 sdet_id.append(chr(ord('a') + (num_id / self.digit_vals[car])))
66 num_id = num_id.__mod__(self.digit_vals[car])
67 sdet_id.append(self.code_ent[1])
68 for car in range(2, 5):
69 sdet_id.append(str(num_id / self.digit_vals[car]))
70 num_id = num_id.__mod__(self.digit_vals[car])
71 sdet_id.append(str(num_id))
72 return "".join(sdet_id)
73
75 """renvoie la représentation numérique d'un identifiant au format SDET
76 """
77 if type(string_id) not in (str, unicode):
78 raise TypeError("Chaine requise : %s" % str(string_id))
79 string_id = string_id.lower()
80 if not self.regexp.match(string_id):
81 raise ValueError("Chaine au mauvais format : %s" % string_id)
82 num_id = 0
83 for car in range(2):
84 num_id += (ord(string_id[car + 1]) - ord('a')) * self.digit_vals[car]
85 for car in range(2, 5):
86 num_id += int(string_id[car + 2]) * self.digit_vals[car]
87 num_id += int(string_id[7])
88 return num_id
89
91 """Adaptation de la classe IdPool pour le côté client
92 (maintient la liste des identifiants disponibles et
93 permet leur affectation séquencielle)
94 """
95
96 - def __init__(self, code_ent, state_dir="/etc/sysconfig/eole"):
97 """initialise un pool sans identifiant disponibles
98 """
99 super(ClientIdPool, self).__init__(code_ent)
100 self.state_file = os.path.join(state_dir, "ent_ids_%s" % code_ent)
101 self.load_state()
102
104 """charge la liste des plages disponibles
105 """
106 self.free = []
107 self.free_space = 0
108 if os.path.isfile(self.state_file):
109 data = file(self.state_file).read().strip()
110
111 for line in data.split('\n'):
112 if line != '':
113 minid, maxid = line.split(',')
114 self._add_free_range(int(minid), int(maxid))
115
117 """sauvegarde les plages disponibles
118 """
119 try:
120 f_state = file(self.state_file, 'w')
121 except IOError:
122 return False
123 for minid, maxid in self.free:
124 f_state.write('%s,%s\n' % (minid, maxid))
125 f_state.close()
126 return True
127
129 """représentation par défaut de l'objet
130 """
131 descr = "ENT %s" % self.code_ent
132 descr += " - %d identifiant(s) disponible(s)" % self.free_space
133 if self.free:
134 descr += " - prochain : %s" % self.id_to_string(self.free[0][0])
135 return descr
136
138 """ajoute une plage d'identifiants disponibles
139 minid, maxid : identifiants au format ent
140 """
141
142 minid = self.string_to_id(minid)
143 maxid = self.string_to_id(maxid)
144 self._add_free_range(minid, maxid)
145
147 """ajoute une plage d'identifiants disponibles
148 """
149 insert_index = 0
150
151 if self.free:
152 for rng in self.free:
153 if rng[0] > maxid:
154
155 break
156 insert_index += 1
157
158 self.free.insert(insert_index, (minid, maxid))
159 self.free_space += maxid - minid + 1
160
162 """renvoie le prochain identifiant disponible
163 """
164 if self.free:
165 first_range = self.free[0]
166 new_id = first_range[0]
167
168 if first_range[0] != first_range[1]:
169 self.free[0] = (first_range[0] + 1, first_range[1])
170 else:
171 self.free.remove(first_range)
172 self.free_space -= 1
173 return self.id_to_string(new_id)
174 return None
175