]> git.proxmox.com Git - mirror_ifupdown2.git/blame - addons/address.py
addons: bridge: remove pvid from vids list on ifquery -r for bridge port
[mirror_ifupdown2.git] / addons / address.py
CommitLineData
15ef32ea
RP
1#!/usr/bin/python
2#
3# Copyright 2014 Cumulus Networks, Inc. All rights reserved.
4# Author: Roopa Prabhu, roopa@cumulusnetworks.com
5#
6
9087e727
JF
7import os
8
15ef32ea 9try:
c6370b56 10 from ipaddr import IPNetwork, IPv4Network, IPv6Network, IPv4Address, IPv6Address
15ef32ea
RP
11 from sets import Set
12 from ifupdown.iface import *
13 from ifupdownaddons.modulebase import moduleBase
14 from ifupdownaddons.iproute2 import iproute2
15 from ifupdownaddons.dhclient import dhclient
84f33af6 16 import ifupdown.policymanager as policymanager
2864d6f3 17 from ifupdown.netlink import netlink
0582f185 18 import ifupdown.ifupdownconfig as ifupdownConfig
fc5e1735 19 import ifupdown.ifupdownflags as ifupdownflags
0232d1bb 20 import ifupdown.statemanager as statemanager
15ef32ea
RP
21except ImportError, e:
22 raise ImportError (str(e) + "- required module not found")
23
24class address(moduleBase):
25 """ ifupdown2 addon module to configure address, mtu, hwaddress, alias
26 (description) on an interface """
27
28 _modinfo = {'mhelp' : 'address configuration module for interfaces',
29 'attrs': {
30 'address' :
31 {'help' : 'ipv4 or ipv6 addresses',
482b2fab 32 'validvals' : ['<ipv4/prefixlen>', '<ipv6/prefixlen>'],
c6370b56 33 'multiline' : True,
15ef32ea
RP
34 'example' : ['address 10.0.12.3/24',
35 'address 2000:1000:1000:1000:3::5/128']},
36 'netmask' :
37 {'help': 'netmask',
38 'example' : ['netmask 255.255.255.0'],
39 'compat' : True},
40 'broadcast' :
41 {'help': 'broadcast address',
482b2fab 42 'validvals' : ['<ipv4>', ],
15ef32ea
RP
43 'example' : ['broadcast 10.0.1.255']},
44 'scope' :
45 {'help': 'scope',
c6370b56 46 'validvals' : ['universe', 'site', 'link', 'host', 'nowhere'],
15ef32ea
RP
47 'example' : ['scope host']},
48 'preferred-lifetime' :
49 {'help': 'preferred lifetime',
c6370b56 50 'validrange' : ['0', '65535'],
15ef32ea
RP
51 'example' : ['preferred-lifetime forever',
52 'preferred-lifetime 10']},
53 'gateway' :
54 {'help': 'default gateway',
482b2fab 55 'validvals' : ['<ipv4>', '<ipv6>'],
15ef32ea
RP
56 'example' : ['gateway 255.255.255.0']},
57 'mtu' :
58 { 'help': 'interface mtu',
c6370b56 59 'validrange' : ['552', '9216'],
15ef32ea
RP
60 'example' : ['mtu 1600'],
61 'default' : '1500'},
62 'hwaddress' :
63 {'help' : 'hw address',
c6370b56 64 'validvals' : ['<mac>',],
15ef32ea
RP
65 'example': ['hwaddress 44:38:39:00:27:b8']},
66 'alias' :
67 { 'help': 'description/alias',
c6370b56 68 'validvals' : ['<text>',],
394e68b5
RP
69 'example' : ['alias testnetwork']},
70 'address-purge' :
71 { 'help': 'purge existing addresses. By default ' +
72 'any existing ip addresses on an interface are ' +
73 'purged to match persistant addresses in the ' +
74 'interfaces file. Set this attribute to \'no\'' +
75 'if you want to preserve existing addresses',
c6370b56 76 'validvals' : ['yes', 'no'],
394e68b5 77 'default' : 'yes',
a794fb31
BR
78 'example' : ['address-purge yes/no']},
79 'clagd-vxlan-anycast-ip' :
80 { 'help' : 'Anycast local IP address for ' +
81 'dual connected VxLANs',
482b2fab 82 'validvals' : ['<ipv4>', ],
a794fb31 83 'example' : ['clagd-vxlan-anycast-ip 36.0.0.11']}}}
15ef32ea
RP
84
85 def __init__(self, *args, **kargs):
86 moduleBase.__init__(self, *args, **kargs)
87 self.ipcmd = None
8e113d63 88 self._bridge_fdb_query_cache = {}
84f33af6 89 self.default_mtu = policymanager.policymanager_api.get_attr_default(module_name=self.__class__.__name__, attr='mtu')
15ef32ea 90
75afe2a7
RP
91 def _address_valid(self, addrs):
92 if not addrs:
93 return False
94 if any(map(lambda a: True if a[:7] != '0.0.0.0'
95 else False, addrs)):
96 return True
97 return False
98
428206bf 99 def _get_hwaddress(self, ifaceobj):
2876ca35 100 hwaddress = ifaceobj.get_attr_value_first('hwaddress')
428206bf
JF
101 if hwaddress and hwaddress.startswith("ether"):
102 hwaddress = hwaddress[5:].strip()
103 return hwaddress
104
105 def _process_bridge(self, ifaceobj, up):
106 hwaddress = self._get_hwaddress(ifaceobj)
75afe2a7
RP
107 addrs = ifaceobj.get_attr_value_first('address')
108 is_vlan_dev_on_vlan_aware_bridge = False
109 is_bridge = self.ipcmd.is_bridge(ifaceobj.name)
110 if not is_bridge:
111 if '.' in ifaceobj.name:
112 (bridgename, vlan) = ifaceobj.name.split('.')
113 is_vlan_dev_on_vlan_aware_bridge = self.ipcmd.bridge_is_vlan_aware(bridgename)
8c2c9f26
RP
114 if ((is_bridge and not self.ipcmd.bridge_is_vlan_aware(ifaceobj.name))
115 or is_vlan_dev_on_vlan_aware_bridge):
75afe2a7
RP
116 if self._address_valid(addrs):
117 if up:
118 self.write_file('/proc/sys/net/ipv4/conf/%s' %ifaceobj.name +
119 '/arp_accept', '1')
120 else:
121 self.write_file('/proc/sys/net/ipv4/conf/%s' %ifaceobj.name +
122 '/arp_accept', '0')
123 if hwaddress and is_vlan_dev_on_vlan_aware_bridge:
124 if up:
125 self.ipcmd.bridge_fdb_add(bridgename, hwaddress, vlan)
126 else:
127 self.ipcmd.bridge_fdb_del(bridgename, hwaddress, vlan)
cb46a208 128
0582f185
RP
129 def _get_anycast_addr(self, ifaceobjlist):
130 for ifaceobj in ifaceobjlist:
131 anycast_addr = ifaceobj.get_attr_value_first('clagd-vxlan-anycast-ip')
132 if anycast_addr:
133 anycast_addr = anycast_addr+'/32'
134 return anycast_addr
135 return None
136
137 def _inet_address_convert_to_cidr(self, ifaceobjlist):
15ef32ea 138 newaddrs = []
0582f185
RP
139 newaddr_attrs = {}
140
141 for ifaceobj in ifaceobjlist:
142 addrs = ifaceobj.get_attr_value('address')
143 if not addrs:
144 continue
145
858a230f
RP
146 if (((ifaceobj.role & ifaceRole.SLAVE) and
147 not (ifaceobj.link_privflags & ifaceLinkPrivFlags.VRF_SLAVE)) or
148 ((ifaceobj.link_kind & ifaceLinkKind.BRIDGE) and
149 (ifaceobj.link_privflags & ifaceLinkPrivFlags.BRIDGE_VLAN_AWARE))):
e6a66e79
RP
150 # we must not configure an IP address if the interface is
151 # enslaved or is a VLAN AWARE BRIDGE
152 self.logger.info('%s: ignoring ip address. Interface is '
153 'enslaved or a vlan aware bridge and cannot'
154 ' have an IP Address' %(ifaceobj.name))
0582f185 155 return (False, newaddrs, newaddr_attrs)
15ef32ea
RP
156 # If user address is not in CIDR notation, convert them to CIDR
157 for addr_index in range(0, len(addrs)):
158 addr = addrs[addr_index]
159 if '/' in addr:
160 newaddrs.append(addr)
161 continue
494d31d2 162 newaddr = addr
15ef32ea
RP
163 netmask = ifaceobj.get_attr_value_n('netmask', addr_index)
164 if netmask:
165 prefixlen = IPNetwork('%s' %addr +
166 '/%s' %netmask).prefixlen
0582f185 167 newaddr = addr + '/%s' %prefixlen
42ae7838
ST
168 else:
169 # we are here because there is no slash (/xx) and no netmask
170 # just let IPNetwork handle the ipv4 or ipv6 address mask
171 prefixlen = IPNetwork(addr).prefixlen
172 newaddr = addr + '/%s' %prefixlen
0582f185 173 newaddrs.append(newaddr)
15ef32ea 174
0582f185
RP
175 attrs = {}
176 for a in ['broadcast', 'pointopoint', 'scope',
177 'preferred-lifetime']:
178 aval = ifaceobj.get_attr_value_n(a, addr_index)
179 if aval:
72c964c2 180 attrs[a] = aval
0582f185
RP
181
182 if attrs:
183 newaddr_attrs[newaddr]= attrs
184 return (True, newaddrs, newaddr_attrs)
185
77021aa1
RP
186 def _inet_address_list_config(self, ifaceobj, newaddrs, newaddr_attrs):
187 for addr_index in range(0, len(newaddrs)):
188 try:
189 if newaddr_attrs:
190 self.ipcmd.addr_add(ifaceobj.name, newaddrs[addr_index],
191 newaddr_attrs.get(newaddrs[addr_index],
192 {}).get('broadcast'),
193 newaddr_attrs.get(newaddrs[addr_index],
194 {}).get('pointopoint'),
195 newaddr_attrs.get(newaddrs[addr_index],
196 {}).get('scope'),
197 newaddr_attrs.get(newaddrs[addr_index],
198 {}).get('preferred-lifetime'))
199 else:
200 self.ipcmd.addr_add(ifaceobj.name, newaddrs[addr_index])
201 except Exception, e:
bf3eda91 202 self.log_error(str(e), ifaceobj)
77021aa1
RP
203
204 def _inet_address_config(self, ifaceobj, ifaceobj_getfunc=None,
205 force_reapply=False):
0582f185
RP
206 squash_addr_config = (True if \
207 ifupdownConfig.config.get('addr_config_squash', \
208 '0') == '1' else False)
209
210 if (squash_addr_config and
211 not (ifaceobj.flags & ifaceobj.YOUNGEST_SIBLING)):
212 return
213
214 purge_addresses = ifaceobj.get_attr_value_first('address-purge')
215 if not purge_addresses:
216 purge_addresses = 'yes'
217
218 if squash_addr_config and ifaceobj.flags & iface.HAS_SIBLINGS:
219 ifaceobjlist = ifaceobj_getfunc(ifaceobj.name)
220 else:
221 ifaceobjlist = [ifaceobj]
222
223 (addr_supported, newaddrs, newaddr_attrs) = self._inet_address_convert_to_cidr(ifaceobjlist)
224 if not addr_supported:
225 return
226 if (not squash_addr_config and (ifaceobj.flags & iface.HAS_SIBLINGS)):
227 # if youngest sibling and squash addr is not set
228 # print a warning that addresses will not be purged
229 if (ifaceobj.flags & iface.YOUNGEST_SIBLING):
230 self.logger.warn('%s: interface has multiple ' %ifaceobj.name +
231 'iface stanzas, skip purging existing addresses')
232 purge_addresses = 'no'
233
fc5e1735 234 if not ifupdownflags.flags.PERFMODE and purge_addresses == 'yes':
0582f185
RP
235 # if perfmode is not set and purge addresses is not set to 'no'
236 # lets purge addresses not in the config
15ef32ea 237 runningaddrs = self.ipcmd.addr_get(ifaceobj.name, details=False)
0582f185 238
a794fb31
BR
239 # if anycast address is configured on 'lo' and is in running config
240 # add it to newaddrs so that ifreload doesn't wipe it out
0582f185
RP
241 anycast_addr = self._get_anycast_addr(ifaceobjlist)
242
a794fb31
BR
243 if runningaddrs and anycast_addr and anycast_addr in runningaddrs:
244 newaddrs.append(anycast_addr)
15ef32ea 245 if newaddrs == runningaddrs:
77021aa1
RP
246 if force_reapply:
247 self._inet_address_list_config(ifaceobj, newaddrs, newaddr_attrs)
15ef32ea
RP
248 return
249 try:
250 # if primary address is not same, there is no need to keep any.
251 # reset all addresses
252 if (newaddrs and runningaddrs and
253 (newaddrs[0] != runningaddrs[0])):
254 self.ipcmd.del_addr_all(ifaceobj.name)
255 else:
256 self.ipcmd.del_addr_all(ifaceobj.name, newaddrs)
257 except Exception, e:
258 self.log_warn(str(e))
259 if not newaddrs:
260 return
77021aa1 261 self._inet_address_list_config(ifaceobj, newaddrs, newaddr_attrs)
15ef32ea 262
0232d1bb
N
263 def _add_delete_gateway(self, ifaceobj, gateways=[], prev_gw=[]):
264 vrf = ifaceobj.get_attr_value_first('vrf')
265 metric = ifaceobj.get_attr_value_first('metric')
266 for del_gw in list(set(prev_gw) - set(gateways)):
267 try:
268 self.ipcmd.route_del_gateway(ifaceobj.name, del_gw, vrf, metric)
269 except:
270 pass
271 for add_gw in list(set(gateways) - set(prev_gw)):
272 try:
273 self.ipcmd.route_add_gateway(ifaceobj.name, add_gw, vrf)
274 except:
275 pass
276
277 def _get_prev_gateway(self, ifaceobj, gateways):
278 ipv = []
279 saved_ifaceobjs = statemanager.statemanager_api.get_ifaceobjs(ifaceobj.name)
280 if not saved_ifaceobjs:
281 return ipv
282 prev_gateways = saved_ifaceobjs[0].get_attr_value('gateway')
283 if not prev_gateways:
284 return ipv
285 return prev_gateways
286
0582f185 287 def _up(self, ifaceobj, ifaceobj_getfunc=None):
15ef32ea
RP
288 if not self.ipcmd.link_exists(ifaceobj.name):
289 return
68d9fee0 290 addr_method = ifaceobj.addr_method
77021aa1 291 force_reapply = False
15ef32ea
RP
292 try:
293 # release any stale dhcp addresses if present
fc5e1735 294 if (addr_method != "dhcp" and not ifupdownflags.flags.PERFMODE and
15ef32ea
RP
295 not (ifaceobj.flags & iface.HAS_SIBLINGS)):
296 # if not running in perf mode and ifaceobj does not have
297 # any sibling iface objects, kill any stale dhclient
298 # processes
75afe2a7 299 dhclientcmd = dhclient()
7c1135ea 300 if dhclientcmd.is_running(ifaceobj.name):
15ef32ea
RP
301 # release any dhcp leases
302 dhclientcmd.release(ifaceobj.name)
77021aa1 303 force_reapply = True
7c1135ea 304 elif dhclientcmd.is_running6(ifaceobj.name):
15ef32ea 305 dhclientcmd.release6(ifaceobj.name)
77021aa1 306 force_reapply = True
15ef32ea
RP
307 except:
308 pass
8e113d63 309
15ef32ea 310 self.ipcmd.batch_start()
68d9fee0 311 if addr_method != "dhcp":
77021aa1
RP
312 self._inet_address_config(ifaceobj, ifaceobj_getfunc,
313 force_reapply)
15ef32ea
RP
314 mtu = ifaceobj.get_attr_value_first('mtu')
315 if mtu:
8e113d63 316 self.ipcmd.link_set(ifaceobj.name, 'mtu', mtu)
6fa93b22 317 elif (not (ifaceobj.name == 'lo') and not ifaceobj.link_kind and
00c12960
RP
318 not (ifaceobj.link_privflags & ifaceLinkPrivFlags.BOND_SLAVE) and
319 self.default_mtu):
320 # logical devices like bridges and vlan devices rely on mtu
321 # from their lower devices. ie mtu travels from
322 # lower devices to upper devices. For bonds mtu travels from
323 # upper to lower devices. running mtu depends on upper and
324 # lower device mtu. With all this implicit mtu
325 # config by the kernel in play, we try to be cautious here
326 # on which devices we want to reset mtu to default.
327 # essentially only physical interfaces which are not bond slaves
328 running_mtu = self.ipcmd.link_get_mtu(ifaceobj.name)
329 if running_mtu != self.default_mtu:
330 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
13e22530 331
15ef32ea
RP
332 alias = ifaceobj.get_attr_value_first('alias')
333 if alias:
8e113d63 334 self.ipcmd.link_set_alias(ifaceobj.name, alias)
093ffa00
JF
335 try:
336 self.ipcmd.batch_commit()
337 except Exception as e:
338 self.logger.error('%s: %s' % (ifaceobj.name, str(e)))
339 ifaceobj.set_status(ifaceStatus.ERROR)
264dcaa0 340
428206bf 341 hwaddress = self._get_hwaddress(ifaceobj)
cb46a208 342 if hwaddress:
264dcaa0 343 running_hwaddress = None
fc5e1735 344 if not ifupdownflags.flags.PERFMODE: # system is clean
2876ca35 345 running_hwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
264dcaa0
RP
346 if hwaddress != running_hwaddress:
347 slave_down = False
2864d6f3 348 netlink.link_set_updown(ifaceobj.name, "down")
264dcaa0
RP
349 if ifaceobj.link_kind & ifaceLinkKind.BOND:
350 # if bond, down all the slaves
351 if ifaceobj.lowerifaces:
352 for l in ifaceobj.lowerifaces:
2864d6f3 353 netlink.link_set_updown(l, "down")
264dcaa0
RP
354 slave_down = True
355 try:
356 self.ipcmd.link_set(ifaceobj.name, 'address', hwaddress)
357 finally:
2864d6f3 358 netlink.link_set_updown(ifaceobj.name, "up")
264dcaa0
RP
359 if slave_down:
360 for l in ifaceobj.lowerifaces:
2864d6f3 361 netlink.link_set_updown(l, "up")
cb46a208 362
68d9fee0
RP
363 try:
364 # Handle special things on a bridge
365 self._process_bridge(ifaceobj, True)
366 except Exception, e:
bf3eda91 367 self.log_error('%s: %s' %(ifaceobj.name, str(e)), ifaceobj)
68d9fee0 368 pass
cb46a208 369
68d9fee0 370 if addr_method != "dhcp":
0232d1bb
N
371 gateways = ifaceobj.get_attr_value('gateway')
372 if not gateways:
373 gateways = []
374 prev_gw = self._get_prev_gateway(ifaceobj, gateways)
375 self._add_delete_gateway(ifaceobj, gateways, prev_gw)
376 return
15ef32ea 377
0582f185 378 def _down(self, ifaceobj, ifaceobj_getfunc=None):
15ef32ea
RP
379 try:
380 if not self.ipcmd.link_exists(ifaceobj.name):
381 return
68d9fee0
RP
382 addr_method = ifaceobj.addr_method
383 if addr_method != "dhcp":
aa052170
N
384 if ifaceobj.get_attr_value_first('address-purge')=='no':
385 addrlist = ifaceobj.get_attr_value('address')
386 for addr in addrlist:
387 self.ipcmd.addr_del(ifaceobj.name, addr)
388 #self.ipcmd.addr_del(ifaceobj.name, ifaceobj.get_attr_value('address')[0])
389 else:
390 self.ipcmd.del_addr_all(ifaceobj.name)
84f33af6 391 mtu = ifaceobj.get_attr_value_first('mtu')
00c12960
RP
392 if (not ifaceobj.link_kind and mtu and
393 self.default_mtu and (mtu != self.default_mtu)):
84f33af6 394 self.ipcmd.link_set(ifaceobj.name, 'mtu', self.default_mtu)
15ef32ea
RP
395 alias = ifaceobj.get_attr_value_first('alias')
396 if alias:
9087e727 397 filename = '/sys/class/net/%s/ifalias' %ifaceobj.name
a4a53f4b 398 self.logger.info('executing echo "" > %s' %filename)
9087e727 399 os.system('echo "" > %s' %filename)
75afe2a7
RP
400 # XXX hwaddress reset cannot happen because we dont know last
401 # address.
402
403 # Handle special things on a bridge
404 self._process_bridge(ifaceobj, False)
15ef32ea 405 except Exception, e:
bcf11b14
RP
406 self.logger.debug('%s : %s' %(ifaceobj.name, str(e)))
407 pass
15ef32ea
RP
408
409 def _get_iface_addresses(self, ifaceobj):
410 addrlist = ifaceobj.get_attr_value('address')
411 outaddrlist = []
412
413 if not addrlist: return None
414 for addrindex in range(0, len(addrlist)):
415 addr = addrlist[addrindex]
416 netmask = ifaceobj.get_attr_value_n('netmask', addrindex)
417 if netmask:
418 prefixlen = IPNetwork('%s' %addr +
419 '/%s' %netmask).prefixlen
420 addr = addr + '/%s' %prefixlen
421 outaddrlist.append(addr)
422 return outaddrlist
423
8e113d63
RP
424 def _get_bridge_fdbs(self, bridgename, vlan):
425 fdbs = self._bridge_fdb_query_cache.get(bridgename)
426 if not fdbs:
427 fdbs = self.ipcmd.bridge_fdb_show_dev(bridgename)
428 if not fdbs:
429 return
430 self._bridge_fdb_query_cache[bridgename] = fdbs
431 return fdbs.get(vlan)
432
433 def _check_addresses_in_bridge(self, ifaceobj, hwaddress):
434 """ If the device is a bridge, make sure the addresses
435 are in the bridge """
436 if '.' in ifaceobj.name:
437 (bridgename, vlan) = ifaceobj.name.split('.')
438 if self.ipcmd.bridge_is_vlan_aware(bridgename):
439 fdb_addrs = self._get_bridge_fdbs(bridgename, vlan)
440 if not fdb_addrs or hwaddress not in fdb_addrs:
441 return False
442 return True
443
0582f185 444 def _query_check(self, ifaceobj, ifaceobjcurr, ifaceobj_getfunc=None):
15ef32ea
RP
445 runningaddrsdict = None
446 if not self.ipcmd.link_exists(ifaceobj.name):
447 self.logger.debug('iface %s not found' %ifaceobj.name)
448 return
16d854b4 449 addr_method = ifaceobj.addr_method
15ef32ea
RP
450 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
451 'mtu', self.ipcmd.link_get_mtu)
428206bf 452 hwaddress = self._get_hwaddress(ifaceobj)
8e113d63 453 if hwaddress:
2876ca35 454 rhwaddress = self.ipcmd.link_get_hwaddress(ifaceobj.name)
8e113d63
RP
455 if not rhwaddress or rhwaddress != hwaddress:
456 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
457 1)
458 elif not self._check_addresses_in_bridge(ifaceobj, hwaddress):
459 # XXX: hw address is not in bridge
460 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
461 1)
462 ifaceobjcurr.status_str = 'bridge fdb error'
463 else:
464 ifaceobjcurr.update_config_with_status('hwaddress', rhwaddress,
465 0)
15ef32ea
RP
466 self.query_n_update_ifaceobjcurr_attr(ifaceobj, ifaceobjcurr,
467 'alias', self.ipcmd.link_get_alias)
468 # compare addresses
16d854b4
RP
469 if addr_method == 'dhcp':
470 return
15ef32ea
RP
471 addrs = self._get_iface_addresses(ifaceobj)
472 runningaddrsdict = self.ipcmd.addr_get(ifaceobj.name)
a794fb31
BR
473 # if anycast address is configured on 'lo' and is in running config
474 # add it to addrs so that query_check doesn't fail
475 anycast_addr = ifaceobj.get_attr_value_first('clagd-vxlan-anycast-ip')
476 if anycast_addr:
477 anycast_addr = anycast_addr+'/32'
478 if runningaddrsdict and anycast_addr and runningaddrsdict.get(anycast_addr):
479 addrs.append(anycast_addr)
15ef32ea
RP
480
481 # Set ifaceobjcurr method and family
482 ifaceobjcurr.addr_method = ifaceobj.addr_method
483 ifaceobjcurr.addr_family = ifaceobj.addr_family
484 if not runningaddrsdict and not addrs:
485 return
486 runningaddrs = runningaddrsdict.keys() if runningaddrsdict else []
487 if runningaddrs != addrs:
488 runningaddrsset = set(runningaddrs) if runningaddrs else set([])
489 addrsset = set(addrs) if addrs else set([])
490 if (ifaceobj.flags & iface.HAS_SIBLINGS):
491 if not addrsset:
492 return
493 # only check for addresses present in running config
494 addrsdiff = addrsset.difference(runningaddrsset)
495 for addr in addrs:
496 if addr in addrsdiff:
497 ifaceobjcurr.update_config_with_status('address',
498 addr, 1)
499 else:
500 ifaceobjcurr.update_config_with_status('address',
501 addr, 0)
502 else:
503 addrsdiff = addrsset.symmetric_difference(runningaddrsset)
504 for addr in addrsset.union(runningaddrsset):
505 if addr in addrsdiff:
506 ifaceobjcurr.update_config_with_status('address',
507 addr, 1)
508 else:
509 ifaceobjcurr.update_config_with_status('address',
510 addr, 0)
511 elif addrs:
512 [ifaceobjcurr.update_config_with_status('address',
513 addr, 0) for addr in addrs]
514 #XXXX Check broadcast address, scope, etc
515 return
516
0582f185 517 def _query_running(self, ifaceobjrunning, ifaceobj_getfunc=None):
15ef32ea
RP
518 if not self.ipcmd.link_exists(ifaceobjrunning.name):
519 self.logger.debug('iface %s not found' %ifaceobjrunning.name)
15ef32ea
RP
520 return
521 dhclientcmd = dhclient()
522 if (dhclientcmd.is_running(ifaceobjrunning.name) or
523 dhclientcmd.is_running6(ifaceobjrunning.name)):
524 # If dhcp is configured on the interface, we skip it
84f33af6 525 return
15ef32ea
RP
526 isloopback = self.ipcmd.link_isloopback(ifaceobjrunning.name)
527 if isloopback:
528 default_addrs = ['127.0.0.1/8', '::1/128']
529 ifaceobjrunning.addr_family = 'inet'
530 ifaceobjrunning.addr_method = 'loopback'
531 else:
532 default_addrs = []
533 runningaddrsdict = self.ipcmd.addr_get(ifaceobjrunning.name)
534 if runningaddrsdict:
535 [ifaceobjrunning.update_config('address', addr)
536 for addr, addrattrs in runningaddrsdict.items()
537 if addr not in default_addrs]
538 mtu = self.ipcmd.link_get_mtu(ifaceobjrunning.name)
539 if (mtu and
540 (ifaceobjrunning.name == 'lo' and mtu != '16436') or
541 (ifaceobjrunning.name != 'lo' and
542 mtu != self.get_mod_subattr('mtu', 'default'))):
543 ifaceobjrunning.update_config('mtu', mtu)
544 alias = self.ipcmd.link_get_alias(ifaceobjrunning.name)
84f33af6 545 if alias:
15ef32ea
RP
546 ifaceobjrunning.update_config('alias', alias)
547
548 _run_ops = {'up' : _up,
549 'down' : _down,
550 'query-checkcurr' : _query_check,
551 'query-running' : _query_running }
552
553 def get_ops(self):
554 """ returns list of ops supported by this module """
555 return self._run_ops.keys()
556
557 def _init_command_handlers(self):
558 if not self.ipcmd:
fc5e1735 559 self.ipcmd = iproute2()
15ef32ea 560
6e16e5ae 561 def run(self, ifaceobj, operation, query_ifaceobj=None, ifaceobj_getfunc=None):
15ef32ea
RP
562 """ run address configuration on the interface object passed as argument
563
564 Args:
565 **ifaceobj** (object): iface object
566
567 **operation** (str): any of 'up', 'down', 'query-checkcurr',
568 'query-running'
569 Kwargs:
570 query_ifaceobj (object): query check ifaceobject. This is only
571 valid when op is 'query-checkcurr'. It is an object same as
572 ifaceobj, but contains running attribute values and its config
573 status. The modules can use it to return queried running state
574 of interfaces. status is success if the running state is same
575 as user required state in ifaceobj. error otherwise.
576 """
8e113d63
RP
577 if ifaceobj.type == ifaceType.BRIDGE_VLAN:
578 return
15ef32ea
RP
579 op_handler = self._run_ops.get(operation)
580 if not op_handler:
581 return
15ef32ea
RP
582 self._init_command_handlers()
583 if operation == 'query-checkcurr':
0582f185
RP
584 op_handler(self, ifaceobj, query_ifaceobj,
585 ifaceobj_getfunc=ifaceobj_getfunc)
15ef32ea 586 else:
0582f185
RP
587 op_handler(self, ifaceobj,
588 ifaceobj_getfunc=ifaceobj_getfunc)