Commit 5be02880 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Add networkmanager mode

parent a0e64482
......@@ -8,12 +8,13 @@ import hostinfo.ifconfig
import hostinfo.macosx_auto
import hostinfo.mio
import hostinfo.named
import hostinfo.networkmanager
import hostinfo.parser
import hostinfo.pxelinux
import hostinfo.samba
import hostinfo.yp
import hostinfo.role
import hostinfo.samba
import hostinfo.util
import hostinfo.yp
import argparse
import os
import sys
......@@ -237,6 +238,9 @@ if __name__ == '__main__':
optParser.add_argument("--netgroup",
action="store", metavar="FILE",
help="Generate netgroup FILE")
optParser.add_argument("--networkmanager",
action="store_true",
help="Update network manager settings")
optParser.add_argument("--next_server",
action="store", metavar="HOST",
help="Use HOST as DHCP next-server")
......@@ -278,6 +282,10 @@ if __name__ == '__main__':
hostinfo.role.generate(tree, None, None)
sys.exit(0)
if options.networkmanager:
hostinfo.networkmanager.execute(tree, host)
sys.exit(0)
if options.dfs:
for (f, c) in hostinfo.samba.msdfs(tree):
symlink["%s/%s" % (options.dfs, f)] = c
......@@ -359,6 +367,7 @@ if __name__ == '__main__':
if options.samba:
file[options.samba] = (hostinfo.samba.share(tree, host), None)
result = 1
for name in file.keys():
write = False
......
......@@ -246,7 +246,7 @@ def generate(tree, host):
config += 'NAME=%s\n' % i.bridge[0]
config += 'ONBOOT=yes\n'
config += 'TYPE=Bridge\n'
config += 'STP=off\n'
config += 'STP=on\n'
config += get_nm_extra(i.bridge[0])
config += generate_ifcfg(tree, i)
result.append(('ifcfg-%s' % i.bridge[0], config))
......
import NetworkManager
import hostinfo.util as util
from copy import deepcopy
def dict_get(d, *i):
for k in i:
if not k in d:
return None
d = d[k]
pass
return d
class Network(object):
def __init__(self):
self._networks = []
self.reload()
pass
def reload(self):
self._bridge = {}
self._wired = {}
self._tunnel = {}
self._tun = {}
self._connection = {}
# Get devices from network manager
for d in NetworkManager.NetworkManager.AllDevices:
if isinstance(d, NetworkManager.Generic):
pass
elif isinstance(d, NetworkManager.Dummy):
pass
elif isinstance(d, NetworkManager.Wireless):
pass
elif isinstance(d, NetworkManager.Wired):
self._wired[d.HwAddress.lower()] = d
pass
elif isinstance(d, NetworkManager.Bridge):
self._bridge[d.HwAddress.lower()] = d
pass
elif isinstance(d, NetworkManager.IPTunnel):
self._tunnel[d.Interface] = d
pass
elif isinstance(d, NetworkManager.Tun):
self._tun[d.Interface] = d
pass
else:
print("UNKNOWN", d.__class__, dir(d))
pass
for c in NetworkManager.Settings.ListConnections():
s = c.GetSettings()
c_type = dict_get(s, 'connection', 'type')
c_uuid = dict_get(s, 'connection', 'uuid')
c_id = dict_get(s, 'connection', 'id')
c_mac = dict_get(s, c_type, 'mac-address')
c_mac = c_mac and c_mac.lower()
self._connection[c_type, c_mac, c_id, c_uuid] = c
pass
# from pprint import pprint
# print('Wired')
# pprint(self._wired)
# print('Bridge')
# pprint(self._bridge)
# print('Tunnel')
# pprint(self._tunnel)
# print('Tun')
# pprint(self._tun)
# print('Connection')
# pprint(self._connection)
def parse_tree(self, tree):
for s in filter(util.network, tree._subnet_):
self._networks.append(util.network(s))
pass
pass
def wired_device_name(self, ethernet):
if ethernet in self._wired:
return self._wired[ethernet].Interface
return None
def get_wired(self, ethernet):
if ethernet in self._wired:
return self._wired[ethernet]
return None
def get_bridge(self, ethernet):
if ethernet in self._bridge:
return self._bridge[ethernet]
return None
def get_connections(self, kind, mac=None, id=None, uuid=None):
result = []
for k,m,i,u in self._connection.keys():
if k != kind:
continue
if mac and (mac != m):
continue
if id and (id != i):
continue
if uuid and (uuid != u):
continue
result.append(self._connection[k,m,i,u])
pass
return result
def address_data(self, address):
a = util.address(address)
if a:
for n in self._networks:
if a in n:
return dict(address=a.compressed, prefix=n.prefixlen)
pass
raise Exception("No network found for", a)
return None
pass
network = Network()
def ipv6_dhcp_duid(interface):
duid = set()
for ipv6 in interface._ipv6_:
duid.add(ipv6.nm_ipv6_dhcp_duid[0:])
pass
if len(duid) != 1:
raise Exception("Multiple nm_dhcp_duid's specified %s", duid)
return duid.pop()
def update_settings(settings, update):
result = deepcopy(settings)
for k,v in update.items():
d = result
for i in k[:-1]:
d = d[i]
pass
if v != None:
d[k[-1]] = v
elif k[-1] in d:
del d[k[-1]]
pass
return result
def configure_networking(connection, interface):
# Construct ipv4 and ipv6 data to be set in bridge
update = dict()
if not interface._static_:
update['ipv4', 'method'] = 'auto'
update['ipv6', 'method'] = 'auto'
update['ipv6', 'dhcp-duid'] = ipv6_dhcp_duid(interface)
pass
else:
ipv4 = list(filter(None,
[network.address_data(i) for i in interface._ip_]))
ipv6 = list(filter(None,
[network.address_data(i) for i in interface._ipv6_]))
update['ipv4', 'address-data'] = ipv4
update['ipv6', 'address-data'] = ipv6
update['ipv4', 'method'] = ('link-local','manual')[len(ipv4) > 0]
update['ipv6', 'method'] = ('link-local','manual')[len(ipv6) > 0]
update['ipv6', 'dhcp-duid'] = None
pass
if interface.bridge[0]:
# (stp == 'no') -> False, else None
update['bridge', 'stp'] = (None,False)[interface.stp[0] == 'no']
before = connection.GetSettings()
after = update_settings(before, update)
if before != after:
connection.Update(after)
return True
return False
def configure_bridge_interface(tree, interface):
bridge_name = interface.bridge[0] or interface.bridge_to[0]
device_name = network.wired_device_name(interface.ethernet[0])
if device_name == None:
raise util.HostinfoException("No device (%s)" % interface.ethernet[0])
config_name = '%s-%s' % (bridge_name, device_name)
# Try to find bridge matching the specs
dev = network.get_wired(ethernet=interface.ethernet[0])
connection = None
if dev and dev.ActiveConnection and dev.ActiveConnection.Id == config_name:
connection = dev.ActiveConnection.Connection
pass
if connection == None:
candidates = network.get_connections(kind='802-3-ethernet',
id=config_name)
if len(candidates):
connection = candidates[0]
pass
pass
# Create new connection if not found
if connection == None:
settings = {
'802-3-ethernet': {
'assigned-mac-address': 'preserve',
'mac-address': interface.ethernet[0]
},
'connection': {
'id': config_name,
'interface-name': dev.Interface,
'master': bridge_name,
'slave-type': 'bridge',
'type': '802-3-ethernet'
}
}
connection = NetworkManager.Settings.AddConnection(settings)
return True
return False
def configure_bridge(tree, interface):
bridge_name = interface.bridge[0]
device_name = network.wired_device_name(interface.ethernet[0])
if device_name == None:
raise util.HostinfoException("No device (%s)" % interface.ethernet[0])
# Try to find bridge matching the specs
bridge = network.get_bridge(ethernet=interface.ethernet[0])
if bridge and bridge.Interface == bridge_name:
bridge_connection = bridge.ActiveConnection.Connection
pass
else:
bridge_connection = None
pass
# Try to find wired connections matching the specs
if bridge_connection == None:
candidates = network.get_connections(kind='bridge', id=bridge_name)
if len(candidates):
bridge_connection = candidates[0]
# Create new connection if not found
if bridge_connection == None:
settings = { 'bridge': {'interface-name': bridge_name,
'mac-address': interface.ethernet[0]},
'connection': { 'type': 'bridge',
'id': bridge_name,
'interface-name': bridge_name }}
bridge_connection = NetworkManager.Settings.AddConnection(settings)
pass
return configure_networking(bridge_connection, interface)
def configure_interface(tree, interface):
result = False
device_name = network.wired_device_name(interface.ethernet[0])
config_name = device_name
# Try to find interface matching the specs
dev = network.get_wired(ethernet=interface.ethernet[0])
connection = None
if dev and dev.ActiveConnection and dev.ActiveConnection.Id == config_name:
connection = dev.ActiveConnection.Connection
pass
if connection == None:
candidates = network.get_connections(kind='802-3-ethernet',
id=config_name)
if len(candidates):
connection = candidates[0]
pass
pass
# Create new connection if not found
if connection == None:
settings = {
'802-3-ethernet': {
'assigned-mac-address': 'preserve',
'mac-address': interface.ethernet[0]
},
'connection': {
'id': config_name,
'interface-name': dev.Interface,
'type': '802-3-ethernet'
}
}
connection = NetworkManager.Settings.AddConnection(settings)
result = True
pass
return configure_networking(connection, interface)
def activate_bridge_interface(interface):
bridge_name = interface.bridge[0] or interface.bridge_to[0]
device_name = network.wired_device_name(interface.ethernet[0])
config_name = '%s-%s' % (bridge_name, device_name)
candidates = network.get_connections(kind='802-3-ethernet', id=config_name)
if len(candidates):
connection = candidates[0]
NetworkManager.NetworkManager.ActivateConnection(
connection, network.get_wired(interface.ethernet[0]), '/')
pass
pass
def activate_bridge(interface):
bridge_name = interface.bridge[0] or interface.bridge_to[0]
candidates = network.get_connections(kind='bridge', id=bridge_name)
if len(candidates):
connection = candidates[0]
NetworkManager.NetworkManager.ActivateConnection(
connection, network.get_bridge(interface.ethernet[0]), '/')
pass
pass
def activate_interface(interface):
device_name = network.wired_device_name(interface.ethernet[0])
config_name = device_name
candidates = network.get_connections(kind='802-3-ethernet', id=config_name)
if len(candidates):
connection = candidates[0]
NetworkManager.NetworkManager.ActivateConnection(
connection, network.get_wired(interface.ethernet[0]), '/')
pass
pass
def execute(tree, host):
network.parse_tree(tree)
for h in tree._host_:
if h.name[0] != host:
continue
for i in h._interface_:
if not i.ethernet[0]:
continue
changed = False
if i.bridge[0]:
changed |= configure_bridge_interface(tree, i)
changed |= configure_bridge(tree, i)
pass
elif i.bridge_to[0]:
changed |= configure_bridge_interface(tree, i)
pass
else:
changed |= configure_interface(tree, i)
pass
if changed:
network.reload()
if i.bridge[0]:
activate_bridge_interface(i)
activate_bridge(i)
pass
elif i.bridge_to[0]:
activate_bridge_interface(i)
pass
else:
activate_interface(i)
pass
pass
pass
pass
return
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment