ifstate 1.13.6__py3-none-any.whl → 2.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- hooks/wrapper.sh +50 -0
- ifstate/ifstate.py +7 -2
- ifstate/vrrp.py +1 -1
- {ifstate-1.13.6.dist-info → ifstate-2.0.0rc1.dist-info}/METADATA +1 -1
- ifstate-2.0.0rc1.dist-info/RECORD +38 -0
- {ifstate-1.13.6.dist-info → ifstate-2.0.0rc1.dist-info}/WHEEL +1 -1
- libifstate/__init__.py +93 -41
- libifstate/hook/__init__.py +195 -0
- libifstate/link/__init__.py +0 -1
- libifstate/link/base.py +34 -36
- libifstate/link/physical.py +2 -2
- libifstate/link/tun.py +2 -2
- libifstate/link/veth.py +2 -2
- libifstate/netns/__init__.py +49 -13
- libifstate/parser/base.py +107 -84
- libifstate/routing/__init__.py +233 -113
- libifstate/util.py +146 -147
- libifstate/wireguard/__init__.py +16 -16
- schema/2/ifstate.conf.schema.json +4398 -0
- ifstate-1.13.6.dist-info/RECORD +0 -37
- libifstate/link/dsa.py +0 -10
- schema/ifstate.conf.schema.json +0 -4259
- {ifstate-1.13.6.dist-info → ifstate-2.0.0rc1.dist-info}/entry_points.txt +0 -0
- {ifstate-1.13.6.dist-info → ifstate-2.0.0rc1.dist-info}/licenses/LICENSE +0 -0
- {ifstate-1.13.6.dist-info → ifstate-2.0.0rc1.dist-info}/top_level.txt +0 -0
libifstate/link/base.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from libifstate.util import logger, IfStateLogging, LinkDependency
|
1
|
+
from libifstate.util import logger, format_ether_address, IfStateLogging, LinkDependency, IDENTIFY_LOOKUPS
|
2
2
|
from libifstate.exception import ExceptionCollector, LinkTypeUnknown, NetnsUnknown, netlinkerror_classes
|
3
3
|
from libifstate.brport import BRPort
|
4
4
|
from libifstate.routing import RTLookups
|
@@ -129,7 +129,7 @@ class Link(ABC):
|
|
129
129
|
return super().__new__(GenericLink)
|
130
130
|
#raise LinkTypeUnknown()
|
131
131
|
|
132
|
-
def __init__(self, ifstate, netns, name, link, ethtool, vrrp, brport):
|
132
|
+
def __init__(self, ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport):
|
133
133
|
self.ifstate = ifstate
|
134
134
|
self.netns = netns
|
135
135
|
self.cap_create = True
|
@@ -139,6 +139,7 @@ class Link(ABC):
|
|
139
139
|
}
|
140
140
|
self.settings.update(link)
|
141
141
|
self.ethtool = None
|
142
|
+
self.hooks = hooks
|
142
143
|
self.vrrp = vrrp
|
143
144
|
if brport:
|
144
145
|
self.brport = BRPort(netns, name, brport)
|
@@ -154,22 +155,17 @@ class Link(ABC):
|
|
154
155
|
self.link_ref = LinkDependency(name, self.netns.netns)
|
155
156
|
|
156
157
|
# prepare link registry search filters
|
157
|
-
if
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
self.settings['permaddr'] = self.settings['permaddr'].lower()
|
166
|
-
self.link_registry_search_args.append({
|
167
|
-
'kind': self.settings['kind'],
|
168
|
-
'permaddr': self.settings['permaddr'],
|
169
|
-
})
|
158
|
+
if identify:
|
159
|
+
search_args = {}
|
160
|
+
for attr in IDENTIFY_LOOKUPS.keys():
|
161
|
+
if attr in identify:
|
162
|
+
search_args[attr] = identify[attr]
|
163
|
+
if search_args:
|
164
|
+
search_args['kind'] = self.settings['kind']
|
165
|
+
self.link_registry_search_args.append(search_args)
|
170
166
|
|
171
167
|
if 'address' in self.settings and self.settings['kind'] == 'physical':
|
172
|
-
self.settings['address'] = self.settings['address']
|
168
|
+
self.settings['address'] = format_ether_address(self.settings['address'])
|
173
169
|
self.link_registry_search_args.append({
|
174
170
|
'kind': self.settings['kind'],
|
175
171
|
'address': self.settings['address'],
|
@@ -249,11 +245,8 @@ class Link(ABC):
|
|
249
245
|
return None
|
250
246
|
|
251
247
|
def get_if_attr(self, key):
|
252
|
-
if key
|
253
|
-
|
254
|
-
return self.iface[key]
|
255
|
-
else:
|
256
|
-
return None
|
248
|
+
if key == "state":
|
249
|
+
return self.iface.get(key)
|
257
250
|
|
258
251
|
if key in self.attr_map:
|
259
252
|
return self._drill_attr(self.iface, self.attr_map[key])
|
@@ -452,11 +445,17 @@ class Link(ABC):
|
|
452
445
|
netns_attr = "{}_netns".format(attr)
|
453
446
|
netnsid_attr = "{}_netnsid".format(attr)
|
454
447
|
if netns_attr in self.settings:
|
455
|
-
#
|
456
|
-
(
|
457
|
-
self.settings[
|
458
|
-
|
459
|
-
|
448
|
+
# ignore *_netns settings if the netns is the same as the interface's one
|
449
|
+
# (there is no IFLA_LINK_NETNSID attribute in such cases)
|
450
|
+
if self.settings[netns_attr] != self.netns.netns:
|
451
|
+
# ToDo: throw exception for unknown netns
|
452
|
+
(peer_ipr, peer_nsid) = self.netns.get_netnsid(self.settings[netns_attr])
|
453
|
+
self.settings[netnsid_attr] = peer_nsid
|
454
|
+
idx = next(iter(peer_ipr.link_lookup(
|
455
|
+
ifname=self.settings[attr])), None)
|
456
|
+
else:
|
457
|
+
idx = next(iter(self.netns.ipr.link_lookup(
|
458
|
+
ifname=self.settings[attr])), None)
|
460
459
|
|
461
460
|
del(self.settings[netns_attr])
|
462
461
|
else:
|
@@ -516,13 +515,6 @@ class Link(ABC):
|
|
516
515
|
if self.idx is not None:
|
517
516
|
self.iface = item.netns.ipr.get_link(self.idx)
|
518
517
|
if self.idx is not None and self.iface is not None:
|
519
|
-
permaddr = item.netns.ipr.get_permaddr(self.iface.get_attr('IFLA_IFNAME'))
|
520
|
-
if not permaddr is None:
|
521
|
-
self.iface['permaddr'] = permaddr
|
522
|
-
businfo = item.netns.ipr.get_businfo(self.iface.get_attr('IFLA_IFNAME'))
|
523
|
-
if not businfo is None:
|
524
|
-
self.iface['businfo'] = businfo
|
525
|
-
|
526
518
|
# check for ifname collisions
|
527
519
|
idx = next(iter(self.netns.ipr.link_lookup(
|
528
520
|
ifname=self.settings['ifname'])), None)
|
@@ -625,6 +617,9 @@ class Link(ABC):
|
|
625
617
|
if not isinstance(err, netlinkerror_classes):
|
626
618
|
raise
|
627
619
|
excpts.add('set', err, state=state)
|
620
|
+
|
621
|
+
# get kernel state
|
622
|
+
self.iface = self.netns.ipr.get_link(self.idx)
|
628
623
|
except Exception as err:
|
629
624
|
if not isinstance(err, netlinkerror_classes):
|
630
625
|
raise
|
@@ -737,7 +732,7 @@ class Link(ABC):
|
|
737
732
|
if do_apply:
|
738
733
|
# temp. remove special settings
|
739
734
|
skipped_settings = {}
|
740
|
-
for setting in ['state', 'peer', 'kind'
|
735
|
+
for setting in ['state', 'peer', 'kind']:
|
741
736
|
if setting in self.settings:
|
742
737
|
skipped_settings[setting] = self.settings.pop(setting)
|
743
738
|
|
@@ -832,6 +827,9 @@ class Link(ABC):
|
|
832
827
|
else:
|
833
828
|
logger.log_ok('link')
|
834
829
|
|
830
|
+
# update kernel state
|
831
|
+
self.iface = self.netns.ipr.get_link(self.idx)
|
832
|
+
|
835
833
|
def depends(self):
|
836
834
|
deps = []
|
837
835
|
|
@@ -894,5 +892,5 @@ class Link(ABC):
|
|
894
892
|
|
895
893
|
|
896
894
|
class GenericLink(Link):
|
897
|
-
def __init__(self, ifstate, netns, name, link, ethtool, vrrp, brport):
|
898
|
-
super().__init__(ifstate, netns, name, link, ethtool, vrrp, brport)
|
895
|
+
def __init__(self, ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport):
|
896
|
+
super().__init__(ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport)
|
libifstate/link/physical.py
CHANGED
@@ -3,8 +3,8 @@ from libifstate.link.base import Link
|
|
3
3
|
from libifstate.exception import LinkCannotAdd
|
4
4
|
|
5
5
|
class PhysicalLink(Link):
|
6
|
-
def __init__(self, ifstate, netns, name, link, ethtool, vrrp, brport):
|
7
|
-
super().__init__(ifstate, netns, name, link, ethtool, vrrp, brport)
|
6
|
+
def __init__(self, ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport):
|
7
|
+
super().__init__(ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport)
|
8
8
|
self.cap_create = False
|
9
9
|
self.cap_ethtool = True
|
10
10
|
self.ethtool = ethtool
|
libifstate/link/tun.py
CHANGED
@@ -6,14 +6,14 @@ from pwd import getpwnam
|
|
6
6
|
from grp import getgrnam
|
7
7
|
|
8
8
|
class TunLink(Link):
|
9
|
-
def __init__(self, ifstate, netns, name, link, ethtool, vrrp, brport):
|
9
|
+
def __init__(self, ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport):
|
10
10
|
if 'tun_owner' in link and isinstance(link['tun_owner'], str):
|
11
11
|
link['tun_owner'] = getpwnam(link['tun_owner'])[2]
|
12
12
|
|
13
13
|
if 'tun_group' in link and isinstance(link['tun_group'], str):
|
14
14
|
link['tun_group'] = getgrnam(link['tun_group'])[2]
|
15
15
|
|
16
|
-
super().__init__(ifstate, netns, name, link, ethtool, vrrp, brport)
|
16
|
+
super().__init__(ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport)
|
17
17
|
self.cap_create = bool(link.get('tun_persist'))
|
18
18
|
|
19
19
|
def create(self, do_apply, sysctl, excpts, oper="add"):
|
libifstate/link/veth.py
CHANGED
@@ -3,14 +3,14 @@ from libifstate.link.base import Link
|
|
3
3
|
from libifstate.exception import LinkCannotAdd, NetnsUnknown
|
4
4
|
|
5
5
|
class VethLink(Link):
|
6
|
-
def __init__(self, ifstate, netns, name, link, ethtool, vrrp, brport):
|
6
|
+
def __init__(self, ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport):
|
7
7
|
# use the bind_netns implementation to create the peer in the
|
8
8
|
# target netns
|
9
9
|
if 'peer_netns' in link:
|
10
10
|
link['bind_netns'] = link['peer_netns']
|
11
11
|
del(link['peer_netns'])
|
12
12
|
|
13
|
-
super().__init__(ifstate, netns, name, link, ethtool, vrrp, brport)
|
13
|
+
super().__init__(ifstate, netns, name, link, identify, ethtool, hooks, vrrp, brport)
|
14
14
|
|
15
15
|
def create(self, do_apply, sysctl, excpts, oper="add"):
|
16
16
|
'''
|
libifstate/netns/__init__.py
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
from libifstate.util import logger, IfStateLogging, IPRouteExt, NetNSExt, root_ipr
|
1
|
+
from libifstate.util import logger, IfStateLogging, IPRouteExt, NetNSExt, root_ipr, root_iw, IDENTIFY_LOOKUPS
|
2
2
|
from libifstate.sysctl import Sysctl
|
3
3
|
|
4
4
|
import atexit
|
5
5
|
from copy import deepcopy
|
6
6
|
import logging
|
7
7
|
import pyroute2
|
8
|
+
from pyroute2.netlink.exceptions import NetlinkError
|
8
9
|
import re
|
9
10
|
import secrets
|
10
11
|
import shutil
|
@@ -13,6 +14,7 @@ import subprocess
|
|
13
14
|
netns_name_map = {}
|
14
15
|
netns_name_root = None
|
15
16
|
netns_nsid_map = {}
|
17
|
+
iw_ifindex_phy_map = {}
|
16
18
|
|
17
19
|
@atexit.register
|
18
20
|
def close_netns():
|
@@ -44,12 +46,27 @@ class NetNameSpace():
|
|
44
46
|
|
45
47
|
if name is None:
|
46
48
|
self.ipr = root_ipr
|
49
|
+
self.iw = root_iw
|
47
50
|
self.mount = b''
|
48
51
|
else:
|
49
52
|
self.ipr = NetNSExt(name)
|
50
53
|
netns_name_map[name] = self.ipr
|
54
|
+
|
55
|
+
# check for wireless phys
|
56
|
+
if root_iw:
|
57
|
+
pyroute2.netns.pushns(name)
|
58
|
+
self.iw = pyroute2.IW()
|
59
|
+
pyroute2.netns.popns()
|
60
|
+
else:
|
61
|
+
self.iw = None
|
62
|
+
|
51
63
|
self.mount = name.encode("utf-8")
|
52
64
|
|
65
|
+
if self.iw is not None:
|
66
|
+
for ifname, ifdict in self.iw.get_interfaces_dict().items():
|
67
|
+
# ifIndex => phyIndex
|
68
|
+
iw_ifindex_phy_map[ifdict[0]] = ifdict[3]
|
69
|
+
|
53
70
|
def __deepcopy__(self, memo):
|
54
71
|
'''
|
55
72
|
Add custom deepcopy implementation to keep single IPRoute and NetNS instances.
|
@@ -59,7 +76,10 @@ class NetNameSpace():
|
|
59
76
|
memo[id(self)] = result
|
60
77
|
for k, v in self.__dict__.items():
|
61
78
|
if k == 'ipr':
|
62
|
-
|
79
|
+
if self.netns is None:
|
80
|
+
setattr(result, k, IPRouteExt())
|
81
|
+
else:
|
82
|
+
setattr(result, k, NetNSExt(self.netns))
|
63
83
|
else:
|
64
84
|
setattr(result, k, deepcopy(v, memo))
|
65
85
|
return result
|
@@ -81,7 +101,7 @@ class NetNameSpace():
|
|
81
101
|
|
82
102
|
return (peer_ipr, peer_nsid)
|
83
103
|
|
84
|
-
def prepare_netns(do_apply, target_netns_list, new_netns_list):
|
104
|
+
def prepare_netns(do_apply, target_netns_list, new_netns_list, ignore_netns):
|
85
105
|
logger.info("configure network namespaces...")
|
86
106
|
|
87
107
|
# get mapping of netns names to lists of pids
|
@@ -94,14 +114,15 @@ def prepare_netns(do_apply, target_netns_list, new_netns_list):
|
|
94
114
|
for name in sorted(names_set):
|
95
115
|
# cleanup orphan netns
|
96
116
|
if name not in target_netns_list:
|
97
|
-
if name in
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
117
|
+
if not any(re.match(regex, name) for regex in ignore_netns):
|
118
|
+
if name in ns_pids:
|
119
|
+
logger.warning(
|
120
|
+
'pids: {}'.format(', '.join((str(x) for x in ns_pids[name]))),
|
121
|
+
extra={'iface': name})
|
122
|
+
logger.log_del(name)
|
102
123
|
|
103
|
-
|
104
|
-
|
124
|
+
if do_apply:
|
125
|
+
pyroute2.netns.remove(name)
|
105
126
|
|
106
127
|
# create missing netns
|
107
128
|
elif name not in current_netns_list or name in new_netns_list:
|
@@ -222,8 +243,16 @@ class LinkRegistryItem():
|
|
222
243
|
self.attributes['kind'] = linkinfo.get_attr('IFLA_INFO_KIND')
|
223
244
|
else:
|
224
245
|
self.attributes['kind'] = "physical"
|
225
|
-
|
226
|
-
|
246
|
+
|
247
|
+
# add iw phy for wireless interfaces
|
248
|
+
if link['index'] in iw_ifindex_phy_map:
|
249
|
+
self.attributes['wiphy'] = iw_ifindex_phy_map[link['index']]
|
250
|
+
|
251
|
+
# add identify attributes
|
252
|
+
for attr, lookup in IDENTIFY_LOOKUPS.items():
|
253
|
+
value = lookup(netns, link)
|
254
|
+
if value is not None:
|
255
|
+
self.attributes[attr] = value
|
227
256
|
|
228
257
|
def __ipr_link(self, command, **kwargs):
|
229
258
|
logger.debug("ip link set netns={} {}".format(
|
@@ -270,7 +299,14 @@ class LinkRegistryItem():
|
|
270
299
|
# ToDo
|
271
300
|
self.update_ifname( self.registry.get_random_name('__netns__') )
|
272
301
|
|
273
|
-
|
302
|
+
if self.attributes.get('wiphy') is not None:
|
303
|
+
# move phy instead of iface for wireless devices
|
304
|
+
if netns.netns is None:
|
305
|
+
self.netns.iw.set_wiphy_netns_by_pid(self.attributes['wiphy'], 1)
|
306
|
+
else:
|
307
|
+
self.netns.iw.set_wiphy_netns_by_pid(self.attributes['wiphy'], netns.ipr.child)
|
308
|
+
else:
|
309
|
+
self.__ipr_link('set', index=self.attributes['index'], net_ns_fd=netns_name)
|
274
310
|
self.netns = netns
|
275
311
|
self.attributes['index'] = next(iter(self.netns.ipr.link_lookup(ifname=self.attributes['ifname'])), None)
|
276
312
|
|
libifstate/parser/base.py
CHANGED
@@ -6,7 +6,6 @@ from copy import deepcopy
|
|
6
6
|
|
7
7
|
class Parser(ABC):
|
8
8
|
_default_lo_link = {
|
9
|
-
'name': 'lo',
|
10
9
|
'addresses': [
|
11
10
|
'127.0.0.1/8',
|
12
11
|
'::1/128',
|
@@ -18,79 +17,96 @@ class Parser(ABC):
|
|
18
17
|
}
|
19
18
|
}
|
20
19
|
_default_ifstates = {
|
21
|
-
'
|
22
|
-
'
|
23
|
-
'
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
'
|
39
|
-
{
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
{'proto': 42},
|
52
|
-
{'proto': 186},
|
53
|
-
{'proto': 187},
|
54
|
-
{'proto': 188},
|
55
|
-
{'proto': 189},
|
56
|
-
{'proto': 192},
|
57
|
-
{'to': 'ff00::/8'},
|
58
|
-
],
|
59
|
-
'rules_builtin': [
|
60
|
-
{'proto': 1},
|
61
|
-
{'proto': 2},
|
62
|
-
{'proto': 8},
|
63
|
-
{'proto': 9},
|
64
|
-
{'proto': 10},
|
65
|
-
{'proto': 11},
|
66
|
-
{'proto': 12},
|
67
|
-
{'proto': 13},
|
68
|
-
{'proto': 14},
|
69
|
-
{'proto': 15},
|
70
|
-
{'proto': 16},
|
71
|
-
{'proto': 18},
|
72
|
-
{'proto': 42},
|
73
|
-
{'proto': 186},
|
74
|
-
{'proto': 187},
|
75
|
-
{'proto': 188},
|
76
|
-
{'proto': 189},
|
77
|
-
{'proto': 192},
|
78
|
-
],
|
79
|
-
},
|
80
|
-
'cshaper': {
|
81
|
-
'default': {
|
82
|
-
'egress_qdisc': {
|
83
|
-
'kind': 'cake',
|
84
|
-
'handle': '1:',
|
85
|
-
},
|
86
|
-
'ingress_qdisc': {
|
87
|
-
'kind': 'cake',
|
88
|
-
'handle': '1:',
|
89
|
-
},
|
90
|
-
'ingress_ifname': {
|
91
|
-
'search': r'^\D{1,3}',
|
92
|
-
'replace': 'ifb',
|
20
|
+
'parameters': {
|
21
|
+
'cshaper': {
|
22
|
+
'default': {
|
23
|
+
'egress_qdisc': {
|
24
|
+
'kind': 'cake',
|
25
|
+
'handle': '1:',
|
26
|
+
},
|
27
|
+
'ingress_qdisc': {
|
28
|
+
'kind': 'cake',
|
29
|
+
'handle': '1:',
|
30
|
+
},
|
31
|
+
'ingress_ifname': {
|
32
|
+
'search': r'^\D{1,3}',
|
33
|
+
'replace': 'ifb',
|
34
|
+
}
|
35
|
+
}
|
36
|
+
},
|
37
|
+
'defaults_builtin': [
|
38
|
+
{
|
39
|
+
'match': [
|
40
|
+
{'ifname': ''}
|
41
|
+
],
|
42
|
+
'clear_addresses': True,
|
43
|
+
'clear_fdb': True,
|
44
|
+
'clear_neighbours': True,
|
45
|
+
'clear_tc': True,
|
46
|
+
'link': {
|
47
|
+
'state': 'down',
|
48
|
+
'master': None
|
49
|
+
}
|
93
50
|
}
|
51
|
+
],
|
52
|
+
'ignore': {
|
53
|
+
'ipaddr_builtin': [
|
54
|
+
'fe80::/10'
|
55
|
+
],
|
56
|
+
'ipaddr_dynamic': True,
|
57
|
+
'ifname_builtin': [
|
58
|
+
r'^br-[\da-f]{12}',
|
59
|
+
r'^docker\d+',
|
60
|
+
r'^ppp\d+$',
|
61
|
+
r'^veth',
|
62
|
+
r'^virbr\d+',
|
63
|
+
r'^vrrp\d*\.\d+$'
|
64
|
+
],
|
65
|
+
'fdb_builtin': [
|
66
|
+
r'^33:33:',
|
67
|
+
r'^01:00:5e:'
|
68
|
+
],
|
69
|
+
'routes_builtin': [
|
70
|
+
{'proto': 1},
|
71
|
+
{'proto': 2},
|
72
|
+
{'proto': 8},
|
73
|
+
{'proto': 9},
|
74
|
+
{'proto': 10},
|
75
|
+
{'proto': 11},
|
76
|
+
{'proto': 12},
|
77
|
+
{'proto': 13},
|
78
|
+
{'proto': 14},
|
79
|
+
{'proto': 15},
|
80
|
+
{'proto': 16},
|
81
|
+
{'proto': 18},
|
82
|
+
{'proto': 42},
|
83
|
+
{'proto': 186},
|
84
|
+
{'proto': 187},
|
85
|
+
{'proto': 188},
|
86
|
+
{'proto': 189},
|
87
|
+
{'proto': 192},
|
88
|
+
{'to': 'ff00::/8'},
|
89
|
+
],
|
90
|
+
'rules_builtin': [
|
91
|
+
{'proto': 1},
|
92
|
+
{'proto': 2},
|
93
|
+
{'proto': 8},
|
94
|
+
{'proto': 9},
|
95
|
+
{'proto': 10},
|
96
|
+
{'proto': 11},
|
97
|
+
{'proto': 12},
|
98
|
+
{'proto': 13},
|
99
|
+
{'proto': 14},
|
100
|
+
{'proto': 15},
|
101
|
+
{'proto': 16},
|
102
|
+
{'proto': 18},
|
103
|
+
{'proto': 42},
|
104
|
+
{'proto': 186},
|
105
|
+
{'proto': 187},
|
106
|
+
{'proto': 188},
|
107
|
+
{'proto': 189},
|
108
|
+
{'proto': 192},
|
109
|
+
],
|
94
110
|
}
|
95
111
|
}
|
96
112
|
}
|
@@ -114,11 +130,11 @@ class Parser(ABC):
|
|
114
130
|
|
115
131
|
def _update_lo(self, cfg):
|
116
132
|
if 'interfaces' in cfg:
|
117
|
-
lo
|
118
|
-
|
119
|
-
|
133
|
+
if 'lo' in cfg['interfaces']:
|
134
|
+
cfg['interfaces']['lo'] = self.merge(
|
135
|
+
deepcopy(Parser._default_lo_link), cfg['interfaces']['lo'])
|
120
136
|
else:
|
121
|
-
cfg['interfaces']
|
137
|
+
cfg['interfaces']['lo'] = Parser._default_lo_link
|
122
138
|
|
123
139
|
def config(self):
|
124
140
|
# merge builtin defaults with config
|
@@ -126,7 +142,7 @@ class Parser(ABC):
|
|
126
142
|
|
127
143
|
# 'ignore' should still be an object
|
128
144
|
try:
|
129
|
-
iter(cfg["ignore"])
|
145
|
+
iter(cfg["parameters"]["ignore"])
|
130
146
|
except TypeError:
|
131
147
|
raise ParserValidationError("$.ignore: is not of type 'object'")
|
132
148
|
|
@@ -136,18 +152,25 @@ class Parser(ABC):
|
|
136
152
|
self._update_lo(cfg['namespaces'][namespace])
|
137
153
|
|
138
154
|
# merge builtin defaults
|
139
|
-
|
155
|
+
if "defaults" in cfg["parameters"]:
|
156
|
+
cfg["parameters"]["defaults"].extend(cfg["parameters"]["defaults_builtin"])
|
157
|
+
else:
|
158
|
+
cfg["parameters"]["defaults"] = cfg["parameters"]["defaults_builtin"]
|
159
|
+
del cfg["parameters"]["defaults_builtin"]
|
160
|
+
|
161
|
+
# merge builtin ignore lists
|
162
|
+
for k in list(cfg["parameters"]["ignore"]):
|
140
163
|
if k.endswith("_builtin"):
|
141
164
|
n = k[:-8]
|
142
|
-
if n in cfg["ignore"]:
|
165
|
+
if n in cfg["parameters"]["ignore"]:
|
143
166
|
try:
|
144
|
-
cfg["ignore"][n] += cfg["ignore"][k]
|
167
|
+
cfg["parameters"]["ignore"][n] += cfg["parameters"]["ignore"][k]
|
145
168
|
except TypeError:
|
146
169
|
raise ParserValidationError("$.ignore.{}: is not of type '{}'".format(
|
147
|
-
n, type(cfg["ignore"][k]).__name__))
|
170
|
+
n, type(cfg["parameters"]["ignore"][k]).__name__))
|
148
171
|
else:
|
149
|
-
cfg["ignore"][n] = cfg["ignore"][k]
|
150
|
-
del(cfg["ignore"][k])
|
172
|
+
cfg["parameters"]["ignore"][n] = cfg["parameters"]["ignore"][k]
|
173
|
+
del (cfg["parameters"]["ignore"][k])
|
151
174
|
|
152
175
|
return cfg
|
153
176
|
|