summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJernej Jakob <jernej.jakob@gmail.com>2020-05-02 15:02:44 +0200
committerJernej Jakob <jernej.jakob@gmail.com>2020-05-02 20:40:38 +0200
commit9e51fa4ad6c2edd25c57d17e520a5b5c83a4f5b8 (patch)
tree215cb4a535387c2801b1473d8c062d258dfb1246
parentc7c77c144495052cfb227a35e69d69e8d9747e81 (diff)
downloadvyos-1x-9e51fa4ad6c2edd25c57d17e520a5b5c83a4f5b8.tar.gz
vyos-1x-9e51fa4ad6c2edd25c57d17e520a5b5c83a4f5b8.zip
interface: T2367: fix add_addr and del_addr address tracking in cache
Correctly track addresses in cache _addr variable
-rw-r--r--python/vyos/ifconfig/interface.py77
1 files changed, 50 insertions, 27 deletions
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index a156eddd9..8bcfda13c 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -219,7 +219,7 @@ class Interface(Control):
else:
raise Exception('interface "{}" not found'.format(self.config['ifname']))
- # list of assigned IP addresses
+ # temporary list of assigned IP addresses
self._addr = []
self.operational = self.OperationalClass(ifname)
@@ -621,7 +621,8 @@ class Interface(Control):
def add_addr(self, addr):
"""
Add IP(v6) address to interface. Address is only added if it is not
- already assigned to that interface.
+ already assigned to that interface. Address format must be validated
+ and compressed/normalized before calling this function.
addr: can be an IPv4 address, IPv6 address, dhcp or dhcpv6!
IPv4: add IPv4 address to interface
@@ -629,6 +630,7 @@ class Interface(Control):
dhcp: start dhclient (IPv4) on interface
dhcpv6: start dhclient (IPv6) on interface
+ Returns False if address is already assigned and wasn't re-added.
Example:
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
@@ -637,32 +639,42 @@ class Interface(Control):
>>> j.get_addr()
['192.0.2.1/24', '2001:db8::ffff/64']
"""
-
- # cache new IP address which is assigned to interface
- self._addr.append(addr)
-
- # we can not have both DHCP and static IPv4 addresses assigned to an interface
- if 'dhcp' in self._addr:
- for addr in self._addr:
- # do not change below 'if' ordering esle you will get an exception as:
- # ValueError: 'dhcp' does not appear to be an IPv4 or IPv6 address
- if addr != 'dhcp' and is_ipv4(addr):
- raise ConfigError(
- "Can't configure both static IPv4 and DHCP address on the same interface")
-
- if addr == 'dhcp':
- self.dhcp.v4.set()
- elif addr == 'dhcpv6':
- self.dhcp.v6.set()
+ # XXX: normalize/compress with ipaddress if calling functions don't?
+ # is subnet mask always passed, and in the same way?
+ ret = True
+
+ # we can't have both DHCP and static IPv4 addresses assigned
+ for a in self._addr:
+ if ( ( addr == 'dhcp' and a != 'dhcpv6' and is_ipv4(a) ) or
+ ( a == 'dhcp' and addr != 'dhcpv6' and is_ipv4(addr) ) ):
+ raise ConfigError((
+ "Can't configure both static IPv4 and DHCP address "
+ "on the same interface"))
+
+ # do not add same address twice
+ if addr not in self._addr:
+ # add to interface
+ if addr == 'dhcp':
+ self.dhcp.v4.set()
+ elif addr == 'dhcpv6':
+ self.dhcp.v6.set()
+ else:
+ if not is_intf_addr_assigned(self.ifname, addr):
+ ret = self._cmd(f'ip addr add "{addr}" dev "{self.ifname}"')
+ else:
+ return False
+ # add to cache
+ self._addr.append(addr)
else:
- if not is_intf_addr_assigned(self.config['ifname'], addr):
- cmd = 'ip addr add "{}" dev "{}"'.format(addr, self.config['ifname'])
- return self._cmd(cmd)
+ return False
+
+ return ret
def del_addr(self, addr):
"""
- Delete IP(v6) address to interface. Address is only added if it is
- assigned to that interface.
+ Delete IP(v6) address from interface. Address is only deleted if it is
+ assigned to that interface. Address format must be exactly the same as
+ was used when adding the address.
addr: can be an IPv4 address, IPv6 address, dhcp or dhcpv6!
IPv4: delete IPv4 address from interface
@@ -670,6 +682,7 @@ class Interface(Control):
dhcp: stop dhclient (IPv4) on interface
dhcpv6: stop dhclient (IPv6) on interface
+ Returns False if address isn't already assigned and wasn't deleted.
Example:
>>> from vyos.ifconfig import Interface
>>> j = Interface('eth0')
@@ -681,11 +694,21 @@ class Interface(Control):
>>> j.get_addr()
['2001:db8::ffff/64']
"""
+ ret = True
+
+ # remove from interface
if addr == 'dhcp':
self.dhcp.v4.delete()
elif addr == 'dhcpv6':
self.dhcp.v6.delete()
else:
- if is_intf_addr_assigned(self.config['ifname'], addr):
- cmd = 'ip addr del "{}" dev "{}"'.format(addr, self.config['ifname'])
- return self._cmd(cmd)
+ if is_intf_addr_assigned(self.ifname, addr):
+ ret = self._cmd(f'ip addr del "{addr}" dev "{self.ifname}"')
+ else:
+ return False
+
+ if addr in self._addr:
+ # remove from cache
+ self._addr.remove(addr)
+
+ return ret