3 # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
4 # Author: Roopa Prabhu, roopa@cumulusnetworks.com
9 from ipaddr
import IPNetwork
, IPv4Network
, IPv6Network
, _BaseV6
12 from ifupdown2
.ifupdown
.iface
import *
13 from ifupdown2
.ifupdown
.utils
import utils
14 from ifupdown2
.ifupdown
.netlink
import netlink
16 from ifupdown2
.ifupdownaddons
.dhclient
import dhclient
17 from ifupdown2
.ifupdownaddons
.LinkUtils
import LinkUtils
18 from ifupdown2
.ifupdownaddons
.modulebase
import moduleBase
20 import ifupdown2
.ifupdown
.statemanager
as statemanager
21 import ifupdown2
.ifupdown
.policymanager
as policymanager
22 import ifupdown2
.ifupdown
.ifupdownflags
as ifupdownflags
23 import ifupdown2
.ifupdown
.ifupdownconfig
as ifupdownconfig
25 from ifupdown
.iface
import *
26 from ifupdown
.utils
import utils
27 from ifupdown
.netlink
import netlink
29 from ifupdownaddons
.dhclient
import dhclient
30 from ifupdownaddons
.LinkUtils
import LinkUtils
31 from ifupdownaddons
.modulebase
import moduleBase
33 import ifupdown
.statemanager
as statemanager
34 import ifupdown
.policymanager
as policymanager
35 import ifupdown
.ifupdownflags
as ifupdownflags
36 import ifupdown
.ifupdownconfig
as ifupdownconfig
39 class address(moduleBase
):
40 """ ifupdown2 addon module to configure address, mtu, hwaddress, alias
41 (description) on an interface """
43 _modinfo
= {'mhelp' : 'address configuration module for interfaces',
46 {'help' : 'ipv4 or ipv6 addresses',
47 'validvals' : ['<ipv4/prefixlen>', '<ipv6/prefixlen>'],
49 'example' : ['address 10.0.12.3/24',
50 'address 2000:1000:1000:1000:3::5/128']},
53 'example' : ['netmask 255.255.255.0'],
56 {'help': 'broadcast address',
57 'validvals' : ['<ipv4>', ],
58 'example' : ['broadcast 10.0.1.255']},
61 'validvals' : ['universe', 'site', 'link', 'host', 'nowhere'],
62 'example' : ['scope host']},
63 'preferred-lifetime' :
64 {'help': 'preferred lifetime',
65 'validrange' : ['0', '65535'],
66 'example' : ['preferred-lifetime forever',
67 'preferred-lifetime 10']},
69 {'help': 'default gateway',
70 'validvals' : ['<ipv4>', '<ipv6>'],
72 'example' : ['gateway 255.255.255.0']},
74 { 'help': 'interface mtu',
75 'validrange' : ['552', '9216'],
76 'example' : ['mtu 1600'],
79 {'help' : 'hw address',
80 'validvals' : ['<mac>',],
81 'example': ['hwaddress 44:38:39:00:27:b8']},
83 { 'help': 'description/alias',
84 'example' : ['alias testnetwork']},
86 { 'help': 'purge existing addresses. By default ' +
87 'any existing ip addresses on an interface are ' +
88 'purged to match persistant addresses in the ' +
89 'interfaces file. Set this attribute to \'no\'' +
90 'if you want to preserve existing addresses',
91 'validvals' : ['yes', 'no'],
93 'example' : ['address-purge yes/no']},
94 'clagd-vxlan-anycast-ip' :
95 { 'help' : 'Anycast local IP address for ' +
96 'dual connected VxLANs',
97 'validvals' : ['<ipv4>', ],
98 'example' : ['clagd-vxlan-anycast-ip 36.0.0.11']},
100 { 'help': 'ip forwarding flag',
101 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
103 'example' : ['ip-forward off']},
105 { 'help': 'ipv6 forwarding flag',
106 'validvals': ['on', 'off', 'yes', 'no', '0', '1'],
108 'example' : ['ip6-forward off']},
110 { 'help': 'mpls enable flag',
111 'validvals': ['yes', 'no'],
113 'example' : ['mpls-enable yes']},
115 'help': 'enable disable ipv6 link addrgenmode',
116 'validvals': ['on', 'off'],
125 def __init__(self
, *args
, **kargs
):
126 moduleBase
.__init
__(self
, *args
, **kargs
)
128 self
._bridge
_fdb
_query
_cache
= {}
129 self
.default_mtu
= policymanager
.policymanager_api
.get_attr_default(module_name
=self
.__class
__.__name
__, attr
='mtu')
130 self
.max_mtu
= policymanager
.policymanager_api
.get_module_globals(module_name
=self
.__class
__.__name
__, attr
='max_mtu')
131 self
.ipforward
= policymanager
.policymanager_api
.get_attr_default(module_name
=self
.__class
__.__name
__, attr
='ip-forward')
132 self
.ip6forward
= policymanager
.policymanager_api
.get_attr_default(module_name
=self
.__class
__.__name
__, attr
='ip6-forward')
133 self
.ifaces_defaults
= policymanager
.policymanager_api
.get_iface_defaults(module_name
=self
.__class
__.__name
__)
134 self
.enable_l3_iface_forwarding_checks
= utils
.get_boolean_from_string(
135 policymanager
.policymanager_api
.get_module_globals(
136 self
.__class
__.__name
__,
137 'enable_l3_iface_forwarding_checks'
141 if not self
.default_mtu
:
142 self
.default_mtu
= '1500'
144 self
.logger
.info('address: using default mtu %s' %self
.default_mtu
)
147 self
.logger
.info('address: using max mtu %s' %self
.max_mtu
)
149 self
.lower_iface_mtu_checked_list
= list()
151 def syntax_check(self
, ifaceobj
, ifaceobj_getfunc
=None):
152 return (self
.syntax_check_multiple_gateway(ifaceobj
)
153 and self
.syntax_check_addr_allowed_on(ifaceobj
, True)
154 and self
.syntax_check_mtu(ifaceobj
, ifaceobj_getfunc
)
155 and self
.syntax_check_sysctls(ifaceobj
)
156 and self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
, syntax_check
=True))
158 def syntax_check_enable_l3_iface_forwardings(self
, ifaceobj
, ifaceobj_getfunc
, syntax_check
=False):
159 if (self
.enable_l3_iface_forwarding_checks
160 and (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
161 or ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
)
162 and not ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
):
164 ifname
= ifaceobj
.name
166 vlan_ipforward_off
= None
168 for obj
in ifaceobj_getfunc(ifname
) or [ifaceobj
]:
170 vlan_addr
= obj
.get_attr_value('address')
172 if not vlan_ipforward_off
:
173 ip_forward_value
= obj
.get_attr_value_first('ip-forward')
175 if ip_forward_value
and not utils
.get_boolean_from_string(ip_forward_value
):
176 vlan_ipforward_off
= True
178 if vlan_addr
and vlan_ipforward_off
:
181 'configuring ip-forward off and ip address(es) (%s) is not compatible'
182 % (', '.join(vlan_addr
))
186 '%s: configuring ip-forward off and ip address(es) (%s) is not compatible'
187 % (ifname
, ', '.join(vlan_addr
))
192 def syntax_check_sysctls(self
, ifaceobj
):
194 bridge_port
= (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)
195 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
196 if bridge_port
and ipforward
:
198 self
.log_error('%s: \'ip-forward\' is not supported for '
199 'bridge port' %ifaceobj
.name
)
200 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
201 if bridge_port
and ip6forward
:
203 self
.log_error('%s: \'ip6-forward\' is not supported for '
204 'bridge port' %ifaceobj
.name
)
207 def syntax_check_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
208 mtu
= ifaceobj
.get_attr_value_first('mtu')
210 return self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
,
214 def syntax_check_addr_allowed_on(self
, ifaceobj
, syntax_check
=False):
215 if ifaceobj
.get_attr_value('address'):
216 return utils
.is_addr_ip_allowed_on(ifaceobj
, syntax_check
=syntax_check
)
219 def _syntax_check_multiple_gateway(self
, family
, found
, addr
, type_obj
):
220 if type(IPNetwork(addr
)) == type_obj
:
222 raise Exception('%s: multiple gateways for %s family'
227 def syntax_check_multiple_gateway(self
, ifaceobj
):
231 gateways
= ifaceobj
.get_attr_value('gateway')
232 for addr
in gateways
if gateways
else []:
234 if self
._syntax
_check
_multiple
_gateway
('inet', inet
, addr
,
237 if self
._syntax
_check
_multiple
_gateway
('inet6', inet6
, addr
,
240 except Exception as e
:
241 self
.logger
.warning('%s: address: %s' % (ifaceobj
.name
, str(e
)))
245 def _address_valid(self
, addrs
):
248 if any(map(lambda a
: True if a
[:7] != '0.0.0.0'
253 def _get_hwaddress(self
, ifaceobj
):
254 return utils
.strip_hwaddress(ifaceobj
.get_attr_value_first('hwaddress'))
256 def _process_bridge(self
, ifaceobj
, up
):
257 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
258 addrs
= ifaceobj
.get_attr_value_first('address')
259 is_vlan_dev_on_vlan_aware_bridge
= False
260 is_bridge
= self
.ipcmd
.is_bridge(ifaceobj
.name
)
262 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
263 bridgename
= ifaceobj
.lowerifaces
[0]
264 vlan
= self
._get
_vlan
_id
(ifaceobj
)
265 is_vlan_dev_on_vlan_aware_bridge
= self
.ipcmd
.bridge_is_vlan_aware(bridgename
)
266 if ((is_bridge
and not self
.ipcmd
.bridge_is_vlan_aware(ifaceobj
.name
))
267 or is_vlan_dev_on_vlan_aware_bridge
):
268 if self
._address
_valid
(addrs
):
270 self
.write_file('/proc/sys/net/ipv4/conf/%s' %ifaceobj
.name
+
273 self
.write_file('/proc/sys/net/ipv4/conf/%s' %ifaceobj
.name
+
275 if hwaddress
and is_vlan_dev_on_vlan_aware_bridge
:
277 self
.ipcmd
.bridge_fdb_add(bridgename
, hwaddress
, vlan
)
279 self
.ipcmd
.bridge_fdb_del(bridgename
, hwaddress
, vlan
)
281 def _get_anycast_addr(self
, ifaceobjlist
):
282 for ifaceobj
in ifaceobjlist
:
283 anycast_addr
= ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip')
285 anycast_addr
= anycast_addr
+'/32'
289 def _inet_address_convert_to_cidr(self
, ifaceobjlist
):
293 for ifaceobj
in ifaceobjlist
:
294 addrs
= ifaceobj
.get_attr_value('address')
298 if not self
.syntax_check_addr_allowed_on(ifaceobj
,
300 return (False, newaddrs
, newaddr_attrs
)
301 # If user address is not in CIDR notation, convert them to CIDR
302 for addr_index
in range(0, len(addrs
)):
303 addr
= addrs
[addr_index
]
306 newaddrs
.append(addr
)
308 netmask
= ifaceobj
.get_attr_value_n('netmask', addr_index
)
310 prefixlen
= IPNetwork('%s' %addr
+
311 '/%s' %netmask
).prefixlen
312 newaddr
= addr
+ '/%s' %prefixlen
314 # we are here because there is no slash (/xx) and no netmask
315 # just let IPNetwork handle the ipv4 or ipv6 address mask
316 prefixlen
= IPNetwork(addr
).prefixlen
317 newaddr
= addr
+ '/%s' %prefixlen
318 newaddrs
.append(newaddr
)
321 for a
in ['broadcast', 'pointopoint', 'scope',
322 'preferred-lifetime']:
323 aval
= ifaceobj
.get_attr_value_n(a
, addr_index
)
328 newaddr_attrs
[newaddr
]= attrs
329 return (True, newaddrs
, newaddr_attrs
)
331 def _inet_address_list_config(self
, ifaceobj
, newaddrs
, newaddr_attrs
):
332 for addr_index
in range(0, len(newaddrs
)):
335 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
],
336 newaddr_attrs
.get(newaddrs
[addr_index
],
337 {}).get('broadcast'),
338 newaddr_attrs
.get(newaddrs
[addr_index
],
339 {}).get('pointopoint'),
340 newaddr_attrs
.get(newaddrs
[addr_index
],
342 newaddr_attrs
.get(newaddrs
[addr_index
],
343 {}).get('preferred-lifetime'))
345 self
.ipcmd
.addr_add(ifaceobj
.name
, newaddrs
[addr_index
])
347 self
.log_error(str(e
), ifaceobj
)
349 def _inet_address_config(self
, ifaceobj
, ifaceobj_getfunc
=None,
350 force_reapply
=False):
351 squash_addr_config
= (True if \
352 ifupdownconfig
.config
.get('addr_config_squash', \
353 '0') == '1' else False)
355 if (squash_addr_config
and
356 not (ifaceobj
.flags
& ifaceobj
.YOUNGEST_SIBLING
)):
359 purge_addresses
= ifaceobj
.get_attr_value_first('address-purge')
360 if not purge_addresses
:
361 purge_addresses
= 'yes'
363 if squash_addr_config
and ifaceobj
.flags
& iface
.HAS_SIBLINGS
:
364 ifaceobjlist
= ifaceobj_getfunc(ifaceobj
.name
)
366 ifaceobjlist
= [ifaceobj
]
368 module_name
= self
.__class
__.__name
__
369 ifname
= ifaceobj
.name
371 (addr_supported
, newaddrs
, newaddr_attrs
) = self
._inet
_address
_convert
_to
_cidr
(ifaceobjlist
)
372 newaddrs
= utils
.get_ip_objs(module_name
, ifname
, newaddrs
)
374 if not addr_supported
:
376 if (not squash_addr_config
and (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
377 # if youngest sibling and squash addr is not set
378 # print a warning that addresses will not be purged
379 if (ifaceobj
.flags
& iface
.YOUNGEST_SIBLING
):
380 self
.logger
.warn('%s: interface has multiple ' %ifaceobj
.name
+
381 'iface stanzas, skip purging existing addresses')
382 purge_addresses
= 'no'
384 if not ifupdownflags
.flags
.PERFMODE
and purge_addresses
== 'yes':
385 # if perfmode is not set and purge addresses is not set to 'no'
386 # lets purge addresses not in the config
387 runningaddrs
= self
.ipcmd
.get_running_addrs(ifaceobj
, details
=False)
389 # if anycast address is configured on 'lo' and is in running config
390 # add it to newaddrs so that ifreload doesn't wipe it out
391 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, self
._get
_anycast
_addr
(ifaceobjlist
))
393 if runningaddrs
and anycast_addr
and anycast_addr
in runningaddrs
:
394 newaddrs
.append(anycast_addr
)
396 user_ip4
, user_ip6
, newaddrs
= self
.order_user_configured_addrs(newaddrs
)
398 if newaddrs
== runningaddrs
or self
.compare_running_ips_and_user_config(user_ip4
, user_ip6
, runningaddrs
):
400 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
403 # if primary address is not same, there is no need to keep any.
404 # reset all addresses
405 if newaddrs
and runningaddrs
and newaddrs
[0] != runningaddrs
[0]:
408 skip_addrs
= newaddrs
or []
409 for addr
in runningaddrs
or []:
410 if addr
in skip_addrs
:
412 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
414 self
.log_warn(str(e
))
417 self
._inet
_address
_list
_config
(ifaceobj
, newaddrs
, newaddr_attrs
)
419 def compare_running_ips_and_user_config(self
, user_ip4
, user_ip6
, running_addrs
):
421 We need to compare the user config ips and the running ips.
422 ip4 ordering matters (primary etc) but ip6 order doesn't matter
424 this function replaces the strict comparison previously in place
425 if newaddrs == running_addrs ?
427 We will compare if the ip4 ordering is correct, then check if all
428 ip6 are present in the list (without checking the ordering)
430 if (user_ip4
or user_ip6
) and not running_addrs
:
432 elif running_addrs
and not user_ip4
and not user_ip6
:
434 elif not running_addrs
and not user_ip4
and not user_ip6
:
437 len_ip4
= len(user_ip4
)
438 len_running_addrs
= len(running_addrs
)
440 if len_ip4
> len_running_addrs
:
445 if user_ip4
[i
] != running_addrs
[i
]:
450 running_ip6
= running_addrs
[len_ip4
:]
452 running_ip6
= running_addrs
455 len_ip6
= len(user_ip6
)
457 for ip6
in running_ip6
:
458 if ip6
not in user_ip6
:
464 def order_user_configured_addrs(self
, user_config_addrs
):
468 for a
in user_config_addrs
:
469 if isinstance(a
, _BaseV6
):
474 return ip4
, ip6
, ip4
+ ip6
476 def _delete_gateway(self
, ifaceobj
, gateways
, vrf
, metric
):
477 for del_gw
in gateways
:
479 self
.ipcmd
.route_del_gateway(ifaceobj
.name
, del_gw
, vrf
, metric
)
480 except Exception as e
:
481 self
.logger
.debug('%s: %s' % (ifaceobj
.name
, str(e
)))
483 def _add_delete_gateway(self
, ifaceobj
, gateways
=[], prev_gw
=[]):
484 vrf
= ifaceobj
.get_attr_value_first('vrf')
485 metric
= ifaceobj
.get_attr_value_first('metric')
486 self
._delete
_gateway
(ifaceobj
, list(set(prev_gw
) - set(gateways
)),
488 for add_gw
in gateways
:
490 self
.ipcmd
.route_add_gateway(ifaceobj
.name
, add_gw
, vrf
, metric
)
491 except Exception as e
:
492 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)))
494 def _get_prev_gateway(self
, ifaceobj
, gateways
):
496 saved_ifaceobjs
= statemanager
.statemanager_api
.get_ifaceobjs(ifaceobj
.name
)
497 if not saved_ifaceobjs
:
499 prev_gateways
= saved_ifaceobjs
[0].get_attr_value('gateway')
500 if not prev_gateways
:
504 def _check_mtu_config(self
, ifaceobj
, mtu
, ifaceobj_getfunc
, syntaxcheck
=False):
506 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
508 self
.logger
.warn('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
511 self
.logger
.info('%s: bridge inherits mtu from its ports. There is no need to assign mtu on a bridge' %ifaceobj
.name
)
512 elif ifaceobj_getfunc
:
513 if ((ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
514 ifaceobj
.upperifaces
):
515 masterobj
= ifaceobj_getfunc(ifaceobj
.upperifaces
[0])
517 master_mtu
= masterobj
[0].get_attr_value_first('mtu')
518 if master_mtu
and master_mtu
!= mtu
:
520 self
.logger
.warn('%s: bond slave mtu %s is different from bond master %s mtu %s. There is no need to configure mtu on a bond slave.' %(ifaceobj
.name
, mtu
, masterobj
[0].name
, master_mtu
))
523 self
.logger
.info('%s: bond slave mtu %s is different from bond master %s mtu %s. There is no need to configure mtu on a bond slave.' %(ifaceobj
.name
, mtu
, masterobj
[0].name
, master_mtu
))
524 elif ((ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
) and
525 ifaceobj
.lowerifaces
):
526 lowerobj
= ifaceobj_getfunc(ifaceobj
.lowerifaces
[0])
529 lowerdev_mtu
= lowerobj
[0].get_attr_value_first('mtu')
531 lowerdev_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lowerobj
[0].name
)
532 if lowerdev_mtu
and int(mtu
) > int(lowerdev_mtu
):
533 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
534 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, lowerdev_mtu
))
536 elif (not lowerobj
[0].link_kind
and
537 not (lowerobj
[0].link_privflags
& ifaceLinkPrivFlags
.LOOPBACK
) and
538 not lowerdev_mtu
and self
.default_mtu
and
539 (int(mtu
) > int(self
.default_mtu
))):
540 # only check default mtu on lower device which is a physical interface
541 self
.logger
.warn('%s: vlan dev mtu %s is greater than lower realdev %s mtu %s'
542 %(ifaceobj
.name
, mtu
, lowerobj
[0].name
, self
.default_mtu
))
544 if self
.max_mtu
and mtu
> self
.max_mtu
:
545 self
.logger
.warn('%s: specified mtu %s is greater than max mtu %s'
546 %(ifaceobj
.name
, mtu
, self
.max_mtu
))
550 def _propagate_mtu_to_upper_devs(self
, ifaceobj
, mtu
, ifaceobj_getfunc
):
551 if (not ifaceobj
.upperifaces
or
552 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) or
553 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.VRF_SLAVE
) or
554 (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
)):
556 for u
in ifaceobj
.upperifaces
:
557 upperobjs
= ifaceobj_getfunc(u
)
559 not (upperobjs
[0].link_kind
& ifaceLinkKind
.VLAN
)):
561 # only adjust mtu for vlan devices on ifaceobj
562 umtu
= upperobjs
[0].get_attr_value_first('mtu')
564 running_mtu
= self
.ipcmd
.link_get_mtu(upperobjs
[0].name
)
565 if not running_mtu
or (running_mtu
!= mtu
):
566 self
.ipcmd
.link_set(u
, 'mtu', mtu
)
568 def _process_mtu_config(self
, ifaceobj
, ifaceobj_getfunc
, mtu
):
570 if not self
._check
_mtu
_config
(ifaceobj
, mtu
, ifaceobj_getfunc
):
572 cached_running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
573 running_mtu
= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
)
574 if not running_mtu
or (running_mtu
and running_mtu
!= mtu
):
575 force
= cached_running_mtu
!= running_mtu
576 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', mtu
, force
=force
)
577 if (not ifupdownflags
.flags
.ALL
and
578 not ifaceobj
.link_kind
and
579 ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'):
580 # This is additional cost to us, so do it only when
581 # ifupdown2 is called on a particular interface and
582 # it is a physical interface
583 self
._propagate
_mtu
_to
_upper
_devs
(ifaceobj
, mtu
, ifaceobj_getfunc
)
586 if ifaceobj
.link_kind
:
587 # bonds and vxlan devices need an explicit set of mtu.
588 # bridges don't need mtu set
589 if (ifaceobj
.link_kind
& ifaceLinkKind
.BOND
or
590 ifaceobj
.link_kind
& ifaceLinkKind
.VXLAN
):
591 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
592 if (self
.default_mtu
and running_mtu
!= self
.default_mtu
):
593 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
595 if (ifupdownconfig
.config
.get('adjust_logical_dev_mtu', '1') != '0'
596 and ifaceobj
.lowerifaces
):
597 # set vlan interface mtu to lower device mtu
598 if (ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
):
599 lower_iface
= ifaceobj
.lowerifaces
[0]
600 if lower_iface
not in self
.lower_iface_mtu_checked_list
:
601 lower_iface_mtu
= self
.ipcmd
.link_get_mtu_sysfs(lower_iface
)
602 self
.ipcmd
.cache_update([lower_iface
, 'mtu'], lower_iface_mtu
)
603 self
.lower_iface_mtu_checked_list
.append(lower_iface
)
605 lower_iface_mtu
= self
.ipcmd
.link_get_mtu(lower_iface
)
607 if lower_iface_mtu
!= self
.ipcmd
.link_get_mtu_sysfs(ifaceobj
.name
):
608 self
.ipcmd
.link_set_mtu(ifaceobj
.name
, lower_iface_mtu
)
610 elif (not (ifaceobj
.name
== 'lo') and not ifaceobj
.link_kind
and
611 not (ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BOND_SLAVE
) and
613 # logical devices like bridges and vlan devices rely on mtu
614 # from their lower devices. ie mtu travels from
615 # lower devices to upper devices. For bonds mtu travels from
616 # upper to lower devices. running mtu depends on upper and
617 # lower device mtu. With all this implicit mtu
618 # config by the kernel in play, we try to be cautious here
619 # on which devices we want to reset mtu to default.
620 # essentially only physical interfaces which are not bond slaves
621 running_mtu
= self
.ipcmd
.link_get_mtu(ifaceobj
.name
)
622 if running_mtu
!= self
.default_mtu
:
623 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
625 def _set_bridge_forwarding(self
, ifaceobj
):
626 """ set ip forwarding to 0 if bridge interface does not have a
628 if not ifaceobj
.upperifaces
and not ifaceobj
.get_attr_value('address'):
630 if self
.sysctl_get('net.ipv4.conf.%s.forwarding' %ifaceobj
.name
) == '1':
631 self
.sysctl_set('net.ipv4.conf.%s.forwarding' %ifaceobj
.name
, 0)
632 if self
.sysctl_get('net.ipv6.conf.%s.forwarding' %ifaceobj
.name
) == '1':
633 self
.sysctl_set('net.ipv6.conf.%s.forwarding' %ifaceobj
.name
, 0)
635 if self
.sysctl_get('net.ipv4.conf.%s.forwarding' %ifaceobj
.name
) == '0':
636 self
.sysctl_set('net.ipv4.conf.%s.forwarding' %ifaceobj
.name
, 1)
637 if self
.sysctl_get('net.ipv6.conf.%s.forwarding' %ifaceobj
.name
) == '0':
638 self
.sysctl_set('net.ipv6.conf.%s.forwarding' %ifaceobj
.name
, 1)
640 def _sysctl_config(self
, ifaceobj
):
641 setting_default_value
= False
642 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
644 setting_default_value
= True
645 mpls_enable
= self
.get_mod_subattr('mpls-enable', 'default')
646 mpls_enable
= utils
.boolean_support_binary(mpls_enable
)
647 # File read has been used for better performance
648 # instead of using sysctl command
649 if ifupdownflags
.flags
.PERFMODE
:
650 running_mpls_enable
= '0'
652 running_mpls_enable
= self
.read_file_oneline(
653 '/proc/sys/net/mpls/conf/%s/input'
657 if mpls_enable
!= running_mpls_enable
:
659 self
.sysctl_set('net.mpls.conf.%s.input'
660 %('/'.join(ifaceobj
.name
.split("."))),
662 except Exception as e
:
663 if not setting_default_value
:
664 ifaceobj
.status
= ifaceStatus
.ERROR
665 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
667 if (ifaceobj
.link_kind
& ifaceLinkKind
.BRIDGE
):
668 self
._set
_bridge
_forwarding
(ifaceobj
)
670 if not self
.syntax_check_sysctls(ifaceobj
):
672 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
673 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
674 if ifupdownflags
.flags
.PERFMODE
:
676 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
677 %('/'.join(ifaceobj
.name
.split("."))),
678 utils
.boolean_support_binary(ipforward
))
680 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
681 %('/'.join(ifaceobj
.name
.split("."))),
682 utils
.boolean_support_binary(ip6forward
))
684 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
687 self
.log_error('%s: \'ip-forward\' is not supported for '
688 'bridge port' %ifaceobj
.name
)
690 self
.log_error('%s: \'ip6-forward\' is not supported for '
691 'bridge port' %ifaceobj
.name
)
693 setting_default_value
= False
695 setting_default_value
= True
696 ipforward
= (self
.ipforward
or
697 self
.get_mod_subattr('ip-forward', 'default'))
698 ipforward
= utils
.boolean_support_binary(ipforward
)
699 # File read has been used for better performance
700 # instead of using sysctl command
701 running_ipforward
= self
.read_file_oneline(
702 '/proc/sys/net/ipv4/conf/%s/forwarding'
704 if ipforward
!= running_ipforward
:
706 self
.sysctl_set('net.ipv4.conf.%s.forwarding'
707 %('/'.join(ifaceobj
.name
.split("."))),
709 except Exception as e
:
710 if not setting_default_value
:
711 ifaceobj
.status
= ifaceStatus
.ERROR
712 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
714 setting_default_value
= False
716 setting_default_value
= True
717 ip6forward
= (self
.ip6forward
or
718 self
.get_mod_subattr('ip6-forward', 'default'))
719 ip6forward
= utils
.boolean_support_binary(ip6forward
)
720 # File read has been used for better performance
721 # instead of using sysctl command
722 running_ip6forward
= self
.read_file_oneline(
723 '/proc/sys/net/ipv6/conf/%s/forwarding'
725 if ip6forward
!= running_ip6forward
:
727 self
.sysctl_set('net.ipv6.conf.%s.forwarding'
728 %('/'.join(ifaceobj
.name
.split("."))),
730 except Exception as e
:
731 # There is chance of ipv6 being removed because of,
732 # for example, setting mtu < 1280
733 # In such cases, log error only if user has configured
735 if not setting_default_value
:
736 ifaceobj
.status
= ifaceStatus
.ERROR
737 self
.logger
.error('%s: %s' %(ifaceobj
.name
, str(e
)))
739 def process_mtu(self
, ifaceobj
, ifaceobj_getfunc
):
740 mtu
= ifaceobj
.get_attr_value_first('mtu')
743 default_iface_mtu
= self
.ifaces_defaults
.get(ifaceobj
.name
, {}).get('mtu')
745 if default_iface_mtu
:
747 mtu
= default_iface_mtu
748 int(default_iface_mtu
)
749 except Exception as e
:
750 self
.logger
.warning('%s: MTU value from policy file: %s' % (ifaceobj
.name
, str(e
)))
753 self
._process
_mtu
_config
(ifaceobj
, ifaceobj_getfunc
, mtu
)
755 def up_ipv6_addrgen(self
, ifaceobj
):
756 user_configured_ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
758 if not user_configured_ipv6_addrgen
and ifupdownflags
.flags
.PERFMODE
:
759 # no need to go further during perfmode (boot)
762 if not user_configured_ipv6_addrgen
:
763 # if user didn't configure ipv6-addrgen, should we reset to default?
764 user_configured_ipv6_addrgen
= self
.get_attr_default_value('ipv6-addrgen')
773 }.get(user_configured_ipv6_addrgen
.lower(), None)
775 if ipv6_addrgen_nl
is not None:
776 self
.ipcmd
.ipv6_addrgen(ifaceobj
.name
, ipv6_addrgen_nl
, link_created
=True)
777 # link_create=False will flush the addr cache of that intf
779 self
.logger
.warning('%s: invalid value "%s" for attribute ipv6-addrgen' % (ifaceobj
.name
, user_configured_ipv6_addrgen
))
781 def _up(self
, ifaceobj
, ifaceobj_getfunc
=None):
782 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
785 if not self
.syntax_check_enable_l3_iface_forwardings(ifaceobj
, ifaceobj_getfunc
):
788 alias
= ifaceobj
.get_attr_value_first('alias')
789 current_alias
= self
.ipcmd
.link_get_alias(ifaceobj
.name
)
790 if alias
and alias
!= current_alias
:
791 self
.ipcmd
.link_set_alias(ifaceobj
.name
, alias
)
792 elif not alias
and current_alias
:
793 self
.ipcmd
.link_set_alias(ifaceobj
.name
, '')
795 self
._sysctl
_config
(ifaceobj
)
797 addr_method
= ifaceobj
.addr_method
798 force_reapply
= False
800 # release any stale dhcp addresses if present
801 if (addr_method
not in ["dhcp", "ppp"] and not ifupdownflags
.flags
.PERFMODE
and
802 not (ifaceobj
.flags
& iface
.HAS_SIBLINGS
)):
803 # if not running in perf mode and ifaceobj does not have
804 # any sibling iface objects, kill any stale dhclient
806 dhclientcmd
= dhclient()
807 if dhclientcmd
.is_running(ifaceobj
.name
):
808 # release any dhcp leases
809 dhclientcmd
.release(ifaceobj
.name
)
811 elif dhclientcmd
.is_running6(ifaceobj
.name
):
812 dhclientcmd
.release6(ifaceobj
.name
)
817 self
.ipcmd
.batch_start()
818 self
.up_ipv6_addrgen(ifaceobj
)
820 if addr_method
not in ["dhcp", "ppp"]:
821 self
._inet
_address
_config
(ifaceobj
, ifaceobj_getfunc
,
824 self
.process_mtu(ifaceobj
, ifaceobj_getfunc
)
827 self
.ipcmd
.batch_commit()
828 except Exception as e
:
829 self
.log_error('%s: %s' % (ifaceobj
.name
, str(e
)), ifaceobj
, raise_error
=False)
832 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
834 running_hwaddress
= None
835 if not ifupdownflags
.flags
.PERFMODE
: # system is clean
836 running_hwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
837 if hwaddress
!= running_hwaddress
:
839 netlink
.link_set_updown(ifaceobj
.name
, "down")
840 if ifaceobj
.link_kind
& ifaceLinkKind
.BOND
:
841 # if bond, down all the slaves
842 if ifaceobj
.lowerifaces
:
843 for l
in ifaceobj
.lowerifaces
:
844 netlink
.link_set_updown(l
, "down")
847 self
.ipcmd
.link_set(ifaceobj
.name
, 'address', hwaddress
)
849 netlink
.link_set_updown(ifaceobj
.name
, "up")
851 for l
in ifaceobj
.lowerifaces
:
852 netlink
.link_set_updown(l
, "up")
854 # Handle special things on a bridge
855 self
._process
_bridge
(ifaceobj
, True)
857 self
.log_error('%s: %s' %(ifaceobj
.name
, str(e
)), ifaceobj
)
859 gateways
= ifaceobj
.get_attr_value('gateway')
862 prev_gw
= self
._get
_prev
_gateway
(ifaceobj
, gateways
)
863 self
._add
_delete
_gateway
(ifaceobj
, gateways
, prev_gw
)
865 def _down(self
, ifaceobj
, ifaceobj_getfunc
=None):
867 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
869 addr_method
= ifaceobj
.addr_method
870 if addr_method
not in ["dhcp", "ppp"]:
871 if ifaceobj
.get_attr_value_first('address-purge')=='no':
872 addrlist
= ifaceobj
.get_attr_value('address')
873 for addr
in addrlist
:
874 self
.ipcmd
.addr_del(ifaceobj
.name
, addr
)
875 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
876 elif not ifaceobj
.link_kind
:
877 # for logical interfaces we don't need to remove the ip addresses
878 # kernel will do it for us on 'ip link del'
879 self
.ipcmd
.del_addr_all(ifaceobj
.name
)
880 gateways
= ifaceobj
.get_attr_value('gateway')
882 self
._delete
_gateway
(ifaceobj
, gateways
,
883 ifaceobj
.get_attr_value_first('vrf'),
884 ifaceobj
.get_attr_value_first('metric'))
885 mtu
= ifaceobj
.get_attr_value_first('mtu')
886 if (not ifaceobj
.link_kind
and mtu
and
887 self
.default_mtu
and (mtu
!= self
.default_mtu
)):
888 self
.ipcmd
.link_set(ifaceobj
.name
, 'mtu', self
.default_mtu
)
889 alias
= ifaceobj
.get_attr_value_first('alias')
891 self
.write_file('/sys/class/net/%s/ifalias' % ifaceobj
.name
, '\n')
892 # XXX hwaddress reset cannot happen because we dont know last
895 # Handle special things on a bridge
896 self
._process
_bridge
(ifaceobj
, False)
898 self
.logger
.debug('%s : %s' %(ifaceobj
.name
, str(e
)))
901 def _get_iface_addresses(self
, ifaceobj
):
902 addrlist
= ifaceobj
.get_attr_value('address')
905 if not addrlist
: return None
906 for addrindex
in range(0, len(addrlist
)):
907 addr
= addrlist
[addrindex
]
908 netmask
= ifaceobj
.get_attr_value_n('netmask', addrindex
)
910 prefixlen
= IPNetwork('%s' %addr
+
911 '/%s' %netmask
).prefixlen
912 addr
= addr
+ '/%s' %prefixlen
913 outaddrlist
.append(addr
)
916 def _get_bridge_fdbs(self
, bridgename
, vlan
):
917 fdbs
= self
._bridge
_fdb
_query
_cache
.get(bridgename
)
919 fdbs
= self
.ipcmd
.bridge_fdb_show_dev(bridgename
)
922 self
._bridge
_fdb
_query
_cache
[bridgename
] = fdbs
923 return fdbs
.get(vlan
)
925 def _check_addresses_in_bridge(self
, ifaceobj
, hwaddress
):
926 """ If the device is a bridge, make sure the addresses
927 are in the bridge """
928 if ifaceobj
.link_kind
& ifaceLinkKind
.VLAN
:
929 bridgename
= ifaceobj
.lowerifaces
[0]
930 vlan
= self
._get
_vlan
_id
(ifaceobj
)
931 if self
.ipcmd
.bridge_is_vlan_aware(bridgename
):
932 fdb_addrs
= self
._get
_bridge
_fdbs
(bridgename
, str(vlan
))
933 if not fdb_addrs
or hwaddress
not in fdb_addrs
:
937 def _query_sysctl(self
, ifaceobj
, ifaceobjcurr
):
938 bridge_port
= ifaceobj
.link_privflags
& ifaceLinkPrivFlags
.BRIDGE_PORT
939 ipforward
= ifaceobj
.get_attr_value_first('ip-forward')
942 ifaceobjcurr
.status
= ifaceStatus
.ERROR
943 ifaceobjcurr
.status_str
= ('\'ip-forward\' not supported ' +
945 ifaceobjcurr
.update_config_with_status('ip-forward', 1, None)
947 running_ipforward
= self
.read_file_oneline(
948 '/proc/sys/net/ipv4/conf/%s/forwarding'
950 running_ipforward
= utils
.get_boolean_from_string(running_ipforward
)
951 config_ipforward
= utils
.get_boolean_from_string(ipforward
)
952 ifaceobjcurr
.update_config_with_status(
954 'on' if running_ipforward
else 'off',
955 running_ipforward
!= config_ipforward
958 ip6forward
= ifaceobj
.get_attr_value_first('ip6-forward')
961 ifaceobjcurr
.status
= ifaceStatus
.ERROR
962 ifaceobjcurr
.status_str
= ('\'ip6-forward\' not supported ' +
964 ifaceobjcurr
.update_config_with_status('ip6-forward', 1, None)
966 running_ip6forward
= self
.read_file_oneline(
967 '/proc/sys/net/ipv6/conf/%s/forwarding'
969 running_ip6forward
= utils
.get_boolean_from_string(running_ip6forward
)
970 config_ip6forward
= utils
.get_boolean_from_string(ip6forward
)
971 ifaceobjcurr
.update_config_with_status(
973 'on' if running_ip6forward
else 'off',
974 running_ip6forward
!= config_ip6forward
976 mpls_enable
= ifaceobj
.get_attr_value_first('mpls-enable');
978 running_mpls_enable
= self
.read_file_oneline(
979 '/proc/sys/net/mpls/conf/%s/input'
981 running_mpls_enable
= utils
.get_yesno_from_onezero(
983 ifaceobjcurr
.update_config_with_status('mpls-enable',
985 mpls_enable
!= running_mpls_enable
)
988 def query_check_ipv6_addrgen(self
, ifaceobj
, ifaceobjcurr
):
989 ipv6_addrgen
= ifaceobj
.get_attr_value_first('ipv6-addrgen')
994 if ipv6_addrgen
in utils
._string
_values
:
995 ifaceobjcurr
.update_config_with_status(
998 utils
.get_boolean_from_string(ipv6_addrgen
) == self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobj
.name
)
1001 ifaceobjcurr
.update_config_with_status('ipv6-addrgen', ipv6_addrgen
, 1)
1003 def _query_check(self
, ifaceobj
, ifaceobjcurr
, ifaceobj_getfunc
=None):
1004 runningaddrsdict
= None
1005 if not self
.ipcmd
.link_exists(ifaceobj
.name
):
1006 self
.logger
.debug('iface %s not found' %ifaceobj
.name
)
1009 self
.query_check_ipv6_addrgen(ifaceobj
, ifaceobjcurr
)
1011 addr_method
= ifaceobj
.addr_method
1012 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1013 'mtu', self
.ipcmd
.link_get_mtu
)
1014 hwaddress
= self
._get
_hwaddress
(ifaceobj
)
1016 rhwaddress
= self
.ipcmd
.link_get_hwaddress(ifaceobj
.name
)
1017 if not rhwaddress
or rhwaddress
!= hwaddress
:
1018 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1020 elif not self
._check
_addresses
_in
_bridge
(ifaceobj
, hwaddress
):
1021 # XXX: hw address is not in bridge
1022 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1024 ifaceobjcurr
.status_str
= 'bridge fdb error'
1026 ifaceobjcurr
.update_config_with_status('hwaddress', rhwaddress
,
1028 self
.query_n_update_ifaceobjcurr_attr(ifaceobj
, ifaceobjcurr
,
1029 'alias', self
.ipcmd
.link_get_alias
)
1030 self
._query
_sysctl
(ifaceobj
, ifaceobjcurr
)
1032 if addr_method
in ["dhcp", "ppp"]:
1034 addrs
= utils
.get_normalized_ip_addr(ifaceobj
.name
,
1035 self
._get
_iface
_addresses
(ifaceobj
))
1036 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobj
)
1037 # if anycast address is configured on 'lo' and is in running config
1038 # add it to addrs so that query_check doesn't fail
1039 anycast_addr
= utils
.get_normalized_ip_addr(ifaceobj
.name
, ifaceobj
.get_attr_value_first('clagd-vxlan-anycast-ip'))
1041 anycast_addr
= anycast_addr
+'/32'
1042 if runningaddrsdict
and anycast_addr
and runningaddrsdict
.get(anycast_addr
):
1043 addrs
.append(anycast_addr
)
1045 # Set ifaceobjcurr method and family
1046 ifaceobjcurr
.addr_method
= ifaceobj
.addr_method
1047 ifaceobjcurr
.addr_family
= ifaceobj
.addr_family
1048 if not runningaddrsdict
and not addrs
:
1050 runningaddrs
= runningaddrsdict
.keys() if runningaddrsdict
else []
1051 # Add /32 netmask to configured address without netmask.
1052 # This may happen on interfaces where pointopoint is used.
1053 runningaddrs
= [ addr
if '/' in addr
else addr
+ '/32' for addr
in runningaddrs
]
1054 if runningaddrs
!= addrs
:
1055 runningaddrsset
= set(runningaddrs
) if runningaddrs
else set([])
1056 addrsset
= set(addrs
) if addrs
else set([])
1057 if (ifaceobj
.flags
& iface
.HAS_SIBLINGS
):
1060 # only check for addresses present in running config
1061 addrsdiff
= addrsset
.difference(runningaddrsset
)
1063 if addr
in addrsdiff
:
1064 ifaceobjcurr
.update_config_with_status('address',
1067 ifaceobjcurr
.update_config_with_status('address',
1070 addrsdiff
= addrsset
.symmetric_difference(runningaddrsset
)
1071 for addr
in addrsset
.union(runningaddrsset
):
1072 if addr
in addrsdiff
:
1073 ifaceobjcurr
.update_config_with_status('address',
1076 ifaceobjcurr
.update_config_with_status('address',
1079 [ifaceobjcurr
.update_config_with_status('address',
1080 addr
, 0) for addr
in addrs
]
1081 #XXXX Check broadcast address, scope, etc
1084 def query_running_ipv6_addrgen(self
, ifaceobjrunning
):
1085 ipv6_addrgen
= self
.ipcmd
.get_ipv6_addrgen_mode(ifaceobjrunning
.name
)
1088 ifaceobjrunning
.update_config('ipv6-addrgen', 'off')
1090 def _query_running(self
, ifaceobjrunning
, ifaceobj_getfunc
=None):
1091 if not self
.ipcmd
.link_exists(ifaceobjrunning
.name
):
1092 self
.logger
.debug('iface %s not found' %ifaceobjrunning
.name
)
1095 self
.query_running_ipv6_addrgen(ifaceobjrunning
)
1097 dhclientcmd
= dhclient()
1098 if (dhclientcmd
.is_running(ifaceobjrunning
.name
) or
1099 dhclientcmd
.is_running6(ifaceobjrunning
.name
)):
1100 # If dhcp is configured on the interface, we skip it
1102 isloopback
= self
.ipcmd
.link_isloopback(ifaceobjrunning
.name
)
1104 default_addrs
= ['127.0.0.1/8', '::1/128']
1105 ifaceobjrunning
.addr_family
.append('inet')
1106 ifaceobjrunning
.addr_method
= 'loopback'
1109 runningaddrsdict
= self
.ipcmd
.get_running_addrs(ifaceobjrunning
)
1110 if runningaddrsdict
:
1111 [ifaceobjrunning
.update_config('address', addr
)
1112 for addr
, addrattrs
in runningaddrsdict
.items()
1113 if addr
not in default_addrs
]
1114 mtu
= self
.ipcmd
.link_get_mtu(ifaceobjrunning
.name
)
1116 (ifaceobjrunning
.name
== 'lo' and mtu
!= '16436') or
1117 (ifaceobjrunning
.name
!= 'lo' and
1118 mtu
!= self
.get_mod_subattr('mtu', 'default'))):
1119 ifaceobjrunning
.update_config('mtu', mtu
)
1120 alias
= self
.ipcmd
.link_get_alias(ifaceobjrunning
.name
)
1122 ifaceobjrunning
.update_config('alias', alias
)
1124 ipforward
= self
.read_file_oneline(
1125 '/proc/sys/net/ipv4/conf/%s/forwarding'
1126 %ifaceobjrunning
.name
)
1129 _run_ops
= {'up' : _up
,
1131 'query-checkcurr' : _query_check
,
1132 'query-running' : _query_running
}
1135 """ returns list of ops supported by this module """
1136 return self
._run
_ops
.keys()
1138 def _init_command_handlers(self
):
1140 self
.ipcmd
= LinkUtils()
1142 def run(self
, ifaceobj
, operation
, query_ifaceobj
=None, ifaceobj_getfunc
=None):
1143 """ run address configuration on the interface object passed as argument
1146 **ifaceobj** (object): iface object
1148 **operation** (str): any of 'up', 'down', 'query-checkcurr',
1151 query_ifaceobj (object): query check ifaceobject. This is only
1152 valid when op is 'query-checkcurr'. It is an object same as
1153 ifaceobj, but contains running attribute values and its config
1154 status. The modules can use it to return queried running state
1155 of interfaces. status is success if the running state is same
1156 as user required state in ifaceobj. error otherwise.
1158 if ifaceobj
.type == ifaceType
.BRIDGE_VLAN
:
1160 op_handler
= self
._run
_ops
.get(operation
)
1163 self
._init
_command
_handlers
()
1164 if operation
== 'query-checkcurr':
1165 op_handler(self
, ifaceobj
, query_ifaceobj
,
1166 ifaceobj_getfunc
=ifaceobj_getfunc
)
1168 op_handler(self
, ifaceobj
,
1169 ifaceobj_getfunc
=ifaceobj_getfunc
)