add SubMulti
[tiramisu.git] / test / test_parsing_group.py
1 # coding: utf-8
2 import autopath
3 from tiramisu.setting import groups, owners
4 from tiramisu.config import Config
5 from tiramisu.option import ChoiceOption, BoolOption, IntOption, \
6     StrOption, OptionDescription
7 from tiramisu.error import SlaveError
8
9 from py.test import raises
10
11
12 def make_description():
13     numero_etab = StrOption('numero_etab', "identifiant de l'établissement")
14     nom_machine = StrOption('nom_machine', "nom de la machine", default="eoleng")
15     nombre_interfaces = IntOption('nombre_interfaces', "nombre d'interfaces à activer",
16                                   default=1)
17     activer_proxy_client = BoolOption('activer_proxy_client', "utiliser un proxy",
18                                       default=False)
19     mode_conteneur_actif = BoolOption('mode_conteneur_actif', "le serveur est en mode conteneur",
20                                       default=False)
21     adresse_serveur_ntp = StrOption('serveur_ntp', "adresse serveur ntp", multi=True)
22     time_zone = ChoiceOption('time_zone', 'fuseau horaire du serveur',
23                              ('Paris', 'Londres'), 'Paris')
24
25     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé")
26     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
27
28     master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
29     interface1 = OptionDescription('interface1', '', [master])
30     interface1.impl_set_group_type(groups.family)
31
32     general = OptionDescription('general', '', [numero_etab, nom_machine,
33                                 nombre_interfaces, activer_proxy_client,
34                                 mode_conteneur_actif, adresse_serveur_ntp,
35                                 time_zone])
36     general.impl_set_group_type(groups.family)
37     new = OptionDescription('new', '', [], properties=('hidden',))
38     new.impl_set_group_type(groups.family)
39     creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1, new])
40     descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole])
41     return descr
42
43
44 def test_base_config():
45     descr = make_description()
46     config = Config(descr)
47     config.read_write()
48     assert config.creole.general.activer_proxy_client is False
49     assert config.creole.general.nom_machine == "eoleng"
50     assert config.find_first(byname='nom_machine', type_='value') == "eoleng"
51     result = {'general.numero_etab': None, 'general.nombre_interfaces': 1,
52               'general.serveur_ntp': [], 'interface1.ip_admin_eth0.ip_admin_eth0': None,
53               'general.mode_conteneur_actif': False, 'general.time_zone': 'Paris',
54               'interface1.ip_admin_eth0.netmask_admin_eth0': None, 'general.nom_machine':
55               'eoleng', 'general.activer_proxy_client': False}
56     assert config.creole.make_dict() == result
57     result = {'serveur_ntp': [], 'mode_conteneur_actif': False,
58               'ip_admin_eth0': None, 'time_zone': 'Paris', 'numero_etab': None,
59               'netmask_admin_eth0': None, 'nom_machine': 'eoleng', 'activer_proxy_client':
60               False, 'nombre_interfaces': 1}
61     assert config.creole.make_dict(flatten=True) == result
62
63
64 def test_make_dict_filter():
65     descr = make_description()
66     config = Config(descr)
67     config.read_write()
68     subresult = {'numero_etab': None, 'nombre_interfaces': 1,
69                  'serveur_ntp': [], 'mode_conteneur_actif': False,
70                  'time_zone': 'Paris', 'nom_machine': 'eoleng',
71                  'activer_proxy_client': False}
72     result = {}
73     for key, value in subresult.items():
74         result['general.' + key] = value
75     assert config.creole.make_dict(withoption='numero_etab') == result
76     raises(AttributeError, "config.creole.make_dict(withoption='numero_etab', withvalue='toto')")
77     assert config.creole.make_dict(withoption='numero_etab', withvalue=None) == result
78     assert config.creole.general.make_dict(withoption='numero_etab') == subresult
79
80
81 def test_get_group_type():
82     descr = make_description()
83     config = Config(descr)
84     config.read_write()
85     grp = config.unwrap_from_path('creole.general')
86     assert grp.impl_get_group_type() == groups.family
87     assert grp.impl_get_group_type() == 'family'
88     assert isinstance(grp.impl_get_group_type(), groups.GroupType)
89     raises(TypeError, 'grp.impl_set_group_type(groups.default)')
90
91
92 def test_iter_on_groups():
93     descr = make_description()
94     config = Config(descr)
95     config.read_write()
96     result = list(config.creole.iter_groups(group_type=groups.family))
97     group_names = [res[0] for res in result]
98     assert group_names == ['general', 'interface1']
99     for i in config.creole.iter_groups(group_type=groups.family):
100         #test StopIteration
101         break
102
103
104 def test_iter_on_groups_force_permissive():
105     descr = make_description()
106     config = Config(descr)
107     config.read_write()
108     config.cfgimpl_get_settings().setpermissive(('hidden',))
109     result = list(config.creole.iter_groups(group_type=groups.family,
110                                             force_permissive=True))
111     group_names = [res[0] for res in result]
112     assert group_names == ['general', 'interface1', 'new']
113
114
115 def test_iter_on_groups_props():
116     descr = make_description()
117     config = Config(descr)
118     config.read_write()
119     config.cfgimpl_get_settings()[descr.creole.interface1].append('disabled')
120     result = list(config.creole.iter_groups(group_type=groups.family))
121     group_names = [res[0] for res in result]
122     assert group_names == ['general']
123
124
125 def test_iter_on_empty_group():
126     config = Config(OptionDescription("name", "descr", []))
127     config.read_write()
128     result = list(config.iter_groups())
129     assert result == []
130     for i in config.iter_groups():
131         pass
132     for i in config:
133         pass
134     assert [] == list(config)
135
136
137 def test_iter_not_group():
138     config = Config(OptionDescription("name", "descr", []))
139     config.read_write()
140     raises(TypeError, "list(config.iter_groups(group_type='family'))")
141
142
143 def test_groups_with_master():
144     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
145     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
146     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
147     interface1.impl_set_group_type(groups.master)
148     assert interface1.impl_get_group_type() == groups.master
149
150
151 def test_groups_with_master_in_config():
152     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
153     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
154     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
155     interface1.impl_set_group_type(groups.master)
156     Config(interface1)
157     assert interface1.impl_get_group_type() == groups.master
158
159
160 def test_allowed_groups():
161     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
162     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
163     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
164     raises(ValueError, "interface1.impl_set_group_type('toto')")
165
166
167 def test_master_not_valid_name():
168     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
169     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
170     invalid_group = OptionDescription('interface1', '', [ip_admin_eth0, netmask_admin_eth0])
171     raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
172
173
174 def test_sub_group_in_master_group():
175     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
176     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
177     subgroup = OptionDescription("subgroup", '', [])
178     invalid_group = OptionDescription('ip_admin_eth0', '', [subgroup, ip_admin_eth0, netmask_admin_eth0])
179     raises(ValueError, "invalid_group.impl_set_group_type(groups.master)")
180
181
182 def test_group_always_has_multis():
183     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
184     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
185     group = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
186     raises(ValueError, "group.impl_set_group_type(groups.master)")
187
188
189 #____________________________________________________________
190 def test_values_with_master_and_slaves():
191     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
192     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
193     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
194     interface1.impl_set_group_type(groups.master)
195     maconfig = OptionDescription('toto', '', [interface1])
196     cfg = Config(maconfig)
197     cfg.read_write()
198     owner = cfg.cfgimpl_get_settings().getowner()
199     assert interface1.impl_get_group_type() == groups.master
200     assert cfg.getowner(ip_admin_eth0) == owners.default
201     assert cfg.getowner(netmask_admin_eth0) == owners.default
202     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
203     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
204     assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
205     assert cfg.ip_admin_eth0.netmask_admin_eth0 == [None]
206     assert cfg.getowner(ip_admin_eth0) == owner
207     assert cfg.getowner(netmask_admin_eth0) == owners.default
208     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.147"]
209     raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.append(None)')
210     raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(0)')
211
212
213 def test_reset_values_with_master_and_slaves():
214     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
215     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
216     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
217     interface1.impl_set_group_type(groups.master)
218     maconfig = OptionDescription('toto', '', [interface1])
219     cfg = Config(maconfig)
220     cfg.read_write()
221     owner = cfg.cfgimpl_get_settings().getowner()
222     assert interface1.impl_get_group_type() == groups.master
223     assert cfg.getowner(ip_admin_eth0) == owners.default
224     assert cfg.getowner(netmask_admin_eth0) == owners.default
225     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
226     assert cfg.getowner(ip_admin_eth0) == owner
227     assert cfg.getowner(netmask_admin_eth0) == owners.default
228     del(cfg.ip_admin_eth0.ip_admin_eth0)
229     assert cfg.getowner(ip_admin_eth0) == owners.default
230     assert cfg.getowner(netmask_admin_eth0) == owners.default
231     assert cfg.ip_admin_eth0.ip_admin_eth0 == []
232     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
233
234
235 def test_values_with_master_and_slaves_slave():
236     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
237     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
238     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
239     interface1.impl_set_group_type(groups.master)
240     maconfig = OptionDescription('toto', '', [interface1])
241     cfg = Config(maconfig)
242     cfg.read_write()
243     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
244     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
245     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
246     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']
247     cfg.ip_admin_eth0.netmask_admin_eth0[0] = '255.255.255.0'
248     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']")
249     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = []")
250     del(cfg.ip_admin_eth0.netmask_admin_eth0)
251     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']
252     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
253     assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0', None]
254     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
255     raises(SlaveError, 'cfg.ip_admin_eth0.netmask_admin_eth0.pop(1)')
256
257
258 def test_values_with_master_and_slaves_master():
259     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
260     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
261     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
262     interface1.impl_set_group_type(groups.master)
263     maconfig = OptionDescription('toto', '', [interface1])
264     cfg = Config(maconfig)
265     cfg.read_write()
266     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
267     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]
268     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
269     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
270     raises(SlaveError, 'cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]')
271     assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0', '255.255.255.0']
272     cfg.ip_admin_eth0.ip_admin_eth0.pop(1)
273     assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
274     assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0']
275     del(cfg.ip_admin_eth0.ip_admin_eth0)
276     assert cfg.ip_admin_eth0.ip_admin_eth0 == []
277     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
278
279
280 def test_values_with_master_and_slaves_master_error():
281     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
282     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
283     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
284     interface1.impl_set_group_type(groups.master)
285     maconfig = OptionDescription('toto', '', [interface1])
286     cfg = Config(maconfig)
287     cfg.read_write()
288     cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
289     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
290     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0', '255.255.255.0']")
291     cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
292     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
293     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0', '255.255.255.0']")
294
295
296 def test_values_with_master_owner():
297     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
298     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
299     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
300     interface1.impl_set_group_type(groups.master)
301     maconfig = OptionDescription('toto', '', [interface1])
302     cfg = Config(maconfig)
303     cfg.read_write()
304     owner = cfg.cfgimpl_get_settings().getowner()
305     assert cfg.getowner(ip_admin_eth0) == owners.default
306     assert cfg.getowner(netmask_admin_eth0) == owners.default
307     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
308     assert cfg.getowner(ip_admin_eth0) == owner
309     assert cfg.getowner(netmask_admin_eth0) == owners.default
310     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
311     assert cfg.getowner(ip_admin_eth0) == owner
312     assert cfg.getowner(netmask_admin_eth0) == owners.default
313
314
315 def test_values_with_master_disabled():
316     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
317     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
318     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
319     interface1.impl_set_group_type(groups.master)
320     maconfig = OptionDescription('toto', '', [interface1])
321     cfg = Config(maconfig)
322     cfg.read_write()
323     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
324     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
325     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
326     cfg.ip_admin_eth0.netmask_admin_eth0 = ["192.168.230.145"]
327     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
328     del(cfg.ip_admin_eth0.netmask_admin_eth0)
329     cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
330     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
331     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
332
333     #delete with value in disabled var
334     cfg.cfgimpl_get_settings()[netmask_admin_eth0].remove('disabled')
335     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
336     cfg.ip_admin_eth0.netmask_admin_eth0 = ["192.168.230.145"]
337     cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
338     cfg.ip_admin_eth0.ip_admin_eth0.pop(0)
339
340     #append with value in disabled var
341     cfg.cfgimpl_get_settings()[netmask_admin_eth0].remove('disabled')
342     cfg.ip_admin_eth0.ip_admin_eth0.append("192.168.230.145")
343     cfg.ip_admin_eth0.netmask_admin_eth0 = ["192.168.230.145"]
344     cfg.cfgimpl_get_settings()[netmask_admin_eth0].append('disabled')
345     cfg.ip_admin_eth0.ip_admin_eth0.append('192.168.230.43')
346
347
348 def test_multi_insert():
349     var = StrOption('var', '', ['ok'], multi=True)
350     od = OptionDescription('od', '', [var])
351     c = Config(od)
352     c.read_write()
353     assert c.var == ['ok']
354     assert c.getowner(var) == owners.default
355     c.var.insert(0, 'nok')
356     assert c.var == ['nok', 'ok']
357     assert c.getowner(var) != owners.default
358     raises(ValueError, 'c.var.insert(0, 1)')
359
360
361 def test_multi_insert_master():
362     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
363     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
364     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
365     interface1.impl_set_group_type(groups.master)
366     maconfig = OptionDescription('toto', '', [interface1])
367     cfg = Config(maconfig)
368     cfg.read_write()
369     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.insert(0, 'nok')")
370     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.insert(0, 'nok')")
371
372
373 def test_multi_sort():
374     var = StrOption('var', '', ['ok', 'nok'], multi=True)
375     od = OptionDescription('od', '', [var])
376     c = Config(od)
377     c.read_write()
378     assert c.var == ['ok', 'nok']
379     assert c.getowner(var) == owners.default
380     c.var.sort()
381     assert c.var == ['nok', 'ok']
382     assert c.getowner(var) != owners.default
383
384
385 def test_multi_sort_master():
386     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
387     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
388     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
389     interface1.impl_set_group_type(groups.master)
390     maconfig = OptionDescription('toto', '', [interface1])
391     cfg = Config(maconfig)
392     cfg.read_write()
393     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.sort()")
394     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.sort()")
395
396
397 def test_multi_reverse():
398     var = StrOption('var', '', ['ok', 'nok'], multi=True)
399     od = OptionDescription('od', '', [var])
400     c = Config(od)
401     c.read_write()
402     assert c.var == ['ok', 'nok']
403     assert c.getowner(var) == owners.default
404     c.var.reverse()
405     assert c.var == ['nok', 'ok']
406     assert c.getowner(var) != owners.default
407
408
409 def test_multi_reverse_master():
410     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
411     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
412     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
413     interface1.impl_set_group_type(groups.master)
414     maconfig = OptionDescription('toto', '', [interface1])
415     cfg = Config(maconfig)
416     cfg.read_write()
417     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.reverse()")
418     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.reverse()")
419
420
421 def test_multi_extend():
422     var = StrOption('var', '', ['ok', 'nok'], multi=True)
423     od = OptionDescription('od', '', [var])
424     c = Config(od)
425     c.read_write()
426     assert c.var == ['ok', 'nok']
427     assert c.getowner(var) == owners.default
428     c.var.extend(['pok'])
429     assert c.var == ['ok', 'nok', 'pok']
430     assert c.getowner(var) != owners.default
431     raises(ValueError, 'c.var.extend([1])')
432
433
434 def test_multi_extend_master():
435     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
436     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
437     interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
438     interface1.impl_set_group_type(groups.master)
439     maconfig = OptionDescription('toto', '', [interface1])
440     cfg = Config(maconfig)
441     cfg.read_write()
442     raises(SlaveError, "cfg.ip_admin_eth0.ip_admin_eth0.extend(['ok'])")
443     raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0.extend(['ok'])")
444
445
446 def test_multi_non_valid_value():
447     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
448     maconfig = OptionDescription('toto', '', [ip_admin_eth0])
449     cfg = Config(maconfig)
450     cfg.read_write()
451     cfg.ip_admin_eth0 = ['a']
452     raises(ValueError, 'cfg.ip_admin_eth0[0] = 1')