]> git.proxmox.com Git - mirror_ifupdown2.git/blame - ifupdown2/addons/addressvirtual.py
addons: ppp: fixes PEP8 warning
[mirror_ifupdown2.git] / ifupdown2 / addons / addressvirtual.py
CommitLineData
15ef32ea
RP
1#!/usr/bin/python
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
9
d486dd0d
JF
10from ipaddr import IPNetwork, IPv6Network
11
12try:
13 from ifupdown2.ifupdown.iface import *
7b711dc5 14 from ifupdown2.ifupdown.utils import utils
d486dd0d
JF
15 from ifupdown2.ifupdown.netlink import netlink
16
17 from ifupdown2.ifupdownaddons.LinkUtils import LinkUtils
18 from ifupdown2.ifupdownaddons.modulebase import moduleBase
19
20 import ifupdown2.ifupdown.statemanager as statemanager
23e8546d 21 import ifupdown2.ifupdown.policymanager as policymanager
d486dd0d
JF
22 import ifupdown2.ifupdown.ifupdownflags as ifupdownflags
23 import ifupdown2.ifupdown.ifupdownconfig as ifupdownconfig
24except ImportError:
25 from ifupdown.iface import *
7b711dc5 26 from ifupdown.utils import utils
d486dd0d
JF
27 from ifupdown.netlink import netlink
28
29 from ifupdownaddons.LinkUtils import LinkUtils
30 from ifupdownaddons.modulebase import moduleBase
31
32 import ifupdown.statemanager as statemanager
23e8546d 33 import ifupdown.policymanager as policymanager
d486dd0d
JF
34 import ifupdown.ifupdownflags as ifupdownflags
35 import ifupdown.ifupdownconfig as ifupdownconfig
36
37
15ef32ea
RP
38class addressvirtual(moduleBase):
39 """ ifupdown2 addon module to configure virtual addresses """
40
41 _modinfo = {'mhelp' : 'address module configures virtual addresses for ' +
42 'interfaces. It creates a macvlan interface for ' +
43 'every mac ip address-virtual line',
44 'attrs' : {
45 'address-virtual' :
482b2fab 46 { 'help' : 'bridge router virtual mac and ips',
100ab3ea 47 'multivalue' : True,
2c592263 48 'validvals' : ['<mac-ip/prefixlen-list>',],
7b711dc5
JF
49 'example': ['address-virtual 00:11:22:33:44:01 11.0.1.1/24 11.0.1.2/24']
50 },
51 'address-virtual-ipv6-addrgen': {
52 'help': 'enable disable ipv6 link addrgenmode',
53 'validvals': ['on', 'off'],
54 'default': 'on',
55 'example': [
b478792b
JF
56 'address-virtual-ipv6-addrgen on',
57 'address-virtual-ipv6-addrgen off'
7b711dc5
JF
58 ]
59 }
60 }}
15ef32ea 61
8e113d63 62
15ef32ea
RP
63 def __init__(self, *args, **kargs):
64 moduleBase.__init__(self, *args, **kargs)
65 self.ipcmd = None
8e113d63 66 self._bridge_fdb_query_cache = {}
23e8546d
JF
67 self.addressvirtual_with_route_metric = utils.get_boolean_from_string(
68 policymanager.policymanager_api.get_module_globals(
69 module_name=self.__class__.__name__,
70 attr='addressvirtual_with_route_metric'
71 ),
72 default=True
73 )
15ef32ea 74
42e85fc8
RP
75 def get_dependent_ifacenames(self, ifaceobj, ifacenames_all=None):
76 if ifaceobj.get_attr_value('address-virtual'):
77 ifaceobj.link_privflags |= ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE
15ef32ea 78
aaef0a79
RP
79 def _get_macvlan_prefix(self, ifaceobj):
80 return '%s-v' %ifaceobj.name[0:13].replace('.', '-')
81
e1601369 82 def _add_addresses_to_bridge(self, ifaceobj, hwaddress):
8e113d63 83 # XXX: batch the addresses
d486dd0d
JF
84 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
85 bridgename = ifaceobj.lowerifaces[0]
86 vlan = self._get_vlan_id(ifaceobj)
e1601369
RP
87 if self.ipcmd.bridge_is_vlan_aware(bridgename):
88 [self.ipcmd.bridge_fdb_add(bridgename, addr,
89 vlan) for addr in hwaddress]
8e113d63
RP
90 elif self.ipcmd.is_bridge(ifaceobj.name):
91 [self.ipcmd.bridge_fdb_add(ifaceobj.name, addr)
92 for addr in hwaddress]
e1601369
RP
93
94 def _remove_addresses_from_bridge(self, ifaceobj, hwaddress):
8e113d63 95 # XXX: batch the addresses
d486dd0d
JF
96 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
97 bridgename = ifaceobj.lowerifaces[0]
98 vlan = self._get_vlan_id(ifaceobj)
e1601369 99 if self.ipcmd.bridge_is_vlan_aware(bridgename):
55072bd1
ST
100 for addr in hwaddress:
101 try:
102 self.ipcmd.bridge_fdb_del(bridgename, addr, vlan)
103 except Exception, e:
104 self.logger.debug("%s: %s" %(ifaceobj.name, str(e)))
105 pass
8e113d63 106 elif self.ipcmd.is_bridge(ifaceobj.name):
55072bd1
ST
107 for addr in hwaddress:
108 try:
109 self.ipcmd.bridge_fdb_del(ifaceobj.name, addr)
110 except Exception, e:
111 self.logger.debug("%s: %s" %(ifaceobj.name, str(e)))
112 pass
8e113d63
RP
113
114 def _get_bridge_fdbs(self, bridgename, vlan):
115 fdbs = self._bridge_fdb_query_cache.get(bridgename)
116 if not fdbs:
117 fdbs = self.ipcmd.bridge_fdb_show_dev(bridgename)
118 if not fdbs:
119 return
120 self._bridge_fdb_query_cache[bridgename] = fdbs
121 return fdbs.get(vlan)
122
123 def _check_addresses_in_bridge(self, ifaceobj, hwaddress):
124 """ If the device is a bridge, make sure the addresses
125 are in the bridge """
d486dd0d
JF
126 if ifaceobj.link_kind & ifaceLinkKind.VLAN:
127 bridgename = ifaceobj.lowerifaces[0]
128 vlan = self._get_vlan_id(ifaceobj)
8e113d63 129 if self.ipcmd.bridge_is_vlan_aware(bridgename):
d486dd0d 130 fdb_addrs = self._get_bridge_fdbs(bridgename, str(vlan))
8e113d63
RP
131 if not fdb_addrs or hwaddress not in fdb_addrs:
132 return False
133 return True
e1601369 134
00f6105d
RP
135 def _fix_connected_route(self, ifaceobj, vifacename, addr):
136 #
d486dd0d 137 # XXX: Hack to make sure the primary address
00f6105d
RP
138 # is the first in the routing table.
139 #
140 # We use `ip route get` on the vrr network to see which
141 # device the kernel returns. if it is the mac vlan device,
142 # flap the macvlan device to adjust the routing table entry.
d486dd0d 143 #
00f6105d
RP
144 # flapping the macvlan device makes sure the macvlan
145 # connected route goes through delete + add, hence adjusting
146 # the order in the routing table.
147 #
148 try:
149 self.logger.info('%s: checking route entry ...' %ifaceobj.name)
150 ip = IPNetwork(addr)
d486dd0d
JF
151
152 # we don't support ip6 route fix yet
153 if type(ip) == IPv6Network:
154 return
155
00f6105d
RP
156 route_prefix = '%s/%d' %(ip.network, ip.prefixlen)
157
aa895ecd
JF
158 if ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE:
159 vrf_master = self.ipcmd.link_get_master(ifaceobj.name)
160 else:
161 vrf_master = None
162
163 dev = self.ipcmd.ip_route_get_dev(route_prefix, vrf_master=vrf_master)
164
d486dd0d 165 if dev and dev != ifaceobj.name:
00f6105d
RP
166 self.logger.info('%s: preferred routing entry ' %ifaceobj.name +
167 'seems to be of the macvlan dev %s'
168 %vifacename +
169 ' .. flapping macvlan dev to fix entry.')
170 self.ipcmd.link_down(vifacename)
171 self.ipcmd.link_up(vifacename)
172 except Exception, e:
173 self.logger.debug('%s: fixing route entry failed (%s)'
d486dd0d 174 % (ifaceobj.name, str(e)))
00f6105d
RP
175 pass
176
1b284018
RP
177 def _handle_vrf_slaves(self, macvlan_ifacename, ifaceobj):
178 vrfname = self.ipcmd.link_get_master(ifaceobj.name)
179 if vrfname:
d486dd0d 180 self.ipcmd.link_set(macvlan_ifacename, 'master', vrfname)
1b284018 181
55072bd1
ST
182 def _get_macs_from_old_config(self, ifaceobj=None):
183 """ This method returns a list of the mac addresses
184 in the address-virtual attribute for the bridge. """
185 maclist = []
186 saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name)
187 if not saved_ifaceobjs:
188 return maclist
189 # we need the old saved configs from the statemanager
190 for oldifaceobj in saved_ifaceobjs:
191 if not oldifaceobj.get_attr_value('address-virtual'):
192 continue
193 for av in oldifaceobj.get_attr_value('address-virtual'):
194 macip = av.split()
195 if len(macip) < 2:
196 self.logger.debug("%s: incorrect old address-virtual attrs '%s'"
197 %(oldifaceobj.name, av))
198 continue
199 maclist.append(macip[0])
200 return maclist
201
7b711dc5
JF
202 def get_addressvirtual_ipv6_addrgen_user_conf(self, ifaceobj):
203 ipv6_addrgen = ifaceobj.get_attr_value_first('address-virtual-ipv6-addrgen')
204
205 if ipv6_addrgen:
206 return True, utils.get_boolean_from_string(ipv6_addrgen)
207
208 return False, None
209
e1601369 210 def _apply_address_config(self, ifaceobj, address_virtual_list):
fc5e1735 211 purge_existing = False if ifupdownflags.flags.PERFMODE else True
15ef32ea 212
9e0be374 213 lower_iface_mtu = update_mtu = None
d486dd0d 214 if ifupdownconfig.config.get('adjust_logical_dev_mtu', '1') != '0':
9e0be374
JF
215 if ifaceobj.lowerifaces and address_virtual_list:
216 update_mtu = True
217
7b711dc5
JF
218 should_configure_ipv6_addrgen, ipv6_addrgen_user_value = self.get_addressvirtual_ipv6_addrgen_user_conf(ifaceobj)
219
e1601369 220 hwaddress = []
15ef32ea
RP
221 self.ipcmd.batch_start()
222 av_idx = 0
aaef0a79 223 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
15ef32ea
RP
224 for av in address_virtual_list:
225 av_attrs = av.split()
226 if len(av_attrs) < 2:
bf3eda91
RP
227 self.log_error("%s: incorrect address-virtual attrs '%s'"
228 %(ifaceobj.name, av), ifaceobj,
229 raise_error=False)
15ef32ea
RP
230 av_idx += 1
231 continue
232
4d3dc0f7
N
233 mac = av_attrs[0]
234 if not self.check_mac_address(ifaceobj, mac):
235 continue
15ef32ea
RP
236 # Create a macvlan device on this device and set the virtual
237 # router mac and ip on it
00f6105d 238 link_created = False
cb46a208 239 macvlan_ifacename = '%s%d' %(macvlan_prefix, av_idx)
e74d01e1 240 if not self.ipcmd.link_exists(macvlan_ifacename):
d486dd0d
JF
241 try:
242 netlink.link_add_macvlan(ifaceobj.name, macvlan_ifacename)
243 except:
244 self.ipcmd.link_add_macvlan(ifaceobj.name, macvlan_ifacename)
00f6105d 245 link_created = True
d486dd0d
JF
246
247 # first thing we need to handle vrf enslavement
248 if (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE):
249 self._handle_vrf_slaves(macvlan_ifacename, ifaceobj)
250
7b711dc5
JF
251 if should_configure_ipv6_addrgen:
252 self.ipcmd.ipv6_addrgen(macvlan_ifacename, ipv6_addrgen_user_value)
253
5df79763
ST
254 ips = av_attrs[1:]
255 if mac != 'None':
256 mac = mac.lower()
257 # customer could have used UPPERCASE for MAC
258 self.ipcmd.link_set_hwaddress(macvlan_ifacename, mac)
259 hwaddress.append(mac)
23e8546d
JF
260
261 if self.addressvirtual_with_route_metric and self.ipcmd.addr_metric_support():
262 metric = self.ipcmd.get_default_ip_metric()
263 else:
264 metric = None
265
dfaa8a2d
JF
266 self.ipcmd.addr_add_multiple(
267 ifaceobj,
268 macvlan_ifacename,
269 ips,
270 purge_existing,
23e8546d 271 metric=metric
dfaa8a2d 272 )
9e0be374 273
00f6105d
RP
274 # If link existed before, flap the link
275 if not link_created:
20e547e7 276
23e8546d 277 if not self.addressvirtual_with_route_metric or not self.ipcmd.addr_metric_support():
20e547e7
JF
278 # if the system doesn't support ip addr set METRIC
279 # we need to do manually check the ordering of the ip4 routes
280 self._fix_connected_route(ifaceobj, macvlan_ifacename, ips[0])
281
9e0be374 282 if update_mtu:
0493bac6 283 lower_iface_mtu = self.ipcmd.link_get_mtu(ifaceobj.name, refresh=True)
9e0be374
JF
284 update_mtu = False
285
d486dd0d 286 if lower_iface_mtu and lower_iface_mtu != self.ipcmd.link_get_mtu(macvlan_ifacename, refresh=True):
0493bac6
JF
287 try:
288 self.ipcmd.link_set_mtu(macvlan_ifacename,
289 lower_iface_mtu)
290 except Exception as e:
291 self.logger.info('%s: failed to set mtu %s: %s' %
292 (macvlan_ifacename, lower_iface_mtu, e))
9e0be374 293
dc3f4c45
RP
294 # set macvlan device to up in anycase.
295 # since we auto create them here..we are responsible
296 # to bring them up here in the case they were brought down
297 # by some other entity in the system.
298 netlink.link_set_updown(macvlan_ifacename, "up")
d486dd0d
JF
299 else:
300 try:
23e8546d 301 if not self.addressvirtual_with_route_metric or not self.ipcmd.addr_metric_support():
dfaa8a2d
JF
302 # if the system doesn't support ip addr set METRIC
303 # we need to do manually check the ordering of the ip6 routes
304 self.ipcmd.fix_ipv6_route_metric(ifaceobj, macvlan_ifacename, ips)
d486dd0d
JF
305 except Exception as e:
306 self.logger.debug('fix_vrf_slave_ipv6_route_metric: failed: %s' % e)
1b284018 307
f8ad40ce
SE
308 # Disable IPv6 duplicate address detection on VRR interfaces
309 for key, sysval in { 'accept_dad' : '0', 'dad_transmits' : '0' }.iteritems():
310 syskey = 'net.ipv6.conf.%s.%s' % (macvlan_ifacename, key)
311 if self.sysctl_get(syskey) != sysval:
312 self.sysctl_set(syskey, sysval)
313
15ef32ea
RP
314 av_idx += 1
315 self.ipcmd.batch_commit()
316
55072bd1
ST
317 # check the statemanager for old configs.
318 # We need to remove only the previously configured FDB entries
319 oldmacs = self._get_macs_from_old_config(ifaceobj)
320 # get a list of fdbs in old that are not in new config meaning they should
321 # be removed since they are gone from the config
5df79763 322 removed_macs = [mac for mac in oldmacs if mac.lower() not in hwaddress]
55072bd1 323 self._remove_addresses_from_bridge(ifaceobj, removed_macs)
e1601369
RP
324 # if ifaceobj is a bridge and bridge is a vlan aware bridge
325 # add the vid to the bridge
326 self._add_addresses_to_bridge(ifaceobj, hwaddress)
327
328 def _remove_running_address_config(self, ifaceobj):
329 if not self.ipcmd.link_exists(ifaceobj.name):
15ef32ea 330 return
e1601369 331 hwaddress = []
15ef32ea 332 self.ipcmd.batch_start()
aaef0a79 333 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
55072bd1 334 for macvlan_ifacename in glob.glob("/sys/class/net/%s*" %macvlan_prefix):
e1601369
RP
335 macvlan_ifacename = os.path.basename(macvlan_ifacename)
336 if not self.ipcmd.link_exists(macvlan_ifacename):
337 continue
338 hwaddress.append(self.ipcmd.link_get_hwaddress(macvlan_ifacename))
15ef32ea 339 self.ipcmd.link_delete(os.path.basename(macvlan_ifacename))
e1601369
RP
340 # XXX: Also delete any fdb addresses. This requires, checking mac address
341 # on individual macvlan interfaces and deleting the vlan from that.
15ef32ea 342 self.ipcmd.batch_commit()
e1601369
RP
343 if any(hwaddress):
344 self._remove_addresses_from_bridge(ifaceobj, hwaddress)
15ef32ea 345
e1601369
RP
346 def _remove_address_config(self, ifaceobj, address_virtual_list=None):
347 if not address_virtual_list:
348 self._remove_running_address_config(ifaceobj)
349 return
350
351 if not self.ipcmd.link_exists(ifaceobj.name):
352 return
353 hwaddress = []
354 self.ipcmd.batch_start()
355 av_idx = 0
aaef0a79 356 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
e1601369
RP
357 for av in address_virtual_list:
358 av_attrs = av.split()
359 if len(av_attrs) < 2:
bf3eda91
RP
360 self.log_error("%s: incorrect address-virtual attrs '%s'"
361 %(ifaceobj.name, av), ifaceobj,
362 raise_error=False)
e1601369
RP
363 av_idx += 1
364 continue
365
366 # Delete the macvlan device on this device
cb46a208 367 macvlan_ifacename = '%s%d' %(macvlan_prefix, av_idx)
e1601369
RP
368 self.ipcmd.link_delete(os.path.basename(macvlan_ifacename))
369 if av_attrs[0] != 'None':
370 hwaddress.append(av_attrs[0])
371 av_idx += 1
372 self.ipcmd.batch_commit()
373 self._remove_addresses_from_bridge(ifaceobj, hwaddress)
15ef32ea 374
4d3dc0f7
N
375 def check_mac_address(self, ifaceobj, mac):
376 if mac == 'None':
d486dd0d 377 return True
4d3dc0f7
N
378 mac = mac.lower()
379 try:
586535e8 380 if int(mac.split(":")[0], 16) & 1 :
4d3dc0f7
N
381 self.logger.error("%s: Multicast bit is set in the virtual mac address '%s'" %(ifaceobj.name, mac))
382 return False
383 return True
42e85fc8 384 except Exception:
4d3dc0f7
N
385 return False
386
42e85fc8
RP
387 def _fixup_vrf_enslavements(self, ifaceobj, ifaceobj_getfunc=None):
388 """ This function fixes up address virtual interfaces
389 (macvlans) on vrf slaves. Since this fixup is an overhead,
390 this must be called only in cases when ifupdown2 is
391 called on the vrf device or its slave and not when
392 ifupdown2 is called for all devices. When all
393 interfaces are brought up, the expectation is that
394 the normal path will fix up a vrf device or its slaves"""
395
396 if not ifaceobj_getfunc:
397 return
398 if ((ifaceobj.link_kind & ifaceLinkKind.VRF) and
399 self.ipcmd.link_exists(ifaceobj.name)):
400 # if I am a vrf device and I have slaves
401 # that have address virtual config,
402 # enslave the slaves 'address virtual
403 # interfaces (macvlans)' to myself:
404 running_slaves = self.ipcmd.link_get_lowers(ifaceobj.name)
405 if running_slaves:
406 # pick up any existing slaves of a vrf device and
407 # look for their upperdevices and enslave them to the
408 # vrf device:
409 for s in running_slaves:
410 sobjs = ifaceobj_getfunc(s)
411 if (sobjs and
412 (sobjs[0].link_privflags & ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE)):
413 # enslave all its upper devices to
414 # the vrf device
415 upperdevs = self.ipcmd.link_get_uppers(sobjs[0].name)
416 if not upperdevs:
417 continue
418 for u in upperdevs:
419 # skip vrf device which
420 # will also show up in the
421 # upper device list
422 if u == ifaceobj.name:
423 continue
d486dd0d
JF
424 self.ipcmd.link_set(u, 'master', ifaceobj.name,
425 state='up')
42e85fc8
RP
426 elif ((ifaceobj.link_privflags & ifaceLinkPrivFlags.ADDRESS_VIRTUAL_SLAVE) and
427 (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE) and
428 self.ipcmd.link_exists(ifaceobj.name)):
429 # If I am a vrf slave and I have 'address virtual'
430 # config, make sure my addrress virtual interfaces
431 # (macvlans) are also enslaved to the vrf device
432 vrfname = ifaceobj.get_attr_value_first('vrf')
433 if not vrfname or not self.ipcmd.link_exists(vrfname):
434 return
435 running_uppers = self.ipcmd.link_get_uppers(ifaceobj.name)
436 if not running_uppers:
437 return
438 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
439 if not macvlan_prefix:
440 return
441 for u in running_uppers:
442 if u == vrfname:
443 continue
444 if u.startswith(macvlan_prefix):
d486dd0d
JF
445 self.ipcmd.link_set(u, 'master', vrfname,
446 state='up')
42e85fc8
RP
447
448 def _up(self, ifaceobj, ifaceobj_getfunc=None):
449 if not ifupdownflags.flags.ALL:
450 self._fixup_vrf_enslavements(ifaceobj, ifaceobj_getfunc)
15ef32ea
RP
451 address_virtual_list = ifaceobj.get_attr_value('address-virtual')
452 if not address_virtual_list:
453 # XXX: address virtual is not present. In which case,
00f6105d 454 # delete stale macvlan devices.
e1601369 455 self._remove_address_config(ifaceobj, address_virtual_list)
15ef32ea
RP
456 return
457
1b284018
RP
458 if (ifaceobj.upperifaces and
459 not ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE):
f466af7a
JF
460 self.log_error('%s: invalid placement of address-virtual lines (must be configured under an interface with no upper interfaces or parent interfaces)'
461 % (ifaceobj.name), ifaceobj)
462 return
463
e1601369 464 if not self.ipcmd.link_exists(ifaceobj.name):
15ef32ea 465 return
e1601369 466 self._apply_address_config(ifaceobj, address_virtual_list)
15ef32ea 467
42e85fc8 468 def _down(self, ifaceobj, ifaceobj_getfunc=None):
15ef32ea 469 try:
cb46a208
RP
470 self._remove_address_config(ifaceobj,
471 ifaceobj.get_attr_value('address-virtual'))
15ef32ea
RP
472 except Exception, e:
473 self.log_warn(str(e))
474
475 def _query_check(self, ifaceobj, ifaceobjcurr):
476 address_virtual_list = ifaceobj.get_attr_value('address-virtual')
477 if not address_virtual_list:
478 return
cb46a208
RP
479 if not self.ipcmd.link_exists(ifaceobj.name):
480 return
15ef32ea 481 av_idx = 0
aaef0a79 482 macvlan_prefix = self._get_macvlan_prefix(ifaceobj)
15ef32ea
RP
483 for address_virtual in address_virtual_list:
484 av_attrs = address_virtual.split()
485 if len(av_attrs) < 2:
486 self.logger.warn("%s: incorrect address-virtual attrs '%s'"
487 %(ifaceobj.name, address_virtual))
488 av_idx += 1
489 continue
490
491 # Check if the macvlan device on this interface
cb46a208
RP
492 macvlan_ifacename = '%s%d' %(macvlan_prefix, av_idx)
493 if not self.ipcmd.link_exists(macvlan_ifacename):
494 ifaceobjcurr.update_config_with_status('address-virtual',
495 '', 1)
496 av_idx += 1
497 continue
498 # Check mac and ip address
499 rhwaddress = self.ipcmd.link_get_hwaddress(macvlan_ifacename)
d486dd0d
JF
500 raddrs = self.ipcmd.get_running_addrs(
501 ifname=macvlan_ifacename,
502 details=False,
503 addr_virtual_ifaceobj=ifaceobj
504 )
cb46a208
RP
505 if not raddrs or not rhwaddress:
506 ifaceobjcurr.update_config_with_status('address-virtual', '', 1)
507 av_idx += 1
508 continue
b6688146
JF
509 try:
510 av_attrs[0] = ':'.join([i if len(i) == 2 else '0%s' % i
511 for i in av_attrs[0].split(':')])
512 except:
513 self.logger.info('%s: %s: invalid value for address-virtual (%s)'
514 % (ifaceobj.name,
515 macvlan_ifacename,
516 ' '.join(av_attrs)))
90649d37 517 try:
d486dd0d
JF
518 if (rhwaddress == av_attrs[0].lower() and
519 self.ipcmd.compare_user_config_vs_running_state(raddrs, av_attrs[1:]) and
520 self._check_addresses_in_bridge(ifaceobj, av_attrs[0].lower())):
90649d37
JF
521 ifaceobjcurr.update_config_with_status('address-virtual',
522 address_virtual, 0)
523 else:
524 raddress_virtual = '%s %s' % (rhwaddress, ' '.join(raddrs))
525 ifaceobjcurr.update_config_with_status('address-virtual',
526 raddress_virtual, 1)
527 except:
528 raddress_virtual = '%s %s' % (rhwaddress, ' '.join(raddrs))
529 ifaceobjcurr.update_config_with_status('address-virtual',
530 raddress_virtual, 1)
15ef32ea
RP
531 av_idx += 1
532 return
533
42e85fc8 534 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
aaef0a79 535 macvlan_prefix = self._get_macvlan_prefix(ifaceobjrunning)
8e113d63
RP
536 address_virtuals = glob.glob("/sys/class/net/%s*" %macvlan_prefix)
537 for av in address_virtuals:
538 macvlan_ifacename = os.path.basename(av)
539 rhwaddress = self.ipcmd.link_get_hwaddress(macvlan_ifacename)
d486dd0d 540 raddress = self.ipcmd.get_running_addrs(None, macvlan_ifacename)
8e113d63
RP
541 if not raddress:
542 self.logger.warn('%s: no running addresses'
543 %ifaceobjrunning.name)
544 raddress = []
545 ifaceobjrunning.update_config('address-virtual',
546 '%s %s' %(rhwaddress, ''.join(raddress)))
15ef32ea
RP
547 return
548
549 _run_ops = {'up' : _up,
550 'down' : _down,
551 'query-checkcurr' : _query_check,
552 'query-running' : _query_running}
553
554 def get_ops(self):
555 """ returns list of ops supported by this module """
556 return self._run_ops.keys()
557
558 def _init_command_handlers(self):
559 if not self.ipcmd:
d486dd0d 560 self.ipcmd = LinkUtils()
15ef32ea 561
42e85fc8
RP
562 def run(self, ifaceobj, operation, query_ifaceobj=None,
563 ifaceobj_getfunc=None, **extra_args):
15ef32ea
RP
564 """ run vlan configuration on the interface object passed as argument
565
566 Args:
567 **ifaceobj** (object): iface object
568
569 **operation** (str): any of 'pre-up', 'post-down', 'query-checkcurr',
570 'query-running'
571 Kwargs:
572 **query_ifaceobj** (object): query check ifaceobject. This is only
573 valid when op is 'query-checkcurr'. It is an object same as
574 ifaceobj, but contains running attribute values and its config
575 status. The modules can use it to return queried running state
576 of interfaces. status is success if the running state is same
577 as user required state in ifaceobj. error otherwise.
578 """
84ca006f
RP
579 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
580 return
15ef32ea
RP
581 op_handler = self._run_ops.get(operation)
582 if not op_handler:
583 return
584 self._init_command_handlers()
585 if operation == 'query-checkcurr':
586 op_handler(self, ifaceobj, query_ifaceobj)
587 else:
42e85fc8 588 op_handler(self, ifaceobj, ifaceobj_getfunc=ifaceobj_getfunc)