networkmanager almost done; needs auto-dev for wifi/ethernet and handling of auto resolvers i think
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
try:
|
||||
from . import _common
|
||||
except ImportError:
|
||||
pass # GI isn't supported, so we don't even use a fallback.
|
||||
# try:
|
||||
# from . import _common
|
||||
# except ImportError:
|
||||
# pass # GI isn't supported, so we don't even use a fallback.
|
||||
|
||||
from . import netctl
|
||||
|
||||
@@ -15,10 +15,5 @@ try:
|
||||
except ImportError:
|
||||
from . import networkd_fallback as networkd
|
||||
|
||||
|
||||
try:
|
||||
from . import networkmanager
|
||||
except ImportError:
|
||||
from . import networkmanager_fallback
|
||||
|
||||
from . import networkmanager
|
||||
from . import net
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import gi
|
||||
gi.require_version('NM', '1.0')
|
||||
from gi.repository import GObject, NM, GLib
|
||||
# import gi
|
||||
# gi.require_version('NM', '1.0')
|
||||
# from gi.repository import GObject, NM, GLib
|
||||
|
||||
@@ -14,9 +14,11 @@ class Network(object):
|
||||
if not self.provider:
|
||||
raise RuntimeError('Could not determine handler')
|
||||
self.connections = []
|
||||
self._initConns()
|
||||
|
||||
def _initConns(self):
|
||||
for e in self.xml.xpath('ethernet|wireless'):
|
||||
conn = None
|
||||
if e.tag == 'ethernet':
|
||||
conn = self.provider.Ethernet(e)
|
||||
elif e.tag == 'wireless':
|
||||
|
||||
@@ -1,47 +1,141 @@
|
||||
import configparser
|
||||
import datetime
|
||||
import ipaddress
|
||||
import os
|
||||
import uuid
|
||||
##
|
||||
from . import _common
|
||||
import aif.utils
|
||||
|
||||
_NM = _common.NM
|
||||
# TODO: auto dev assignment
|
||||
|
||||
|
||||
class Connection(object):
|
||||
def __init__(self, iface_xml):
|
||||
self.xml = iface_xml
|
||||
self.id = self.xml.attrib['id']
|
||||
self.device = self.xml.attrib['device']
|
||||
self.is_defroute = aif.utils.xmlBool(self.xml.attrib.get('defroute', 'false'))
|
||||
self.domain = self.xml.attrib.get('searchDomain', None)
|
||||
self._cfg = None
|
||||
self.connection_type = None
|
||||
self.provider_type = 'NetworkManager'
|
||||
self.client = _NM.Client.new()
|
||||
self.addrs = {'ipv4': [],
|
||||
'ipv6': []}
|
||||
self.addrs = {'ipv4': set(),
|
||||
'ipv6': set()}
|
||||
self.resolvers = []
|
||||
self.uuid = uuid.uuid4()
|
||||
self._initAddrs()
|
||||
self._initResolvers()
|
||||
|
||||
def _initAddrs(self):
|
||||
for t in ('ipv4', 'ipv6'):
|
||||
for a in self.xml.findall('addresses/{0}/address'.format(t)):
|
||||
# These tuples follow either:
|
||||
# ('dhcp'/'dhcp6'/'slaac', None, None) for auto configuration
|
||||
# (ipaddress.IPv4/6Address(IP), CIDR, ipaddress.IPv4/6Address(GW)) for static configuration
|
||||
for addrtype in ('ipv4', 'ipv6'):
|
||||
for a in self.xml.findall('addresses/{0}/address'.format(addrtype)):
|
||||
if a.text in ('dhcp', 'dhcp6', 'slaac'):
|
||||
addr = net = None
|
||||
addr = a.text
|
||||
net = None
|
||||
gw = None
|
||||
else:
|
||||
components = a.text.split('/')
|
||||
if len(components) > 2:
|
||||
raise ValueError('Invalid IP/CIDR format: {0}'.format(a.text))
|
||||
if len(components) == 1:
|
||||
addr = components[0]
|
||||
if t == 'ipv4':
|
||||
if addrtype == 'ipv4':
|
||||
components.append('24')
|
||||
elif t == 'ipv6':
|
||||
elif addrtype == 'ipv6':
|
||||
components.append('64')
|
||||
addr = ipaddress.ip_address(components[0])
|
||||
net = ipaddress.ip_network('/'.join(components), strict = False)
|
||||
self.addrs[t].append((addr, net))
|
||||
gw = ipaddress.ip_address(a.attrib.get('gateway'))
|
||||
self.addrs[addrtype].add((addr, net, gw))
|
||||
self.addrs[addrtype] = list(self.addrs[addrtype])
|
||||
return()
|
||||
|
||||
def _initCfg(self):
|
||||
self._cfg = configparser.ConfigParser()
|
||||
self._cfg.optionxform = str
|
||||
self._cfg['connection'] = {'id': self.id,
|
||||
'uuid': self.uuid,
|
||||
'type': self.connection_type,
|
||||
'interface-name': self.device,
|
||||
'permissions': '',
|
||||
'timestamp': datetime.datetime.utcnow().timestamp()}
|
||||
# We *theoretically* could do this in _initAddrs() but we do it separately so we can trim out duplicates.
|
||||
for addrtype, addrs in self.addrs.items():
|
||||
self._cfg[addrtype] = {}
|
||||
cidr_gws = {}
|
||||
self._cfg[addrtype]['dns-search'] = (self.domain if self.domain else '')
|
||||
if addrtype == 'ipv6':
|
||||
self._cfg[addrtype]['addr-gen-mode'] = 'stable-privacy'
|
||||
if not addrs:
|
||||
self._cfg[addrtype]['method'] = 'ignore'
|
||||
else:
|
||||
self._cfg[addrtype]['method'] = 'manual'
|
||||
for idx, (ip, cidr, gw) in enumerate(addrs):
|
||||
if cidr not in cidr_gws.keys():
|
||||
cidr_gws[cidr] = gw
|
||||
new_cidr = True
|
||||
else:
|
||||
new_cidr = False
|
||||
if addrtype == 'ipv4':
|
||||
if ip == 'dhcp':
|
||||
self._cfg[addrtype]['method'] = 'auto'
|
||||
continue
|
||||
elif addrtype == 'ipv6':
|
||||
if ip == 'dhcp6':
|
||||
self._cfg[addrtype]['method'] = 'dhcp'
|
||||
continue
|
||||
elif ip == 'slaac':
|
||||
self._cfg[addrtype]['method'] = 'auto'
|
||||
continue
|
||||
addrnum = idx + 1
|
||||
addr_str = '{0}/{1}'.format(str(ip), str(cidr.prefixlen))
|
||||
if new_cidr:
|
||||
addr_str = '{0},{1}'.format(addr_str, str(gw))
|
||||
self._cfg[addrtype]['address{0}'.format(addrnum)] = addr_str
|
||||
for r in self.resolvers:
|
||||
if addrtype == 'ipv{0}'.format(r.version):
|
||||
if 'dns' not in self._cfg[addrtype]:
|
||||
self._cfg[addrtype]['dns'] = []
|
||||
self._cfg[addrtype]['dns'].append(str(r))
|
||||
if 'dns' in self._cfg[addrtype].keys():
|
||||
self._cfg[addrtype]['dns'] = '{0};'.format(';'.join(self._cfg[addrtype]['dns']))
|
||||
self._initConnCfg()
|
||||
return()
|
||||
|
||||
def _initConnCfg(self):
|
||||
# A dummy method; this is overridden by the subclasses.
|
||||
# It's honestly here to make my IDE stop complaining. :)
|
||||
pass
|
||||
return()
|
||||
|
||||
def _initResolvers(self):
|
||||
for r in self.xml.findall('resolvers/resolver'):
|
||||
self.resolvers.append(ipaddress.ip_address(r.text))
|
||||
resolver = ipaddress.ip_address(r.text)
|
||||
if resolver not in self.resolvers:
|
||||
self.resolvers.append(resolver)
|
||||
return()
|
||||
|
||||
def writeConf(self, chroot_base):
|
||||
cfgroot = os.path.join(chroot_base, 'etc', 'NetworkManager')
|
||||
cfgdir = os.path.join(cfgroot, 'system-connections')
|
||||
cfgpath = os.path.join(cfgdir, '{0}.nmconnection'.format(self.id))
|
||||
os.makedirs(cfgdir, exist_ok = True)
|
||||
with open(cfgpath, 'w') as fh:
|
||||
self._cfg.write(fh, space_around_delimiters = False)
|
||||
for root, dirs, files in os.walk(cfgroot):
|
||||
os.chown(root, 0, 0)
|
||||
for d in dirs:
|
||||
dpath = os.path.join(root, d)
|
||||
os.chown(dpath, 0, 0)
|
||||
for f in files:
|
||||
fpath = os.path.join(root, f)
|
||||
os.chown(fpath, 0, 0)
|
||||
os.chmod(cfgroot, 0o0755)
|
||||
os.chmod(cfgdir, 0o0700)
|
||||
os.chmod(cfgpath, 0o0600)
|
||||
return()
|
||||
|
||||
|
||||
@@ -49,9 +143,17 @@ class Ethernet(Connection):
|
||||
def __init__(self, iface_xml):
|
||||
super().__init__(iface_xml)
|
||||
self.connection_type = 'ethernet'
|
||||
self._initCfg()
|
||||
|
||||
def _initConnCfg(self):
|
||||
pass
|
||||
|
||||
|
||||
class Wireless(Connection):
|
||||
def __init__(self, iface_xml):
|
||||
super().__init__(iface_xml)
|
||||
self.connection_type = 'wireless'
|
||||
self._initCfg()
|
||||
|
||||
def _initConnCfg(self):
|
||||
pass
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
import subprocess
|
||||
Reference in New Issue
Block a user