diff options
author | Christian Poessinger <christian@poessinger.com> | 2020-05-02 21:34:59 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-02 21:34:59 +0200 |
commit | 3501313affa62b88fa530c4518a08269ea6f61c0 (patch) | |
tree | 8a5cbbe418c82de4cbf4e5849a6ce4c58e1d599d /python | |
parent | b47e7ebab5b9a871ce7d37e57193692a043263a2 (diff) | |
parent | 731fdaf86ba20ead3af7e4f988ad84a321fbe12e (diff) | |
download | vyos-1x-3501313affa62b88fa530c4518a08269ea6f61c0.tar.gz vyos-1x-3501313affa62b88fa530c4518a08269ea6f61c0.zip |
Merge pull request #388 from jjakob/flush-addrs-T2367
T2367: flush addresses when adding bond/bridge members
Diffstat (limited to 'python')
-rw-r--r-- | python/vyos/ifconfig/interface.py | 96 |
1 files changed, 64 insertions, 32 deletions
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index a156eddd9..6241c83b5 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) @@ -240,15 +240,11 @@ class Interface(Control): >>> i = Interface('eth0') >>> i.remove() """ - # stop DHCP(v6) if running - self.dhcp.v4.delete() - self.dhcp.v6.delete() # remove all assigned IP addresses from interface - this is a bit redundant # as the kernel will remove all addresses on interface deletion, but we # can not delete ALL interfaces, see below - for addr in self.get_addr(): - self.del_addr(addr) + self.flush_addrs() # --------------------------------------------------------------------- # Any class can define an eternal regex in its definition @@ -621,7 +617,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 +626,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 +635,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 +678,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 +690,34 @@ 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 + + def flush_addrs(self): + """ + Flush all addresses from an interface, including DHCP. + + Will raise an exception on error. + """ + # stop DHCP(v6) if running + self.dhcp.v4.delete() + self.dhcp.v6.delete() + + # flush all addresses + self._cmd(f'ip addr flush dev "{self.config["ifname"]}"') |