diff --git a/doc/service/ip.md b/doc/service/ip.md
index bc39c1c7..ebebf738 100644
--- a/doc/service/ip.md
+++ b/doc/service/ip.md
@@ -6,59 +6,21 @@ La gestion des IP se fait dans un conteneur de [service](service.md).
La déclaration de l'attribut permet d'associer une IP autorisé à accéder au service.
-Il est nécessaire, au minimum, de spécifier son adresse IP et l'interface :
+Il est nécessaire, au minimum, de spécifier le nom d'une variable de type "IP" :
```
-192.168.0.1
+variable_ip
```
-L'IP peut être un variable :
-
-```
-variable_ip
-```
-
-Attention, la variable doit être de type "network".
-
## La gestion d'un réseau
-L'adresse IP peut être un réseau :
+L'adresse peut être de type réseau ("network") :
```
-192.168.0.0
+variable_ip
```
-Le masque de réseau peut être un variable :
-
-```
-variable_ip
-```
-
-Attention, la variable doit être de type "netmask".
-
-## L'interface
-
-Il est possible de spécifier le nom de l'interface si on la connait :
-
-```
-192.168.0.1
-```
-
-Mais il est possible de calculer automatiquement cette valeur :
-
-```
-192.168.0.1
-```
-
-Dans ce cas l'interface est déduite à partir de la table de routage.
-
-L'interface peut être un variable :
-
-```
-192.168.0.1
-```
-
-Attention, la variable doit être de type "string".
+Attention, dans ce cas il faut préciser une variable de type "netmask" dans l'attribut netmask.
## Désactiver la génération d'une IP
@@ -67,11 +29,12 @@ Il est possible de définir une [condition](../condition/README.md) de type "dis
```
- 192.168.0.1
+ variable_ip
+
diff --git a/src/rougail/annotator/service.py b/src/rougail/annotator/service.py
index 5edce2d6..920b01df 100644
--- a/src/rougail/annotator/service.py
+++ b/src/rougail/annotator/service.py
@@ -202,10 +202,10 @@ class ServiceAnnotator:
if type_ == 'symlink':
variable.opt = self.objectspace.paths.get_variable(value)
variable.multi = None
- if self.objectspace.types[dtd_key_type] != 'variable' and \
- variable.opt.type != self.objectspace.types[dtd_key_type]:
- msg = _(f'"{key}" in "{elttype}" must be a variable with type '
- f'"{self.objectspace.types[dtd_key_type]}" not "{variable.opt.type}"')
+ needed_type = self.objectspace.types[dtd_key_type]
+ if needed_type != 'variable' and variable.opt.type != needed_type:
+ msg = _(f'"{value}" in "{elttype}" must be a variable with type '
+ f'"{needed_type}" not "{variable.opt.type}"')
raise DictConsistencyError(msg, 58, elt.xmlfiles)
else:
@@ -245,3 +245,20 @@ class ServiceAnnotator:
msg = _(f'attribute "source" is mandatory for the file "{file_.name}" '
f'"({service_name})"')
raise DictConsistencyError(msg, 34, file_.xmlfiles)
+
+ def _update_ip(self,
+ ip,
+ service_name,
+ ) -> None:
+ variable = self.objectspace.paths.get_variable(ip.name)
+ if variable.type in ['ip', 'network_cidr'] and hasattr(ip, 'netmask'):
+ msg = _(f'ip with ip_type "{variable.type}" must not have netmask')
+ raise DictConsistencyError(msg, 59, ip.xmlfiles)
+ if variable.type == 'network' and not hasattr(ip, 'netmask'):
+ msg = _(f'ip with ip_type "{variable.type}" must have netmask')
+ raise DictConsistencyError(msg, 64, ip.xmlfiles)
+ if hasattr(ip, 'netmask'):
+ netmask = self.objectspace.paths.get_variable(ip.netmask)
+ if netmask.type != 'netmask':
+ msg = _(f'netmask in ip must have type "netmask", not "{netmask.type}"')
+ raise DictConsistencyError(msg, 65, ip.xmlfiles)
diff --git a/src/rougail/data/rougail.dtd b/src/rougail/data/rougail.dtd
index 39004cc3..2a050556 100644
--- a/src/rougail/data/rougail.dtd
+++ b/src/rougail/data/rougail.dtd
@@ -56,11 +56,9 @@
-
-
-
-
-
+
+
+
diff --git a/tests/dictionaries/70container_pathaccess_leadership/makedict/base.json b/tests/dictionaries/70container_pathaccess_leadership/makedict/base.json
deleted file mode 100644
index 1938aa84..00000000
--- a/tests/dictionaries/70container_pathaccess_leadership/makedict/base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"rougail.general.mode_conteneur_actif": "oui", "rougail.general.nut_monitor_netmask.nut_monitor_netmask": [], "services.ntp.ips.nut_monitor_host.interface": "auto", "services.ntp.ips.nut_monitor_host.name": [], "services.ntp.ips.nut_monitor_host.netmask": [], "services.ntp.ips.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70container_servicerestriction/00-base.xml b/tests/dictionaries/70container_servicerestriction/00-base.xml
deleted file mode 100644
index 4a45f66c..00000000
--- a/tests/dictionaries/70container_servicerestriction/00-base.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
- 192.168.1.1
-
-
-
-
-
-
- oui
-
-
-
-
-
diff --git a/tests/dictionaries/70container_servicerestriction/makedict/base.json b/tests/dictionaries/70container_servicerestriction/makedict/base.json
deleted file mode 100644
index 0486314a..00000000
--- a/tests/dictionaries/70container_servicerestriction/makedict/base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"rougail.general.mode_conteneur_actif": "oui", "services.testsrv.ips.192_168_1_1.interface": "eth0", "services.testsrv.ips.192_168_1_1.name": "192.168.1.1", "services.testsrv.ips.192_168_1_1.netmask": "255.255.255.255", "services.testsrv.ips.192_168_1_1.activate": true}
diff --git a/tests/dictionaries/70services_ip/00-base.xml b/tests/dictionaries/70services_ip/00-base.xml
new file mode 100644
index 00000000..4fc371a1
--- /dev/null
+++ b/tests/dictionaries/70services_ip/00-base.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ nut_monitor_host
+
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/70container_pathaccess_leadership/__init__.py b/tests/dictionaries/70services_ip/__init__.py
similarity index 100%
rename from tests/dictionaries/70container_pathaccess_leadership/__init__.py
rename to tests/dictionaries/70services_ip/__init__.py
diff --git a/tests/dictionaries/70services_ip/makedict/base.json b/tests/dictionaries/70services_ip/makedict/base.json
new file mode 100644
index 00000000..70cac6d9
--- /dev/null
+++ b/tests/dictionaries/70services_ip/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_pathaccess_iplist/tiramisu/base.py b/tests/dictionaries/70services_ip/tiramisu/base.py
similarity index 56%
rename from tests/dictionaries/70services_pathaccess_iplist/tiramisu/base.py
rename to tests/dictionaries/70services_ip/tiramisu/base.py
index 33279fa5..41afb692 100644
--- a/tests/dictionaries/70services_pathaccess_iplist/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip/tiramisu/base.py
@@ -11,13 +11,11 @@ try:
from tiramisu3 import *
except:
from tiramisu import *
-option_2 = StrOption(name="condition", doc="condition", default="no", properties=frozenset({"mandatory", "normal"}))
+option_2 = IPOption(name="nut_monitor_host", doc="nut_monitor_host", allow_reserved=True, properties=frozenset({"mandatory", "normal"}))
option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
-option_7 = StrOption(name="interface", doc="interface", default="auto")
-option_8 = NetworkOption(name="name", doc="name", default="192.168.0.1")
-option_9 = NetmaskOption(name="netmask", doc="netmask", default="255.255.255.255")
-option_10 = BoolOption(name="activate", doc="activate", default=Calculation(func.calc_value, Params((ParamValue(False)), kwargs={'default': ParamValue(True), 'condition_0': ParamOption(option_2), 'expected_0': ParamValue("yes")})))
-option_6 = OptionDescription(name="192_168_0_1", doc="192.168.0.1", children=[option_7, option_8, option_9, option_10])
+option_7 = SymLinkOption(name="name", opt=option_2)
+option_8 = BoolOption(name="activate", doc="activate", default=True)
+option_6 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_7, option_8])
option_5 = OptionDescription(name="ips", doc="ips", children=[option_6])
option_4 = OptionDescription(name="nut", doc="nut", children=[option_5])
option_3 = OptionDescription(name="services", doc="services", children=[option_4], properties=frozenset({"hidden"}))
diff --git a/tests/dictionaries/70services_ip_cidr/00-base.xml b/tests/dictionaries/70services_ip_cidr/00-base.xml
new file mode 100644
index 00000000..2ff97246
--- /dev/null
+++ b/tests/dictionaries/70services_ip_cidr/00-base.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ nut_monitor_host
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/70container_servicerestriction/__init__.py b/tests/dictionaries/70services_ip_cidr/__init__.py
similarity index 100%
rename from tests/dictionaries/70container_servicerestriction/__init__.py
rename to tests/dictionaries/70services_ip_cidr/__init__.py
diff --git a/tests/dictionaries/70services_ip_cidr/makedict/base.json b/tests/dictionaries/70services_ip_cidr/makedict/base.json
new file mode 100644
index 00000000..70cac6d9
--- /dev/null
+++ b/tests/dictionaries/70services_ip_cidr/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_pathaccess_iplist2/tiramisu/base.py b/tests/dictionaries/70services_ip_cidr/tiramisu/base.py
similarity index 56%
rename from tests/dictionaries/70services_pathaccess_iplist2/tiramisu/base.py
rename to tests/dictionaries/70services_ip_cidr/tiramisu/base.py
index 7fa0f814..72bd1ad2 100644
--- a/tests/dictionaries/70services_pathaccess_iplist2/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_cidr/tiramisu/base.py
@@ -11,13 +11,11 @@ try:
from tiramisu3 import *
except:
from tiramisu import *
-option_2 = StrOption(name="condition", doc="condition", default="yes", properties=frozenset({"mandatory", "normal"}))
+option_2 = NetworkOption(name="nut_monitor_host", doc="nut_monitor_host", cidr=True, properties=frozenset({"mandatory", "normal"}))
option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
-option_7 = StrOption(name="interface", doc="interface", default="auto")
-option_8 = NetworkOption(name="name", doc="name", default="192.168.0.1")
-option_9 = NetmaskOption(name="netmask", doc="netmask", default="255.255.255.255")
-option_10 = BoolOption(name="activate", doc="activate", default=Calculation(func.calc_value, Params((ParamValue(False)), kwargs={'default': ParamValue(True), 'condition_0': ParamOption(option_2), 'expected_0': ParamValue("yes")})))
-option_6 = OptionDescription(name="192_168_0_1", doc="192.168.0.1", children=[option_7, option_8, option_9, option_10])
+option_7 = SymLinkOption(name="name", opt=option_2)
+option_8 = BoolOption(name="activate", doc="activate", default=True)
+option_6 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_7, option_8])
option_5 = OptionDescription(name="ips", doc="ips", children=[option_6])
option_4 = OptionDescription(name="nut", doc="nut", children=[option_5])
option_3 = OptionDescription(name="services", doc="services", children=[option_4], properties=frozenset({"hidden"}))
diff --git a/tests/dictionaries/70services_pathaccess_iplist/00-base.xml b/tests/dictionaries/70services_ip_iplist/00-base.xml
similarity index 73%
rename from tests/dictionaries/70services_pathaccess_iplist/00-base.xml
rename to tests/dictionaries/70services_ip_iplist/00-base.xml
index 48943c2a..532bdd3f 100644
--- a/tests/dictionaries/70services_pathaccess_iplist/00-base.xml
+++ b/tests/dictionaries/70services_ip_iplist/00-base.xml
@@ -3,19 +3,21 @@
- 192.168.0.1
+ nut_monitor_host
no
+
yes
example
+ nut_monitor_host
diff --git a/tests/dictionaries/70services_pathaccess/__init__.py b/tests/dictionaries/70services_ip_iplist/__init__.py
similarity index 100%
rename from tests/dictionaries/70services_pathaccess/__init__.py
rename to tests/dictionaries/70services_ip_iplist/__init__.py
diff --git a/tests/dictionaries/70services_ip_iplist/makedict/base.json b/tests/dictionaries/70services_ip_iplist/makedict/base.json
new file mode 100644
index 00000000..9c080564
--- /dev/null
+++ b/tests/dictionaries/70services_ip_iplist/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.condition": "no", "rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_ip_iplist/tiramisu/base.py b/tests/dictionaries/70services_ip_iplist/tiramisu/base.py
new file mode 100644
index 00000000..b8cd6e44
--- /dev/null
+++ b/tests/dictionaries/70services_ip_iplist/tiramisu/base.py
@@ -0,0 +1,23 @@
+from importlib.machinery import SourceFileLoader
+from importlib.util import spec_from_loader, module_from_spec
+loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py')
+spec = spec_from_loader(loader.name, loader)
+func = module_from_spec(spec)
+loader.exec_module(func)
+for key, value in dict(locals()).items():
+ if key != ['SourceFileLoader', 'func']:
+ setattr(func, key, value)
+try:
+ from tiramisu3 import *
+except:
+ from tiramisu import *
+option_2 = StrOption(name="condition", doc="condition", default="no", properties=frozenset({"mandatory", "normal"}))
+option_3 = NetworkOption(name="nut_monitor_host", doc="nut_monitor_host", cidr=True, properties=frozenset({"mandatory", "normal", Calculation(func.calc_value, Params(ParamValue('disabled'), kwargs={'condition': ParamOption(option_2, todict=True), 'expected': ParamValue("yes")}))}))
+option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2, option_3])
+option_8 = SymLinkOption(name="name", opt=option_3)
+option_9 = BoolOption(name="activate", doc="activate", default=Calculation(func.calc_value, Params((ParamValue(False)), kwargs={'default': ParamValue(True), 'condition_0': ParamOption(option_2), 'expected_0': ParamValue("yes")})))
+option_7 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_8, option_9])
+option_6 = OptionDescription(name="ips", doc="ips", children=[option_7])
+option_5 = OptionDescription(name="nut", doc="nut", children=[option_6])
+option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"}))
+option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4])
diff --git a/tests/dictionaries/70services_pathaccess_iplist2/00-base.xml b/tests/dictionaries/70services_ip_iplist2/00-base.xml
similarity index 78%
rename from tests/dictionaries/70services_pathaccess_iplist2/00-base.xml
rename to tests/dictionaries/70services_ip_iplist2/00-base.xml
index d1877d36..00e744fa 100644
--- a/tests/dictionaries/70services_pathaccess_iplist2/00-base.xml
+++ b/tests/dictionaries/70services_ip_iplist2/00-base.xml
@@ -3,13 +3,14 @@
- 192.168.0.1
+ nut_monitor_host
yes
+
diff --git a/tests/dictionaries/70services_pathaccess_iplist/__init__.py b/tests/dictionaries/70services_ip_iplist2/__init__.py
similarity index 100%
rename from tests/dictionaries/70services_pathaccess_iplist/__init__.py
rename to tests/dictionaries/70services_ip_iplist2/__init__.py
diff --git a/tests/dictionaries/70services_ip_iplist2/makedict/base.json b/tests/dictionaries/70services_ip_iplist2/makedict/base.json
new file mode 100644
index 00000000..1f7016ff
--- /dev/null
+++ b/tests/dictionaries/70services_ip_iplist2/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.condition": "yes", "rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.activate": false}
diff --git a/tests/dictionaries/70services_ip_iplist2/tiramisu/base.py b/tests/dictionaries/70services_ip_iplist2/tiramisu/base.py
new file mode 100644
index 00000000..5133ea27
--- /dev/null
+++ b/tests/dictionaries/70services_ip_iplist2/tiramisu/base.py
@@ -0,0 +1,23 @@
+from importlib.machinery import SourceFileLoader
+from importlib.util import spec_from_loader, module_from_spec
+loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py')
+spec = spec_from_loader(loader.name, loader)
+func = module_from_spec(spec)
+loader.exec_module(func)
+for key, value in dict(locals()).items():
+ if key != ['SourceFileLoader', 'func']:
+ setattr(func, key, value)
+try:
+ from tiramisu3 import *
+except:
+ from tiramisu import *
+option_2 = StrOption(name="condition", doc="condition", default="yes", properties=frozenset({"mandatory", "normal"}))
+option_3 = NetworkOption(name="nut_monitor_host", doc="nut_monitor_host", cidr=True, properties=frozenset({"mandatory", "normal"}))
+option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2, option_3])
+option_8 = SymLinkOption(name="name", opt=option_3)
+option_9 = BoolOption(name="activate", doc="activate", default=Calculation(func.calc_value, Params((ParamValue(False)), kwargs={'default': ParamValue(True), 'condition_0': ParamOption(option_2), 'expected_0': ParamValue("yes")})))
+option_7 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_8, option_9])
+option_6 = OptionDescription(name="ips", doc="ips", children=[option_7])
+option_5 = OptionDescription(name="nut", doc="nut", children=[option_6])
+option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"}))
+option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4])
diff --git a/tests/dictionaries/70container_pathaccess_leadership/00-base.xml b/tests/dictionaries/70services_ip_leadership/00-base.xml
similarity index 86%
rename from tests/dictionaries/70container_pathaccess_leadership/00-base.xml
rename to tests/dictionaries/70services_ip_leadership/00-base.xml
index 394ce7d8..794890a5 100644
--- a/tests/dictionaries/70container_pathaccess_leadership/00-base.xml
+++ b/tests/dictionaries/70services_ip_leadership/00-base.xml
@@ -4,7 +4,7 @@
- nut_monitor_host
+ nut_monitor_host
diff --git a/tests/dictionaries/70services_pathaccess_iplist2/__init__.py b/tests/dictionaries/70services_ip_leadership/__init__.py
similarity index 100%
rename from tests/dictionaries/70services_pathaccess_iplist2/__init__.py
rename to tests/dictionaries/70services_ip_leadership/__init__.py
diff --git a/tests/dictionaries/70services_ip_leadership/makedict/base.json b/tests/dictionaries/70services_ip_leadership/makedict/base.json
new file mode 100644
index 00000000..0a17121a
--- /dev/null
+++ b/tests/dictionaries/70services_ip_leadership/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.general.mode_conteneur_actif": "oui", "rougail.general.nut_monitor_netmask.nut_monitor_netmask": [], "services.ntp.ips.nut_monitor_host.name": [], "services.ntp.ips.nut_monitor_host.netmask": [], "services.ntp.ips.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70container_pathaccess_leadership/tiramisu/base.py b/tests/dictionaries/70services_ip_leadership/tiramisu/base.py
similarity index 84%
rename from tests/dictionaries/70container_pathaccess_leadership/tiramisu/base.py
rename to tests/dictionaries/70services_ip_leadership/tiramisu/base.py
index bc79dc40..c8398af0 100644
--- a/tests/dictionaries/70container_pathaccess_leadership/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_leadership/tiramisu/base.py
@@ -17,11 +17,10 @@ option_6 = NetworkOption(name="nut_monitor_host", doc="Adresse IP du réseau de
option_4 = Leadership(name="nut_monitor_netmask", doc="Masque de l'IP du réseau de l'esclave", children=[option_5, option_6], properties=frozenset({"basic"}))
option_2 = OptionDescription(name="general", doc="général", children=[option_3, option_4], properties=frozenset({"basic"}))
option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
-option_11 = StrOption(name="interface", doc="interface", default="auto")
-option_12 = SymLinkOption(name="name", opt=option_6)
-option_13 = SymLinkOption(name="netmask", opt=option_5)
-option_14 = BoolOption(name="activate", doc="activate", default=True)
-option_10 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_11, option_12, option_13, option_14])
+option_11 = SymLinkOption(name="name", opt=option_6)
+option_12 = SymLinkOption(name="netmask", opt=option_5)
+option_13 = BoolOption(name="activate", doc="activate", default=True)
+option_10 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_11, option_12, option_13])
option_9 = OptionDescription(name="ips", doc="ips", children=[option_10])
option_8 = OptionDescription(name="ntp", doc="ntp", children=[option_9])
option_7 = OptionDescription(name="services", doc="services", children=[option_8], properties=frozenset({"hidden"}))
diff --git a/tests/dictionaries/70services_ip_network/00-base.xml b/tests/dictionaries/70services_ip_network/00-base.xml
new file mode 100644
index 00000000..8057b3d3
--- /dev/null
+++ b/tests/dictionaries/70services_ip_network/00-base.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ nut_monitor_host
+
+
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/70services_ip_network/__init__.py b/tests/dictionaries/70services_ip_network/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/70services_ip_network/makedict/base.json b/tests/dictionaries/70services_ip_network/makedict/base.json
new file mode 100644
index 00000000..5300cf33
--- /dev/null
+++ b/tests/dictionaries/70services_ip_network/makedict/base.json
@@ -0,0 +1 @@
+{"rougail.nut_monitor_netmask": null, "rougail.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.netmask": null, "services.nut.ips.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70container_servicerestriction/tiramisu/base.py b/tests/dictionaries/70services_ip_network/tiramisu/base.py
similarity index 50%
rename from tests/dictionaries/70container_servicerestriction/tiramisu/base.py
rename to tests/dictionaries/70services_ip_network/tiramisu/base.py
index 65924846..a3c397a8 100644
--- a/tests/dictionaries/70container_servicerestriction/tiramisu/base.py
+++ b/tests/dictionaries/70services_ip_network/tiramisu/base.py
@@ -11,15 +11,14 @@ try:
from tiramisu3 import *
except:
from tiramisu import *
-option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"}))
-option_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"normal"}))
-option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
-option_8 = StrOption(name="interface", doc="interface", default="eth0")
-option_9 = NetworkOption(name="name", doc="name", default="192.168.1.1")
-option_10 = NetmaskOption(name="netmask", doc="netmask", default="255.255.255.255")
-option_11 = BoolOption(name="activate", doc="activate", default=True)
-option_7 = OptionDescription(name="192_168_1_1", doc="192.168.1.1", children=[option_8, option_9, option_10, option_11])
+option_2 = NetmaskOption(name="nut_monitor_netmask", doc="nut_monitor_netmask", properties=frozenset({"mandatory", "normal"}))
+option_3 = NetworkOption(name="nut_monitor_host", doc="nut_monitor_host", properties=frozenset({"mandatory", "normal"}))
+option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2, option_3])
+option_8 = SymLinkOption(name="name", opt=option_3)
+option_9 = SymLinkOption(name="netmask", opt=option_2)
+option_10 = BoolOption(name="activate", doc="activate", default=True)
+option_7 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_8, option_9, option_10])
option_6 = OptionDescription(name="ips", doc="ips", children=[option_7])
-option_5 = OptionDescription(name="testsrv", doc="testsrv", children=[option_6])
+option_5 = OptionDescription(name="nut", doc="nut", children=[option_6])
option_4 = OptionDescription(name="services", doc="services", children=[option_5], properties=frozenset({"hidden"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_4])
diff --git a/tests/dictionaries/70services_pathaccess/00-base.xml b/tests/dictionaries/70services_pathaccess/00-base.xml
deleted file mode 100644
index db76b27d..00000000
--- a/tests/dictionaries/70services_pathaccess/00-base.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
- nut_monitor_host
-
-
-
-
-
-
- oui
-
-
-
-
-
-
-
diff --git a/tests/dictionaries/70services_pathaccess/makedict/base.json b/tests/dictionaries/70services_pathaccess/makedict/base.json
deleted file mode 100644
index e209812c..00000000
--- a/tests/dictionaries/70services_pathaccess/makedict/base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"rougail.general.mode_conteneur_actif": "oui", "rougail.general.nut_monitor_netmask": null, "rougail.general.nut_monitor_host": null, "services.nut.ips.nut_monitor_host.interface": "auto", "services.nut.ips.nut_monitor_host.name": null, "services.nut.ips.nut_monitor_host.netmask": null, "services.nut.ips.nut_monitor_host.activate": true}
diff --git a/tests/dictionaries/70services_pathaccess/tiramisu/base.py b/tests/dictionaries/70services_pathaccess/tiramisu/base.py
deleted file mode 100644
index 436088a9..00000000
--- a/tests/dictionaries/70services_pathaccess/tiramisu/base.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from importlib.machinery import SourceFileLoader
-from importlib.util import spec_from_loader, module_from_spec
-loader = SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py')
-spec = spec_from_loader(loader.name, loader)
-func = module_from_spec(spec)
-loader.exec_module(func)
-for key, value in dict(locals()).items():
- if key != ['SourceFileLoader', 'func']:
- setattr(func, key, value)
-try:
- from tiramisu3 import *
-except:
- from tiramisu import *
-option_3 = StrOption(name="mode_conteneur_actif", doc="No change", default="oui", properties=frozenset({"force_default_on_freeze", "frozen", "hidden", "mandatory", "normal"}))
-option_4 = NetmaskOption(name="nut_monitor_netmask", doc="Masque de l'IP du réseau de l'esclave", properties=frozenset({"basic", "mandatory"}))
-option_5 = NetworkOption(name="nut_monitor_host", doc="Adresse IP du réseau de l'esclave", properties=frozenset({"basic", "mandatory"}))
-option_2 = OptionDescription(name="general", doc="général", children=[option_3, option_4, option_5], properties=frozenset({"basic"}))
-option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
-option_10 = StrOption(name="interface", doc="interface", default="auto")
-option_11 = SymLinkOption(name="name", opt=option_5)
-option_12 = SymLinkOption(name="netmask", opt=option_4)
-option_13 = BoolOption(name="activate", doc="activate", default=True)
-option_9 = OptionDescription(name="nut_monitor_host", doc="nut_monitor_host", children=[option_10, option_11, option_12, option_13])
-option_8 = OptionDescription(name="ips", doc="ips", children=[option_9])
-option_7 = OptionDescription(name="nut", doc="nut", children=[option_8])
-option_6 = OptionDescription(name="services", doc="services", children=[option_7], properties=frozenset({"hidden"}))
-option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_6])
diff --git a/tests/dictionaries/70services_pathaccess_iplist/makedict/base.json b/tests/dictionaries/70services_pathaccess_iplist/makedict/base.json
deleted file mode 100644
index 5b00283a..00000000
--- a/tests/dictionaries/70services_pathaccess_iplist/makedict/base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"rougail.condition": "no", "services.nut.ips.192_168_0_1.interface": "auto", "services.nut.ips.192_168_0_1.name": "192.168.0.1", "services.nut.ips.192_168_0_1.netmask": "255.255.255.255", "services.nut.ips.192_168_0_1.activate": true}
diff --git a/tests/dictionaries/70services_pathaccess_iplist2/makedict/base.json b/tests/dictionaries/70services_pathaccess_iplist2/makedict/base.json
deleted file mode 100644
index ebec540a..00000000
--- a/tests/dictionaries/70services_pathaccess_iplist2/makedict/base.json
+++ /dev/null
@@ -1 +0,0 @@
-{"rougail.condition": "yes", "services.nut.ips.192_168_0_1.interface": "auto", "services.nut.ips.192_168_0_1.name": "192.168.0.1", "services.nut.ips.192_168_0_1.netmask": "255.255.255.255", "services.nut.ips.192_168_0_1.activate": false}
diff --git a/tests/dictionaries/80services_ip_cidr_netmask/00-base.xml b/tests/dictionaries/80services_ip_cidr_netmask/00-base.xml
new file mode 100644
index 00000000..538e7bee
--- /dev/null
+++ b/tests/dictionaries/80services_ip_cidr_netmask/00-base.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ nut_monitor_host
+
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/80services_ip_cidr_netmask/__init__.py b/tests/dictionaries/80services_ip_cidr_netmask/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80services_ip_cidr_netmask/errno_59 b/tests/dictionaries/80services_ip_cidr_netmask/errno_59
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80services_ip_netmask/00-base.xml b/tests/dictionaries/80services_ip_netmask/00-base.xml
new file mode 100644
index 00000000..5b5a7a71
--- /dev/null
+++ b/tests/dictionaries/80services_ip_netmask/00-base.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ nut_monitor_host
+
+
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/80services_ip_netmask/__init__.py b/tests/dictionaries/80services_ip_netmask/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80services_ip_netmask/errno_59 b/tests/dictionaries/80services_ip_netmask/errno_59
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80services_ip_network_no_netmask/00-base.xml b/tests/dictionaries/80services_ip_network_no_netmask/00-base.xml
new file mode 100644
index 00000000..3cdd5971
--- /dev/null
+++ b/tests/dictionaries/80services_ip_network_no_netmask/00-base.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ nut_monitor_host
+
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/80services_ip_network_no_netmask/__init__.py b/tests/dictionaries/80services_ip_network_no_netmask/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80services_ip_network_no_netmask/errno_64 b/tests/dictionaries/80services_ip_network_no_netmask/errno_64
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80services_ip_not_netmask/00-base.xml b/tests/dictionaries/80services_ip_not_netmask/00-base.xml
new file mode 100644
index 00000000..8a6c7f86
--- /dev/null
+++ b/tests/dictionaries/80services_ip_not_netmask/00-base.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ nut_monitor_host
+
+
+
+
+
+
+
+
+
diff --git a/tests/dictionaries/80services_ip_not_netmask/__init__.py b/tests/dictionaries/80services_ip_not_netmask/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/dictionaries/80services_ip_not_netmask/errno_65 b/tests/dictionaries/80services_ip_not_netmask/errno_65
new file mode 100644
index 00000000..e69de29b