summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2019-08-30 13:00:55 +0200
committerChristian Poessinger <christian@poessinger.com>2019-08-30 13:00:55 +0200
commitffd45bf460b312f1799dc8418724bf597b2ffa20 (patch)
tree4fa5e1aa509081452c0634f3f7b2343af49290f6
parent758715df97dea209bffd1a935b70a765a80d2d81 (diff)
downloadvyos-1x-ffd45bf460b312f1799dc8418724bf597b2ffa20.tar.gz
vyos-1x-ffd45bf460b312f1799dc8418724bf597b2ffa20.zip
Python/ifconfig: re-work IP address creation/deletion
-rw-r--r--python/vyos/interfaceconfig.py222
1 files changed, 82 insertions, 140 deletions
diff --git a/python/vyos/interfaceconfig.py b/python/vyos/interfaceconfig.py
index 5bed90494..9790fae49 100644
--- a/python/vyos/interfaceconfig.py
+++ b/python/vyos/interfaceconfig.py
@@ -23,6 +23,10 @@ import socket
import subprocess
import ipaddress
+from vyos.validate import *
+from ipaddress import IPv4Network, IPv6Address
+from netifaces import ifaddresses, AF_INET, AF_INET6
+
dhclient_conf_dir = r'/var/lib/dhcp/dhclient_'
class Interface:
@@ -246,161 +250,99 @@ class Interface:
return False
- def get_addr(self, ret_prefix=None):
- """
- universal: reads all IPs assigned to an interface and returns it in a list,
- or None if no IP address is assigned to the interface. Also may return
- in prefix format if set ret_prefix
+ def get_addr(self):
"""
- ips = []
- try:
- ret = subprocess.check_output(
- ['ip -j addr show dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- j = json.loads(ret)
- for i in j:
- if len(i) != 0:
- for addr in i['addr_info']:
- if ret_prefix:
- ips.append(
- addr['local'] + "/" + str(addr['prefixlen']))
- else:
- ips.append(addr['local'])
- return ips
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
+ Retrieve assigned IPv4 and IPv6 addresses from given interface.
+ This is done using the netifaces and ipaddress python modules.
- def get_ipv4_addr(self):
- """
- reads all IPs assigned to an interface and returns it in a list,
- or None if no IP address is assigned to the interface
- """
- ips = []
- try:
- ret = subprocess.check_output(
- ['ip -j -4 addr show dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- j = json.loads(ret)
- for i in j:
- if len(i) != 0:
- for addr in i['addr_info']:
- ips.append(addr['local'])
- return ips
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
+ Example:
- def get_ipv6_addr(self):
- """
- reads all IPs assigned to an interface and returns it in a list,
- or None if no IP address is assigned to the interface
+ from vyos.interfaceconfig import Interface
+ i = Interface('ens192')
+ i.get_addrs()
+ ['172.16.33.30/24', 'fe80::20c:29ff:fe11:a174/64']
"""
- ips = []
- try:
- ret = subprocess.check_output(
- ['ip -j -6 addr show dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- j = json.loads(ret)
- for i in j:
- if len(i) != 0:
- for addr in i['addr_info']:
- ips.append(addr['local'])
- return ips
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
- def add_addr(self, ipaddr=[]):
- """
- universal: add ipv4/ipv6 addresses on the interface
- """
- for ip in ipaddr:
- proto = '-4'
- if ipaddress.ip_address(ip.split(r'/')[0]).version == 6:
- proto = '-6'
+ ipv4 = []
+ ipv6 = []
- try:
- ret = subprocess.check_output(
- ['ip ' + proto + ' address add ' + ip + ' dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
- return True
+ if AF_INET in ifaddresses(self._ifname).keys():
+ for v4_addr in ifaddresses(self._ifname)[AF_INET]:
+ # we need to manually assemble a list of IPv4 address/prefix
+ prefix = '/' + str(IPv4Network('0.0.0.0/' + v4_addr['netmask']).prefixlen)
+ ipv4.append( v4_addr['addr'] + prefix )
- def del_addr(self, ipaddr=[]):
- """
- universal: delete ipv4/ipv6 addresses on the interface
- """
- for ip in ipaddr:
- proto = '-4'
- if ipaddress.ip_address(ip.split(r'/')[0]).version == 6:
- proto = '-6'
- try:
- ret = subprocess.check_output(
- ['ip ' + proto + ' address del ' + ip + ' dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
- return True
+ if AF_INET6 in ifaddresses(self._ifname).keys():
+ for v6_addr in ifaddresses(self._ifname)[AF_INET6]:
+ # Note that currently expanded netmasks are not supported. That means
+ # 2001:db00::0/24 is a valid argument while 2001:db00::0/ffff:ff00:: not.
+ # see https://docs.python.org/3/library/ipaddress.html
+ bits = bin( int(v6_addr['netmask'].replace(':',''), 16) ).count('1')
+ prefix = '/' + str(bits)
- def add_ipv4_addr(self, ipaddr=[]):
- """
- add addresses on the interface
- """
- for ip in ipaddr:
- try:
- ret = subprocess.check_output(
- ['ip -4 address add ' + ip + ' dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
- return True
+ # we alsoneed to remove the interface suffix on link local addresses
+ v6_addr['addr'] = v6_addr['addr'].split('%')[0]
+ ipv6.append( v6_addr['addr'] + prefix )
+
+ return ipv4 + ipv6
- def del_ipv4_addr(self, ipaddr=[]):
- """
- delete addresses on the interface
- """
- for ip in ipaddr:
- try:
- ret = subprocess.check_output(
- ['ip -4 address del ' + ip + ' dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
- return True
- def add_ipv6_addr(self, ipaddr=[]):
+ def add_addr(self, addr=None):
"""
- add addresses on the interface
+ Add IP address to interface. Address is only added if it yet not added
+ to that interface.
+
+ Example:
+
+ >>> from vyos.interfaceconfig import Interface
+ >>> j = Interface('br100', type='bridge')
+ >>> j.add_addr('192.0.2.1/24')
+ >>> j.add_addr('2001:db8::ffff/64')
+ >>> j.get_addr()
+ ['192.0.2.1/24', '2001:db8::ffff/64']
"""
- for ip in ipaddr:
- try:
- ret = subprocess.check_output(
- ['ip -6 address add ' + ip + ' dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
- return True
- def del_ipv6_addr(self, ipaddr=[]):
+ if not addr:
+ raise ValueError('No IP address specified')
+
+ if not is_intf_addr_assigned(self._ifname, addr):
+ cmd = ''
+ if is_ipv4(addr):
+ cmd = 'sudo ip -4 addr add "{}" broadcast + dev "{}"'.format(addr, self._ifname)
+ elif is_ipv6(addr):
+ cmd = 'sudo ip -6 addr add "{}" dev "{}"'.format(addr, self._ifname)
+
+ self._cmd(cmd)
+
+
+ def del_addr(self, addr=None):
"""
- delete addresses on the interface
+ Remove IP address from interface.
+
+ Example:
+ >>> from vyos.interfaceconfig import Interface
+ >>> j = Interface('br100', type='bridge')
+ >>> j.add_addr('2001:db8::ffff/64')
+ >>> j.add_addr('192.0.2.1/24')
+ >>> j.get_addr()
+ ['192.0.2.1/24', '2001:db8::ffff/64']
+ >>> j.del_addr('192.0.2.1/24')
+ >>> j.get_addr()
+ ['2001:db8::ffff/64']
"""
- for ip in ipaddr:
- try:
- ret = subprocess.check_output(
- ['ip -6 address del ' + ip + ' dev ' + self._ifname], stderr=subprocess.STDOUT, shell=True).decode()
- except subprocess.CalledProcessError as e:
- if self._debug():
- self._debug(e)
- return None
- return True
+
+ if not addr:
+ raise ValueError('No IP address specified')
+
+ if is_intf_addr_assigned(self._ifname, addr):
+ cmd = ''
+ if is_ipv4(addr):
+ cmd = 'ip -4 addr del "{}" dev "{}"'.format(addr, self._ifname)
+ elif is_ipv6(addr):
+ cmd = 'ip -6 addr del "{}" dev "{}"'.format(addr, self._ifname)
+
+ self._cmd(cmd)
+
# replace dhcpv4/v6 with systemd.networkd?
def set_dhcpv4(self):