]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/addons/addressvirtual.py
python3: ipaddress is now part of the standard library (removing python-ipaddr)
[mirror_ifupdown2.git] / ifupdown2 / addons / addressvirtual.py
CommitLineData
35681c06 1#!/usr/bin/env python3
15ef32ea 2#
d486dd0d 3# Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved.
15ef32ea
RP
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6
15ef32ea
RP
7import os
8import glob
223ba5af 9import subprocess
15ef32ea 10
5bc963f0 11from collections import deque
5dded70e
JF
12from ipaddress import ip_network, IPv6Network
13
14def IPNetwork(ip):
15 return ip_network(ip, False)
d486dd0d
JF
16
17try:
223ba5af 18 from ifupdown2.lib.addon import Addon
d486dd0d 19 from ifupdown2.ifupdown.iface import *
7b711dc5 20 from ifupdown2.ifupdown.utils import utils
d486dd0d 21
32d448a8
JF
22 from ifupdown2.nlmanager.nlpacket import Link
23
d486dd0d
JF
24 from ifupdown2.ifupdownaddons.modulebase import moduleBase
25
26 import ifupdown2.ifupdown.statemanager as statemanager
23e8546d 27 import ifupdown2.ifupdown.policymanager as policymanager
d486dd0d
JF
28 import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
29 import ifupdown2.ifupdown.ifupdownconfig as ifupdownconfig
bd441a51 30except (ImportError, ModuleNotFoundError):
223ba5af 31 from lib.addon import Addon
d486dd0d 32 from ifupdown.iface import *
7b711dc5 33 from ifupdown.utils import utils
d486dd0d 34
32d448a8
JF
35 from nlmanager.nlpacket import Link
36
d486dd0d
JF
37 from ifupdownaddons.modulebase import moduleBase
38
39 import ifupdown.statemanager as statemanager
23e8546d 40 import ifupdown.policymanager as policymanager
d486dd0d
JF
41 import ifupdown.ifupdownflags as ifupdownflags
42 import ifupdown.ifupdownconfig as ifupdownconfig
43
44
223ba5af 45class addressvirtual(Addon, moduleBase):
15ef32ea
RP
46 """ ifupdown2 addon module to configure virtual addresses """
47
223ba5af
JF
48 _modinfo = {
49 "mhelp": "address module configures virtual addresses for interfaces. "
50 "It creates a macvlan interface for every mac ip address-virtual line",
51 "attrs": {
52 "address-virtual": {
53 "help": "bridge router virtual mac and ips",
54 "multivalue": True,
55 "validvals": ["<mac-ip/prefixlen-list>", ],
56 "example": ["address-virtual 00:11:22:33:44:01 11.0.1.1/24 11.0.1.2/24"]
57 },
58 "address-virtual-ipv6-addrgen": {
59 "help": "enable disable ipv6 link addrgenmode",
60 "validvals": ["on", "off"],
61 "default": "on",
62 "example": [
63 "address-virtual-ipv6-addrgen on",
64 "address-virtual-ipv6-addrgen off"
65 ]
66 },
67 "vrrp": {
68 "help": "VRRP support",
69 "multivalue": True,
70 "example": [
71 "vrrp 1 10.0.0.15/24 2001:0db8::0370:7334/64",
72 "vrrp 42 10.0.0.42/24"
73 ]
74 }
75 }
76 }
15ef32ea 77
223ba5af
JF
78 DEFAULT_IP_METRIC = 1024
79 ADDR_METRIC_SUPPORT = None
8e113d63 80
15ef32ea 81 def __init__(self, *args, **kargs):
223ba5af 82 Addon.__init__(self)
15ef32ea 83 moduleBase.__init__(self, *args, **kargs)
8e113d63 84 self._bridge_fdb_query_cache = {}
23e8546d
JF
85 self.addressvirtual_with_route_metric = utils.get_boolean_from_string(
86 policymanager.policymanager_api.get_module_globals(
87 module_name=self.__class__.__name__,
88 attr='addressvirtual_with_route_metric'
89 ),
90 default=True
91 )
15ef32ea 92
17da0561
JF
93 self.address_virtual_ipv6_addrgen_value_dict = {'on': 0, 'yes': 0, '0': 0, 'off': 1, 'no': 1, '1': 1}
94
223ba5af
JF
95 if addressvirtual.ADDR_METRIC_SUPPORT is None:
96 try:
97 cmd = [utils.ip_cmd, 'addr', 'help']
98 self.logger.info('executing %s addr help' % utils.ip_cmd)
99
100 process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
101 stdout, stderr = process.communicate()
102 addressvirtual.ADDR_METRIC_SUPPORT = '[ metric METRIC ]' in stderr or ''
103 self.logger.info('address metric support: %s' % ('OK' if addressvirtual.ADDR_METRIC_SUPPORT else 'KO'))
104 except Exception:
105 addressvirtual.ADDR_METRIC_SUPPORT = False
106 self.logger.info('address metric support: KO')
107
108 @classmethod
109 def addr_metric_support(cls):
110 return cls.ADDR_METRIC_SUPPORT
111
112 @classmethod
113 def get_default_ip_metric(cls):
114 return cls.DEFAULT_IP_METRIC
115
42e85fc8 116 def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
5bc963f0 117 if ifaceobj.get_attr_value('address-virtual') or ifaceobj.get_attr_value("vrrp"):
42e85fc8 118 ifaceobj.link_privflags |= ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE
15ef32ea 119
aaef0a79
RP
120 def _get_macvlan_prefix(self, ifaceobj):
121 return '%s-v' %ifaceobj.name[0:13].replace('.', '-')
122
223ba5af
JF
123 def get_vrrp_prefix(self, ifname, family):
124 return "vrrp%s-%s-" % (family, self.cache.get_ifindex(ifname))
8fb6dd67 125
e1601369 126 def _add_addresses_to_bridge(self, ifaceobj, hwaddress):
8e113d63 127 # XXX: batch the addresses
d486dd0d
JF
128 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
129 bridgename = ifaceobj.lowerifaces[0]
130 vlan = self._get_vlan_id(ifaceobj)
223ba5af
JF
131 if self.cache.bridge_is_vlan_aware(bridgename):
132 [self.iproute2.bridge_fdb_add(bridgename, addr,
e1601369 133 vlan) for addr in hwaddress]
223ba5af
JF
134 elif self.cache.link_is_bridge(ifaceobj.name):
135 [self.iproute2.bridge_fdb_add(ifaceobj.name, addr)
8e113d63 136 for addr in hwaddress]
e1601369
RP
137
138 def _remove_addresses_from_bridge(self, ifaceobj, hwaddress):
8e113d63 139 # XXX: batch the addresses
d486dd0d
JF
140 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
141 bridgename = ifaceobj.lowerifaces[0]
142 vlan = self._get_vlan_id(ifaceobj)
223ba5af 143 if self.cache.bridge_is_vlan_aware(bridgename):
55072bd1
ST
144 for addr in hwaddress:
145 try:
223ba5af 146 self.iproute2.bridge_fdb_del(bridgename, addr, vlan)
3b01ed76 147 except Exception as e:
55072bd1
ST
148 self.logger.debug("%s: %s" %(ifaceobj.name, str(e)))
149 pass
223ba5af 150 elif self.cache.link_is_bridge(ifaceobj.name):
55072bd1
ST
151 for addr in hwaddress:
152 try:
223ba5af 153 self.iproute2.bridge_fdb_del(ifaceobj.name, addr)
3b01ed76 154 except Exception as e:
55072bd1
ST
155 self.logger.debug("%s: %s" %(ifaceobj.name, str(e)))
156 pass
8e113d63
RP
157
158 def _get_bridge_fdbs(self, bridgename, vlan):
159 fdbs = self._bridge_fdb_query_cache.get(bridgename)
160 if not fdbs:
223ba5af 161 fdbs = self.iproute2.bridge_fdb_show_dev(bridgename)
8e113d63
RP
162 if not fdbs:
163 return
164 self._bridge_fdb_query_cache[bridgename] = fdbs
165 return fdbs.get(vlan)
166
167 def _check_addresses_in_bridge(self, ifaceobj, hwaddress):
168 """ If the device is a bridge, make sure the addresses
169 are in the bridge """
d486dd0d
JF
170 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
171 bridgename = ifaceobj.lowerifaces[0]
172 vlan = self._get_vlan_id(ifaceobj)
223ba5af 173 if self.cache.bridge_is_vlan_aware(bridgename):
d486dd0d 174 fdb_addrs = self._get_bridge_fdbs(bridgename, str(vlan))
5bc963f0 175 if not fdb_addrs:
8e113d63 176 return False
223ba5af 177 hwaddress_int = utils.mac_str_to_int(hwaddress)
5bc963f0 178 for mac in fdb_addrs:
223ba5af 179 if utils.mac_str_to_int(mac) == hwaddress_int:
5bc963f0
JF
180 return True
181 return False
8e113d63 182 return True
e1601369 183
00f6105d
RP
184 def _fix_connected_route(self, ifaceobj, vifacename, addr):
185 #
d486dd0d 186 # XXX: Hack to make sure the primary address
00f6105d
RP
187 # is the first in the routing table.
188 #
189 # We use `ip route get` on the vrr network to see which
190 # device the kernel returns. if it is the mac vlan device,
191 # flap the macvlan device to adjust the routing table entry.
d486dd0d 192 #
00f6105d
RP
193 # flapping the macvlan device makes sure the macvlan
194 # connected route goes through delete + add, hence adjusting
195 # the order in the routing table.
196 #
197 try:
198 self.logger.info('%s: checking route entry ...' %ifaceobj.name)
199 ip = IPNetwork(addr)
d486dd0d
JF
200
201 # we don't support ip6 route fix yet
202 if type(ip) == IPv6Network:
203 return
204
00f6105d
RP
205 route_prefix = '%s/%d' %(ip.network, ip.prefixlen)
206
aa895ecd 207 if ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE:
223ba5af 208 vrf_master = self.cache.get_master(ifaceobj.name)
aa895ecd
JF
209 else:
210 vrf_master = None
211
223ba5af 212 dev = self.iproute2.ip_route_get_dev(route_prefix, vrf_master=vrf_master)
aa895ecd 213
d486dd0d 214 if dev and dev != ifaceobj.name:
00f6105d
RP
215 self.logger.info('%s: preferred routing entry ' %ifaceobj.name +
216 'seems to be of the macvlan dev %s'
217 %vifacename +
218 ' .. flapping macvlan dev to fix entry.')
223ba5af
JF
219 self.iproute2.link_down(vifacename)
220 self.iproute2.link_up(vifacename)
3b01ed76 221 except Exception as e:
00f6105d 222 self.logger.debug('%s: fixing route entry failed (%s)'
d486dd0d 223 % (ifaceobj.name, str(e)))
00f6105d
RP
224 pass
225
55072bd1
ST
226 def _get_macs_from_old_config(self, ifaceobj=None):
227 """ This method returns a list of the mac addresses
228 in the address-virtual attribute for the bridge. """
229 maclist = []
230 saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name)
231 if not saved_ifaceobjs:
232 return maclist
233 # we need the old saved configs from the statemanager
234 for oldifaceobj in saved_ifaceobjs:
235 if not oldifaceobj.get_attr_value('address-virtual'):
236 continue
237 for av in oldifaceobj.get_attr_value('address-virtual'):
238 macip = av.split()
239 if len(macip) < 2:
240 self.logger.debug("%s: incorrect old address-virtual attrs '%s'"
241 %(oldifaceobj.name, av))
242 continue
243 maclist.append(macip[0])
244 return maclist
245
7b711dc5
JF
246 def get_addressvirtual_ipv6_addrgen_user_conf(self, ifaceobj):
247 ipv6_addrgen = ifaceobj.get_attr_value_first('address-virtual-ipv6-addrgen')
248
249 if ipv6_addrgen:
007cae35
JF
250 # IFLA_INET6_ADDR_GEN_MODE values:
251 # 0 = eui64
252 # 1 = none
17da0561 253 ipv6_addrgen_nl = self.address_virtual_ipv6_addrgen_value_dict.get(ipv6_addrgen.lower(), None)
007cae35
JF
254
255 if ipv6_addrgen_nl is None:
007cae35
JF
256 self.logger.warning('%s: invalid value "%s" for attribute address-virtual-ipv6-addrgen' % (ifaceobj.name, ipv6_addrgen))
257 else:
258 return True, ipv6_addrgen_nl
7b711dc5 259
17da0561
JF
260 else:
261 # if user didn't configure ipv6-addrgen, should we reset to default?
262 ipv6_addrgen_nl = self.address_virtual_ipv6_addrgen_value_dict.get(
263 self.get_attr_default_value('address-virtual-ipv6-addrgen'),
264 None
265 )
266 if ipv6_addrgen_nl is not None:
267 return True, ipv6_addrgen_nl
268
7b711dc5
JF
269 return False, None
270
e1601369 271 def _remove_running_address_config(self, ifaceobj):
223ba5af 272 if not self.cache.link_exists(ifaceobj.name):
15ef32ea 273 return
e1601369 274 hwaddress = []
223ba5af 275
709f7942
JF
276 for macvlan_prefix in [
277 self._get_macvlan_prefix(ifaceobj),
68c8d699
JF
278 self.get_vrrp_prefix(ifaceobj.name, "4"),
279 self.get_vrrp_prefix(ifaceobj.name, "6")
709f7942
JF
280 ]:
281 for macvlan_ifacename in glob.glob("/sys/class/net/%s*" % macvlan_prefix):
282 macvlan_ifacename = os.path.basename(macvlan_ifacename)
223ba5af 283 if not self.cache.link_exists(macvlan_ifacename):
709f7942 284 continue
223ba5af
JF
285 hwaddress.append(self.cache.get_link_address(macvlan_ifacename))
286 self.netlink.link_del(os.path.basename(macvlan_ifacename))
709f7942
JF
287 # XXX: Also delete any fdb addresses. This requires, checking mac address
288 # on individual macvlan interfaces and deleting the vlan from that.
223ba5af 289
e1601369
RP
290 if any(hwaddress):
291 self._remove_addresses_from_bridge(ifaceobj, hwaddress)
15ef32ea 292
e1601369
RP
293 def _remove_address_config(self, ifaceobj, address_virtual_list=None):
294 if not address_virtual_list:
295 self._remove_running_address_config(ifaceobj)
296 return
297
223ba5af 298 if not self.cache.link_exists(ifaceobj.name):
e1601369
RP
299 return
300 hwaddress = []
e1601369 301 av_idx = 0
aaef0a79 302 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
e1601369
RP
303 for av in address_virtual_list:
304 av_attrs = av.split()
e1601369
RP
305
306 # Delete the macvlan device on this device
cb46a208 307 macvlan_ifacename = '%s%d' %(macvlan_prefix, av_idx)
223ba5af 308 self.netlink.link_del(os.path.basename(macvlan_ifacename))
e1601369
RP
309 if av_attrs[0] != 'None':
310 hwaddress.append(av_attrs[0])
311 av_idx += 1
e1601369 312 self._remove_addresses_from_bridge(ifaceobj, hwaddress)
15ef32ea 313
4d3dc0f7 314 def check_mac_address(self, ifaceobj, mac):
5bc963f0 315 if mac == 'none':
d486dd0d 316 return True
4d3dc0f7 317 try:
586535e8 318 if int(mac.split(":")[0], 16) & 1 :
5b1fffaf
JF
319 self.log_error("%s: Multicast bit is set in the virtual mac address '%s'"
320 % (ifaceobj.name, mac), ifaceobj=ifaceobj)
4d3dc0f7
N
321 return False
322 return True
5b1fffaf 323 except ValueError:
4d3dc0f7
N
324 return False
325
42e85fc8
RP
326 def _fixup_vrf_enslavements(self, ifaceobj, ifaceobj_getfunc=None):
327 """ This function fixes up address virtual interfaces
328 (macvlans) on vrf slaves. Since this fixup is an overhead,
329 this must be called only in cases when ifupdown2 is
330 called on the vrf device or its slave and not when
331 ifupdown2 is called for all devices. When all
332 interfaces are brought up, the expectation is that
333 the normal path will fix up a vrf device or its slaves"""
334
335 if not ifaceobj_getfunc:
336 return
337 if ((ifaceobj.link_kind & ifaceLinkKind.VRF) and
223ba5af 338 self.cache.link_exists(ifaceobj.name)):
42e85fc8
RP
339 # if I am a vrf device and I have slaves
340 # that have address virtual config,
341 # enslave the slaves 'address virtual
342 # interfaces (macvlans)' to myself:
223ba5af 343 running_slaves = self.sysfs.link_get_lowers(ifaceobj.name)
42e85fc8
RP
344 if running_slaves:
345 # pick up any existing slaves of a vrf device and
346 # look for their upperdevices and enslave them to the
347 # vrf device:
348 for s in running_slaves:
349 sobjs = ifaceobj_getfunc(s)
350 if (sobjs and
351 (sobjs[0].link_privflags & ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE)):
352 # enslave all its upper devices to
353 # the vrf device
223ba5af 354 upperdevs = self.sysfs.link_get_uppers(sobjs[0].name)
42e85fc8
RP
355 if not upperdevs:
356 continue
357 for u in upperdevs:
358 # skip vrf device which
359 # will also show up in the
360 # upper device list
361 if u == ifaceobj.name:
362 continue
223ba5af
JF
363 self.netlink.link_set_master(u, ifaceobj.name)
364 self.netlink.link_up(u)
42e85fc8
RP
365 elif ((ifaceobj.link_privflags & ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE) and
366 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE) and
223ba5af 367 self.cache.link_exists(ifaceobj.name)):
42e85fc8
RP
368 # If I am a vrf slave and I have 'address virtual'
369 # config, make sure my addrress virtual interfaces
370 # (macvlans) are also enslaved to the vrf device
371 vrfname = ifaceobj.get_attr_value_first('vrf')
223ba5af 372 if not vrfname or not self.cache.link_exists(vrfname):
42e85fc8 373 return
223ba5af 374 running_uppers = self.sysfs.link_get_uppers(ifaceobj.name)
42e85fc8
RP
375 if not running_uppers:
376 return
377 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
378 if not macvlan_prefix:
379 return
380 for u in running_uppers:
381 if u == vrfname:
382 continue
383 if u.startswith(macvlan_prefix):
223ba5af
JF
384 self.netlink.link_set_master(u, vrfname)
385 self.netlink.link_up(u)
42e85fc8 386
32d448a8 387 def create_macvlan_and_apply_config(self, ifaceobj, intf_config_list, vrrp=False):
223ba5af 388
5bc963f0
JF
389 """
390 intf_config_list = [
391 {
392 "ifname": "macvlan_ifname",
393 "hwaddress": "macvlan_hwaddress",
394 "ips": [str(IPNetwork), ]
395 },
396 ]
397 """
223ba5af
JF
398 hw_address_list = []
399
400 if not intf_config_list:
401 return hw_address_list
402
5bc963f0
JF
403 user_configured_ipv6_addrgenmode, ipv6_addrgen_user_value = self.get_addressvirtual_ipv6_addrgen_user_conf(ifaceobj)
404 purge_existing = False if ifupdownflags.flags.PERFMODE else True
5bc963f0
JF
405 ifname = ifaceobj.name
406
223ba5af 407 update_mtu = lower_iface_mtu = lower_iface_mtu_str = None
5bc963f0
JF
408 if ifupdownconfig.config.get("adjust_logical_dev_mtu", "1") != "0":
409 if ifaceobj.lowerifaces and intf_config_list:
410 update_mtu = True
411
223ba5af
JF
412 if update_mtu:
413 lower_iface_mtu = self.cache.get_link_mtu(ifaceobj.name)
414 lower_iface_mtu_str = str(lower_iface_mtu)
415
416 self.iproute2.batch_start() # TODO: make sure we only do 1 ip link set down and set up (only one flap in the batch)
5bc963f0
JF
417
418 for intf_config_dict in intf_config_list:
419 link_created = False
420 macvlan_ifname = intf_config_dict.get("ifname")
421 macvlan_hwaddr = intf_config_dict.get("hwaddress")
e588acb7 422 macvlan_mode = intf_config_dict.get("mode")
5bc963f0
JF
423 ips = intf_config_dict.get("ips")
424
223ba5af
JF
425 if not self.cache.link_exists(macvlan_ifname):
426 # When creating VRRP macvlan with bridge mode, the kernel
427 # return an error: 'Invalid argument' (22)
428 # so for now we should only use the iproute2 API.
429 # try:
430 # self.netlink.link_add_macvlan(ifname, macvlan_ifname)
431 # except:
432 self.iproute2.link_add_macvlan(ifname, macvlan_ifname, macvlan_mode)
5bc963f0
JF
433 link_created = True
434
435 # first thing we need to handle vrf enslavement
436 if ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE:
223ba5af
JF
437 vrf_ifname = self.cache.get_master(ifaceobj.name)
438 if vrf_ifname:
439 self.iproute2.link_set_master(macvlan_ifname, vrf_ifname)
5bc963f0 440
92c2d4a9
QY
441 # if we are dealing with a VRRP macvlan we need to set addrgenmode
442 # to RANDOM, and protodown on
32d448a8
JF
443 if vrrp:
444 try:
223ba5af 445 self.iproute2.link_set_ipv6_addrgen(
32d448a8
JF
446 macvlan_ifname,
447 Link.IN6_ADDR_GEN_MODE_RANDOM,
448 link_created
449 )
450 except Exception as e:
451 self.logger.warning("%s: %s: ip link set dev %s addrgenmode random: "
452 "operation not supported: %s" % (ifname, macvlan_ifname, macvlan_ifname, str(e)))
92c2d4a9 453 try:
61e63e79 454 if link_created:
223ba5af 455 self.netlink.link_set_protodown_on(macvlan_ifname)
92c2d4a9
QY
456 except Exception as e:
457 self.logger.warning("%s: %s: ip link set dev %s protodown on: operation not supported: %s" % (ifname, macvlan_ifname, macvlan_ifname, str(e)))
32d448a8 458 elif user_configured_ipv6_addrgenmode:
223ba5af 459 self.iproute2.link_set_ipv6_addrgen(macvlan_ifname, ipv6_addrgen_user_value, link_created)
5bc963f0
JF
460
461 if macvlan_hwaddr:
223ba5af
JF
462 self.iproute2.link_set_address_and_keep_down(
463 macvlan_ifname,
464 macvlan_hwaddr,
465 keep_down=ifaceobj.link_privflags & ifaceLinkPrivFlags.KEEP_LINK_DOWN
466 )
5bc963f0
JF
467 hw_address_list.append(macvlan_hwaddr)
468
223ba5af
JF
469 if self.addressvirtual_with_route_metric and self.addr_metric_support():
470 metric = self.get_default_ip_metric()
5bc963f0
JF
471 else:
472 metric = None
473
223ba5af 474 self.iproute2.add_addresses(
5bc963f0
JF
475 ifaceobj,
476 macvlan_ifname,
477 ips,
478 purge_existing,
479 metric=metric
480 )
481
ee007539
JF
482 if ifaceobj.link_privflags & ifaceLinkPrivFlags.KEEP_LINK_DOWN:
483 self.logger.info("%s: keeping macvlan down - link-down yes on lower device %s" % (macvlan_ifname, ifname))
223ba5af 484 self.netlink.link_down(macvlan_ifname)
ee007539 485
5bc963f0
JF
486 # If link existed before, flap the link
487 if not link_created:
488
223ba5af 489 if not self.addressvirtual_with_route_metric or not self.addr_metric_support():
5bc963f0
JF
490 # if the system doesn't support ip addr set METRIC
491 # we need to do manually check the ordering of the ip4 routes
492 self._fix_connected_route(ifaceobj, macvlan_ifname, ips[0])
493
494 if update_mtu:
5bc963f0
JF
495 update_mtu = False
496
5bc963f0 497 try:
223ba5af 498 self.sysfs.link_set_mtu(macvlan_ifname, mtu_str=lower_iface_mtu_str, mtu_int=lower_iface_mtu)
5bc963f0 499 except Exception as e:
223ba5af 500 self.logger.info('%s: failed to set mtu %s: %s' % (macvlan_ifname, lower_iface_mtu, e))
5bc963f0
JF
501
502 # set macvlan device to up in anycase.
503 # since we auto create them here..we are responsible
504 # to bring them up here in the case they were brought down
505 # by some other entity in the system.
ee007539 506 if not ifaceobj.link_privflags & ifaceLinkPrivFlags.KEEP_LINK_DOWN:
223ba5af 507 self.netlink.link_up(macvlan_ifname)
5bc963f0
JF
508 else:
509 try:
223ba5af 510 if not self.addressvirtual_with_route_metric or not self.addr_metric_support():
5bc963f0
JF
511 # if the system doesn't support ip addr set METRIC
512 # we need to do manually check the ordering of the ip6 routes
223ba5af 513 self.iproute2.fix_ipv6_route_metric(ifaceobj, macvlan_ifname, ips)
5bc963f0
JF
514 except Exception as e:
515 self.logger.debug('fix_vrf_slave_ipv6_route_metric: failed: %s' % e)
516
517 # Disable IPv6 duplicate address detection on VRR interfaces
223ba5af
JF
518 sysctl_prefix = "net.ipv6.conf.%s" % macvlan_ifname
519
520 try:
521 syskey = "%s.%s" % (sysctl_prefix, "enhanced_dad")
522 if self.sysctl_get(syskey) != "0":
523 self.sysctl_set(syskey, "0")
524 except Exception as e:
525 self.logger.info("sysctl failure: operation not supported: %s" % str(e))
526
5bc963f0
JF
527 for key, sysval in {
528 "accept_dad": "0",
529 "dad_transmits": "0"
3b01ed76 530 }.items():
223ba5af 531 syskey = "%s.%s" % (sysctl_prefix, key)
5bc963f0
JF
532 if self.sysctl_get(syskey) != sysval:
533 self.sysctl_set(syskey, sysval)
534
223ba5af 535 self.iproute2.batch_commit()
5bc963f0
JF
536 return hw_address_list
537
42e85fc8
RP
538 def _up(self, ifaceobj, ifaceobj_getfunc=None):
539 if not ifupdownflags.flags.ALL:
540 self._fixup_vrf_enslavements(ifaceobj, ifaceobj_getfunc)
5bc963f0 541
15ef32ea 542 address_virtual_list = ifaceobj.get_attr_value('address-virtual')
5bc963f0
JF
543 vrr_config_list = ifaceobj.get_attr_value("vrrp")
544
545 if not address_virtual_list and not vrr_config_list:
15ef32ea 546 # XXX: address virtual is not present. In which case,
00f6105d 547 # delete stale macvlan devices.
5bc963f0 548 self._remove_running_address_config(ifaceobj)
15ef32ea
RP
549 return
550
5bc963f0
JF
551 if ifaceobj.upperifaces and not ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE:
552 self.log_error("%s: invalid placement of address-virtual/vrrp lines "
553 "(must be configured under an interface "
554 "with no upper interfaces or parent interfaces)"
555 % ifaceobj.name, ifaceobj)
f466af7a 556
223ba5af 557 if not self.cache.link_exists(ifaceobj.name):
15ef32ea 558 return
5bc963f0
JF
559
560 addr_virtual_macs = self.create_macvlan_and_apply_config(
561 ifaceobj,
562 self.translate_addrvirtual_user_config_to_list(
563 ifaceobj,
564 address_virtual_list
565 )
566 )
567
568 vrr_macs = self.create_macvlan_and_apply_config(
569 ifaceobj,
570 self.translate_vrr_user_config_to_list(
571 ifaceobj,
572 vrr_config_list
32d448a8
JF
573 ),
574 vrrp=True
5bc963f0
JF
575 )
576
577 hw_address_list = addr_virtual_macs + vrr_macs
578
579 # check the statemanager for old configs.
580 # We need to remove only the previously configured FDB entries
581 oldmacs = self._get_macs_from_old_config(ifaceobj)
582 # get a list of fdbs in old that are not in new config meaning they should
583 # be removed since they are gone from the config
584 removed_macs = [mac for mac in oldmacs if mac.lower() not in hw_address_list]
585 self._remove_addresses_from_bridge(ifaceobj, removed_macs)
586 # if ifaceobj is a bridge and bridge is a vlan aware bridge
587 # add the vid to the bridge
588 self._add_addresses_to_bridge(ifaceobj, hw_address_list)
589
5bc963f0
JF
590 def translate_vrr_user_config_to_list(self, ifaceobj, vrr_config_list, ifquery=False):
591 """
592 If (IPv4 addresses provided):
593 00:00:5e:00:01:<V>
594 else if (IPv6 addresses provided):
595 00:00:5e:00:02:<V>
596
597 vrrp 1 10.0.0.15/24
598 vrrp 1 2001:0db8::0370:7334/64
599
600 # Translate:
601 # vrrp 255 10.0.0.15/24 10.0.0.2/1
602 # To:
603 # [
604 # {
605 # "ifname": "macvlan_ifname",
606 # "hwaddress": "macvlan_hwaddress",
e588acb7 607 # "mode": "macvlan_mode",
5bc963f0
JF
608 # "ips": [str(IPNetwork), ]
609 # },
610 # ]
611 """
612 ifname = ifaceobj.name
613 user_config_list = []
614
8fb6dd67 615 for index, config in enumerate(vrr_config_list or []):
5bc963f0
JF
616 vrrp_id, ip_addrs = config.split(" ", 1)
617 hex_id = '%02x' % int(vrrp_id)
618 ip4 = []
619 ip6 = []
620
621 for ip_addr in ip_addrs.split():
622 ip_network_obj = IPNetwork(ip_addr)
623 is_ip6 = isinstance(ip_network_obj, IPv6Network)
624
625 if is_ip6:
626 ip6.append(ip_addr)
627 else:
628 ip4.append(ip_addr)
629
3e112a1c
JF
630 macvlan_ip4_ifname = "%s%s" % (self.get_vrrp_prefix(ifname, "4"), vrrp_id)
631 macvlan_ip6_ifname = "%s%s" % (self.get_vrrp_prefix(ifname, "6"), vrrp_id)
5bc963f0 632
5bc963f0 633 if ip4 or ifquery:
b994bd39 634 merged_with_existing_obj = False
5bc963f0 635 macvlan_ip4_mac = "00:00:5e:00:01:%s" % hex_id
223ba5af 636 macvlan_ip4_mac_int = utils.mac_str_to_int(macvlan_ip4_mac)
b994bd39
JF
637 # if the vrr config is defined in different lines for the same ID
638 # we need to save the ip4 and ip6 in the objects we previously
639 # created, example:
640 # vrrp 255 10.0.0.15/24 10.0.0.2/15
641 # vrrp 255 fe80::a00:27ff:fe04:42/64
642 for obj in user_config_list:
643 if obj.get("hwaddress_int") == macvlan_ip4_mac_int:
644 obj["ips"] += ip4
645 merged_with_existing_obj = True
646
647 if not merged_with_existing_obj:
648 # if ip4 config wasn't merge with an existing object
649 # we need to insert it in our list
650 user_config_list.append({
651 "ifname": macvlan_ip4_ifname,
652 "hwaddress": macvlan_ip4_mac,
653 "hwaddress_int": macvlan_ip4_mac_int,
654 "mode": "bridge",
655 "ips": ip4,
656 "id": vrrp_id
657 })
bd451a48
JF
658 elif not ip4 and not ifquery:
659 # special check to see if all ipv4 were removed from the vrrp
660 # configuration, if so we need to remove the associated macvlan
223ba5af
JF
661 if self.cache.link_exists(macvlan_ip4_ifname):
662 self.netlink.link_del(macvlan_ip4_ifname)
5bc963f0
JF
663
664 if ip6 or ifquery:
b994bd39 665 merged_with_existing_obj = False
5bc963f0 666 macvlan_ip6_mac = "00:00:5e:00:02:%s" % hex_id
223ba5af 667 macvlan_ip6_mac_int = utils.mac_str_to_int(macvlan_ip6_mac)
b994bd39
JF
668 # if the vrr config is defined in different lines for the same ID
669 # we need to save the ip4 and ip6 in the objects we previously
670 # created, example:
671 # vrrp 255 10.0.0.15/24 10.0.0.2/15
672 # vrrp 255 fe80::a00:27ff:fe04:42/64
673
674 for obj in user_config_list:
675 if obj.get("hwaddress_int") == macvlan_ip6_mac_int:
676 obj["ips"] += ip6
677 merged_with_existing_obj = True
678
679 if not merged_with_existing_obj:
680 # if ip6 config wasn't merge with an existing object
681 # we need to insert it in our list
682 user_config_list.append({
683 "ifname": macvlan_ip6_ifname,
684 "hwaddress": macvlan_ip6_mac,
685 "hwaddress_int": macvlan_ip6_mac_int,
686 "mode": "bridge",
687 "ips": ip6,
688 "id": vrrp_id
689 })
bd451a48
JF
690 elif not ip6 and not ifquery:
691 # special check to see if all ipv6 were removed from the vrrp
692 # configuration, if so we need to remove the associated macvlan
223ba5af
JF
693 if self.cache.link_exists(macvlan_ip6_ifname):
694 self.netlink.link_del(macvlan_ip6_ifname)
5bc963f0 695
c02de75e
JF
696 if not ifquery:
697 # check if vrrp attribute was removed/re-assigned
698 old_vrr_ids = set()
699
700 try:
701 for old_ifaceobj in statemanager.statemanager_api.get_ifaceobjs(ifname) or []:
702 for vrr_config in old_ifaceobj.get_attr_value("vrrp") or []:
703 try:
704 old_vrr_ids.add(vrr_config.split()[0])
705 except:
706 continue
707
708 if old_vrr_ids:
709
710 for config in user_config_list:
711 try:
712 old_vrr_ids.remove(config["id"])
713 except KeyError:
714 pass
715
716 for id_to_remove in old_vrr_ids:
717 macvlan_ip4_ifname = "%s%s" % (self.get_vrrp_prefix(ifname, "4"), id_to_remove)
718 macvlan_ip6_ifname = "%s%s" % (self.get_vrrp_prefix(ifname, "6"), id_to_remove)
719
223ba5af
JF
720 if self.cache.link_exists(macvlan_ip4_ifname):
721 self.netlink.link_del(macvlan_ip4_ifname)
c02de75e 722
223ba5af
JF
723 if self.cache.link_exists(macvlan_ip6_ifname):
724 self.netlink.link_del(macvlan_ip6_ifname)
c02de75e
JF
725
726 except Exception as e:
727 self.logger.debug("%s: vrrp: failure while removing unused macvlan(s)" % ifname)
728
5bc963f0
JF
729 return user_config_list
730
731 def translate_addrvirtual_user_config_to_list(self, ifaceobj, address_virtual_list):
732 """
733 # Translate:
734 # address-virtual 00:11:22:33:44:01 2001:0db8::0370:7334/64 11.0.1.1/24 11.0.1.2/24
735 # To:
736 # [
737 # {
738 # "ifname": "macvlan_ifname",
739 # "hwaddress": "macvlan_hwaddress",
740 # "ips": [str(IPNetwork), ]
741 # },
742 # ]
743 """
744 user_config_list = []
745
746 if not address_virtual_list:
747 return user_config_list
748
749 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
750
751 for index, addr_virtual in enumerate(address_virtual_list):
752 av_attrs = addr_virtual.split()
5bc963f0
JF
753 mac = av_attrs[0]
754 if mac:
755 mac = mac.lower()
756
757 if not self.check_mac_address(ifaceobj, mac):
758 continue
759
e588acb7
JF
760 config = {
761 "ifname": "%s%d" % (macvlan_prefix, index),
762 "mode": "private"
763 }
5bc963f0
JF
764
765 if mac != "none":
766 config["hwaddress"] = mac
223ba5af 767 config["hwaddress_int"] = utils.mac_str_to_int(mac)
5bc963f0
JF
768
769 ip_network_obj_list = []
770 for ip in av_attrs[1:]:
771 ip_network_obj_list.append(str(IPNetwork(ip)))
772
773 config["ips"] = ip_network_obj_list
774 user_config_list.append(config)
775
776 return user_config_list
777
42e85fc8 778 def _down(self, ifaceobj, ifaceobj_getfunc=None):
15ef32ea 779 try:
cb46a208
RP
780 self._remove_address_config(ifaceobj,
781 ifaceobj.get_attr_value('address-virtual'))
5bc963f0
JF
782
783 #### VRR
784 hwaddress = []
68c8d699 785 for vrr_prefix in [self.get_vrrp_prefix(ifaceobj.name, "4"), self.get_vrrp_prefix(ifaceobj.name, "6")]:
5bc963f0
JF
786 for macvlan_ifacename in glob.glob("/sys/class/net/%s*" % vrr_prefix):
787 macvlan_ifacename = os.path.basename(macvlan_ifacename)
223ba5af 788 if not self.cache.link_exists(macvlan_ifacename):
5bc963f0 789 continue
223ba5af
JF
790 hwaddress.append(self.cache.get_link_address(macvlan_ifacename))
791 self.netlink.link_del(macvlan_ifacename)
5bc963f0
JF
792 # XXX: Also delete any fdb addresses. This requires, checking mac address
793 # on individual macvlan interfaces and deleting the vlan from that.
5bc963f0
JF
794 if any(hwaddress):
795 self._remove_addresses_from_bridge(ifaceobj, hwaddress)
3b01ed76 796 except Exception as e:
5bc963f0
JF
797 import traceback
798 traceback.print_exc()
15ef32ea
RP
799 self.log_warn(str(e))
800
801 def _query_check(self, ifaceobj, ifaceobjcurr):
5bc963f0 802
223ba5af 803 if not self.cache.link_exists(ifaceobj.name):
cb46a208 804 return
007cae35
JF
805
806 user_config_address_virtual_ipv6_addr = ifaceobj.get_attr_value_first('address-virtual-ipv6-addrgen')
807 if user_config_address_virtual_ipv6_addr and user_config_address_virtual_ipv6_addr not in utils._string_values:
808 ifaceobjcurr.update_config_with_status('address-virtual-ipv6-addrgen', user_config_address_virtual_ipv6_addr, 1)
809 user_config_address_virtual_ipv6_addr = None
5bc963f0
JF
810
811 address_virtual_list = ifaceobj.get_attr_value('address-virtual')
812
813 macvlans_running_ipv6_addr_virtual = self.query_check_macvlan_config(
814 ifaceobj,
815 ifaceobjcurr,
816 "address-virtual",
817 user_config_address_virtual_ipv6_addr,
818 virtual_addr_list_raw=address_virtual_list,
819 macvlan_config_list=self.translate_addrvirtual_user_config_to_list(
820 ifaceobj,
821 address_virtual_list
822 )
823 )
824
825 vrr_config_list = ifaceobj.get_attr_value("vrrp")
826
827 macvlans_running_ipv6_addr_vrr = self.query_check_macvlan_config(
828 ifaceobj,
829 ifaceobjcurr,
830 "vrrp",
831 user_config_address_virtual_ipv6_addr,
832 virtual_addr_list_raw=vrr_config_list,
833 macvlan_config_list=self.translate_vrr_user_config_to_list(
834 ifaceobj,
835 vrr_config_list,
836 ifquery=True
837 )
838 )
839
840 macvlans_running_ipv6_addr = macvlans_running_ipv6_addr_virtual + macvlans_running_ipv6_addr_vrr
841 if user_config_address_virtual_ipv6_addr:
842 bool_user_ipv6_addrgen = utils.get_boolean_from_string(user_config_address_virtual_ipv6_addr)
843 for running_ipv6_addrgen in macvlans_running_ipv6_addr:
844 if (not bool_user_ipv6_addrgen) != running_ipv6_addrgen:
845 ifaceobjcurr.update_config_with_status('address-virtual-ipv6-addrgen', user_config_address_virtual_ipv6_addr, 1)
846 return
847 ifaceobjcurr.update_config_with_status('address-virtual-ipv6-addrgen', user_config_address_virtual_ipv6_addr, 0)
848
223ba5af
JF
849 @staticmethod
850 def compare_user_config_vs_running_state(running_addrs, user_addrs):
851 ip4 = []
852 ip6 = []
853
854 for ip in user_addrs or []:
855 obj = IPNetwork(ip)
856
857 if type(obj) == IPv6Network:
858 ip6.append(obj)
859 else:
860 ip4.append(obj)
861
862 running_ipobj = []
863 for ip in running_addrs or []:
864 running_ipobj.append(IPNetwork(ip))
865
866 return running_ipobj == (ip4 + ip6)
867
5bc963f0
JF
868 def query_check_macvlan_config(self, ifaceobj, ifaceobjcurr, attr_name, user_config_address_virtual_ipv6_addr, virtual_addr_list_raw, macvlan_config_list):
869 """
870 macvlan_config_list = [
871 {
872 "ifname": "macvlan_ifname",
873 "hwaddress": "macvlan_hwaddress",
874 "ips": [str(IPNetwork), ]
875 },
876 ]
877 """
878 is_vrr = attr_name == "vrrp"
007cae35
JF
879 macvlans_running_ipv6_addr = []
880
5bc963f0
JF
881 if not virtual_addr_list_raw:
882 return macvlans_running_ipv6_addr
883
884 macvlan_config_queue = deque(macvlan_config_list)
885
886 while macvlan_config_queue:
887
888 ip4_config = None
889 ip6_config = None
890
891 config = macvlan_config_queue.popleft()
892
893 if is_vrr:
894 ip4_config = config
895 ip6_config = macvlan_config_queue.popleft()
896
897 macvlan_ifacename = config.get("ifname")
15ef32ea 898
223ba5af 899 if not self.cache.link_exists(macvlan_ifacename):
5bc963f0 900 ifaceobjcurr.update_config_with_status(attr_name, "", 1)
cb46a208 901 continue
007cae35 902
5bc963f0
JF
903 macvlan_hwaddress = config.get("hwaddress")
904 macvlan_hwaddress_int = config.get("hwaddress_int")
905
007cae35 906 if user_config_address_virtual_ipv6_addr:
223ba5af 907 macvlans_running_ipv6_addr.append(self.cache.get_link_ipv6_addrgen_mode(macvlan_ifacename))
007cae35 908
cb46a208 909 # Check mac and ip address
223ba5af
JF
910 rhwaddress = ip4_macvlan_hwaddress = self.cache.get_link_address(macvlan_ifacename)
911 raddrs = ip4_running_addrs =[str(ip) for ip in self.cache.get_ifupdown2_addresses_list(
d486dd0d 912 ifname=macvlan_ifacename,
223ba5af
JF
913 ifaceobj_list=[ifaceobj],
914 with_address_virtual=True
915 )]
007cae35 916
5bc963f0
JF
917 if not is_vrr:
918 ips = config.get("ips")
919
223ba5af 920 if not rhwaddress:
5bc963f0
JF
921 ifaceobjcurr.update_config_with_status(attr_name, "", 1)
922 continue
923
924 try:
223ba5af
JF
925 if utils.mac_str_to_int(rhwaddress) == macvlan_hwaddress_int \
926 and self.compare_user_config_vs_running_state(raddrs, ips) \
5bc963f0
JF
927 and self._check_addresses_in_bridge(ifaceobj, macvlan_hwaddress):
928 ifaceobjcurr.update_config_with_status(
929 attr_name,
930 " ".join(virtual_addr_list_raw),
931 0
932 )
933 else:
c3231ed0
JF
934 if raddrs:
935 address_virtual_value = "%s %s" % (rhwaddress, " ".join(raddrs))
936 else:
937 address_virtual_value = rhwaddress
938
939 ifaceobjcurr.update_config_with_status(attr_name, address_virtual_value, 1)
5bc963f0 940 except:
c3231ed0
JF
941 if raddrs:
942 address_virtual_value = "%s %s" % (rhwaddress, " ".join(raddrs))
943 else:
944 address_virtual_value = rhwaddress
945
946 ifaceobjcurr.update_config_with_status(attr_name, address_virtual_value, 1)
5bc963f0
JF
947 else:
948 # VRRP
949
950 ok = False
951 # check macvlan ip4 hwaddress (only if ip4 were provided by the user)
952 if not ip4_config.get("ips") or ip4_macvlan_hwaddress == ip4_config.get("hwaddress"):
953 ip6_macvlan_ifname = ip6_config.get("ifname")
954 ip6_macvlan_hwaddress = ip6_config.get("hwaddress")
955
956 # check macvlan ip6 hwaddress (only if ip6 were provided by the user)
223ba5af 957 if not ip6_config.get("ips") or self.cache.get_link_address_raw(ip6_macvlan_ifname) == ip6_config.get("hwaddress_int"):
5bc963f0
JF
958
959 # check all ip4
223ba5af 960 if self.compare_user_config_vs_running_state(
5bc963f0
JF
961 ip4_running_addrs,
962 ip4_config.get("ips")
963 ) and self._check_addresses_in_bridge(ifaceobj, ip4_macvlan_hwaddress):
223ba5af 964 ip6_running_addrs = [str(ip) for ip in self.cache.get_ifupdown2_addresses_list(
5bc963f0
JF
965 ifname=ip6_macvlan_ifname,
966 details=False,
223ba5af
JF
967 ifaceobj_list=[ifaceobj],
968 with_address_virtual=True
969 )]
5bc963f0
JF
970
971 # check all ip6
223ba5af 972 if self.compare_user_config_vs_running_state(
5bc963f0
JF
973 ip6_running_addrs,
974 ip6_config.get("ips")
223ba5af 975 ) and self._check_addresses_in_bridge(ifaceobj, ip6_macvlan_hwaddress):
5bc963f0
JF
976 ifaceobjcurr.update_config_with_status(
977 attr_name,
978 "%s %s" % (ip4_config.get("id"), " ".join(ip4_config.get("ips") + ip6_config.get("ips"))),
979 0
980 )
981 ok = True
982
983 if not ok:
984 ifaceobjcurr.update_config_with_status(
985 attr_name,
986 "%s %s" % (ip4_config.get("id"), " ".join(ip4_config.get("ips") + ip6_config.get("ips"))),
987 1
988 )
989
990 return macvlans_running_ipv6_addr
15ef32ea 991
42e85fc8 992 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
aaef0a79 993 macvlan_prefix = self._get_macvlan_prefix(ifaceobjrunning)
223ba5af 994 address_virtuals = glob.glob("/sys/class/net/%s*" %macvlan_prefix)
007cae35 995 macvlans_ipv6_addrgen_list = []
8e113d63
RP
996 for av in address_virtuals:
997 macvlan_ifacename = os.path.basename(av)
223ba5af
JF
998 rhwaddress = self.cache.get_link_address(macvlan_ifacename)
999 raddress = [str(ip) for ip in self.cache.get_ifupdown2_addresses_list(
1000 ifaceobj_list=ifaceobj_getfunc(ifaceobjrunning.name) or [],
1001 ifname=ifaceobjrunning.name,
1002 with_address_virtual=True
1003 )]
c3175b31
JF
1004
1005 raddress = list(set(raddress))
1006
8e113d63 1007 if not raddress:
c46af1c9 1008 self.logger.warning('%s: no running addresses'
8e113d63
RP
1009 %ifaceobjrunning.name)
1010 raddress = []
1011 ifaceobjrunning.update_config('address-virtual',
c3175b31 1012 '%s %s' %(rhwaddress, ' '.join(raddress)))
007cae35 1013
223ba5af 1014 macvlans_ipv6_addrgen_list.append((macvlan_ifacename, self.cache.get_link_ipv6_addrgen_mode(macvlan_ifacename)))
007cae35
JF
1015
1016 macvlan_count = len(address_virtuals)
1017 if not macvlan_count:
1018 return
1019 ipv6_addrgen = macvlans_ipv6_addrgen_list[0][1]
1020
1021 for macvlan_ifname, macvlan_ipv6_addrgen in macvlans_ipv6_addrgen_list:
1022 if macvlan_ipv6_addrgen != ipv6_addrgen:
1023 # one macvlan has a different ipv6-addrgen configuration
1024 # we simply return, ifquery-running will print the macvlan
1025 # stanzas with the ipv6-addrgen on/off attribute
1026 return
1027 ifaceobjrunning.update_config('address-virtual-ipv6-addrgen', 'off' if ipv6_addrgen else 'on')
1028
223ba5af
JF
1029 _run_ops = {
1030 'up': _up,
1031 'down': _down,
1032 'query-checkcurr': _query_check,
1033 'query-running': _query_running
1034 }
15ef32ea
RP
1035
1036 def get_ops(self):
1037 """ returns list of ops supported by this module """
3b01ed76 1038 return list(self._run_ops.keys())
15ef32ea 1039
15ef32ea 1040
42e85fc8
RP
1041 def run(self, ifaceobj, operation, query_ifaceobj=None,
1042 ifaceobj_getfunc=None, **extra_args):
15ef32ea
RP
1043 """ run vlan configuration on the interface object passed as argument
1044
1045 Args:
1046 **ifaceobj** (object): iface object
1047
1048 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
1049 'query-running'
1050 Kwargs:
1051 **query_ifaceobj** (object): query check ifaceobject. This is only
1052 valid when op is 'query-checkcurr'. It is an object same as
1053 ifaceobj, but contains running attribute values and its config
1054 status. The modules can use it to return queried running state
1055 of interfaces. status is success if the running state is same
1056 as user required state in ifaceobj. error otherwise.
1057 """
84ca006f
RP
1058 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
1059 return
15ef32ea
RP
1060 op_handler = self._run_ops.get(operation)
1061 if not op_handler:
1062 return
223ba5af 1063
15ef32ea
RP
1064 if operation == 'query-checkcurr':
1065 op_handler(self, ifaceobj, query_ifaceobj)
1066 else:
42e85fc8 1067 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)