20
20
arch linux network helper module
23
# Arch has two different kinds of network configuration. More recently,
24
# there's 'netcfg' and previously (for lack of a better term) 'legacy'.
27
# - 1 shell-script-style global configuration (/etc/rc.conf)
28
# - one IP per interface
29
# - routes are per interface
30
# - gateways are global
31
# - DNS is per interface
34
# - multiple shell-script-style network configurations, 1 per interface
35
# - one IP per configuration
36
# - routes are per interface
37
# - gateways are per interface
38
# - DNS is global (/etc/resolv.conf)
51
def configure_network(network_config, *args, **kwargs):
53
# Update config file with new interface configuration
54
interfaces = network_config.get('interfaces', [])
56
# Check if netcfg is installed (and should be used)
64
def configure_network(hostname, interfaces):
65
# Arch is a rolling release, meaning new features and updated packages
66
# roll out on a unpredictable schedule. It also means there is no such
67
# thing as v1.0 or v2.0. So, let's try checking if the netcfg package
68
# is installed to see what format should be used.
57
69
status = _execute(['/usr/bin/pacman', '-Q', 'netcfg'])
58
70
use_netcfg = (status == 0)
70
82
remove_files = set()
72
84
# Generate new /etc/resolv.conf file
73
data = _get_resolv_conf(interfaces)
74
update_files[RESOLV_FILE] = data
85
filepath, data = commands.network.get_resolv_conf(interfaces)
87
update_files[filepath] = data
76
89
# Update config file with new hostname
77
hostname = network_config.get('hostname')
79
90
infile = StringIO(update_files.get(CONF_FILE, ''))
81
92
data = get_hostname_file(infile, hostname)
136
147
return outfile.read()
139
def _get_resolv_conf(interfaces):
141
for interface in interfaces:
142
if interface['label'] != 'public':
145
for nameserver in interface.get('dns', []):
146
resolv_data += 'nameserver %s\n' % nameserver
151
return '# Automatically generated, do not edit\n' + resolv_data
154
150
def _parse_variable(line):
155
151
k, v = line.split('=')
179
for interface in interfaces:
181
label = interface['label']
183
raise SystemError("No interface label found")
186
ifname_prefix = INTERFACE_LABELS[label]
188
raise SystemError("Invalid label '%s'" % label)
190
ip4s = interface.get('ips', [])
191
ip6s = interface.get('ip6s', [])
193
if not ip4s and not ip6s:
194
raise SystemError("No IPs found for interface")
197
mac = interface['mac']
199
raise SystemError("No mac address found for interface")
201
if label == "public":
202
gateway4 = interface.get('gateway')
203
gateway6 = interface.get('gateway6')
205
if not gateway4 and not gateway6:
206
raise SystemError("No gateway found for public interface")
209
dns = interface['dns']
211
raise SystemError("No DNS found for public interface")
213
gateway4 = gateway6 = None
175
gateway4, gateway6 = commands.network.get_gateways(interfaces)
177
ifnames = interfaces.keys()
180
for ifname_prefix in ifnames:
181
interface = interfaces[ifname_prefix]
183
ip4s = interface['ip4s']
184
ip6s = interface['ip6s']
215
186
ifname_suffix_num = 0
217
for i in xrange(max(len(ip4s), len(ip6s))):
188
for ip4, ip6 in map(None, ip4s, ip6s):
218
189
if ifname_suffix_num:
219
190
ifname = "%s:%d" % (ifname_prefix, ifname_suffix_num)
221
192
ifname = ifname_prefix
227
enabled = ip_info.get('enabled', '0')
231
netmask = ip_info['netmask']
234
"Missing IP or netmask in interface's IP list")
236
line.append('%s netmask %s' % (ip, netmask))
241
enabled = ip_info.get('enabled', '0')
243
ip = ip_info.get('address', ip_info.get('ip'))
246
"Missing IP in interface's IP list")
247
netmask = ip_info.get('netmask')
250
"Missing netmask in interface's IP list")
253
gateway6 = ip_info.get('gateway', gateway6)
255
line.append('add %s/%s' % (ip, netmask))
196
line.append('%(address)s netmask %(netmask)s' % ip4)
199
line.append('add %(address)s/%(prefixlen)s' % ip6)
257
201
ifname_suffix_num += 1
259
203
ifaces.append((ifname.replace(':', '_'), ' '.join(line)))
261
for i, route in enumerate(interface.get('routes', [])):
262
network = route['route']
263
netmask = route['netmask']
264
gateway = route['gateway']
266
line = "-net %s netmask %s gw %s" % (network, netmask, gateway)
205
for i, route in enumerate(interface['routes']):
206
line = "-net %(network)s netmask %(netmask)s gw %(gateway)s" % \
268
209
routes.append(('%s_route%d' % (ifname_prefix, i), line))
364
305
return outfile.read()
367
def _get_file_data_netcfg(interface):
308
def _get_file_data_netcfg(ifname_prefix, interface):
369
310
Return data for (sub-)interfaces
375
label = interface['label']
377
raise SystemError("No interface label found")
380
ifname_prefix = INTERFACE_LABELS[label]
382
raise SystemError("Invalid label '%s'" % label)
384
ip4s = interface.get('ips', [])
385
ip6s = interface.get('ip6s', [])
387
if not ip4s and not ip6s:
388
raise SystemError("No IPs found for interface")
391
mac = interface['mac']
393
raise SystemError("No mac address found for interface")
395
if label == "public":
396
gateway4 = interface.get('gateway')
397
gateway6 = interface.get('gateway6')
399
if not gateway4 and not gateway6:
400
raise SystemError("No gateway found for public interface")
403
dns = interface['dns']
405
raise SystemError("No DNS found for public interface")
407
gateway4 = gateway6 = dns = None
315
ip4s = interface['ip4s']
316
ip6s = interface['ip6s']
318
gateway4 = interface['gateway4']
319
gateway6 = interface['gateway6']
321
dns = interface['dns']
409
323
ifname_suffix_num = 0
411
for i in xrange(max(len(ip4s), len(ip6s))):
325
for ip4, ip6 in map(None, ip4s, ip6s):
412
326
if ifname_suffix_num:
413
327
ifname = "%s:%d" % (ifname_prefix, ifname_suffix_num)
419
333
print >>outfile, 'CONNECTION="ethernet"'
420
334
print >>outfile, 'INTERFACE=%s' % ifname
425
enabled = ip_info.get('enabled', '0')
429
netmask = ip_info['netmask']
432
"Missing IP or netmask in interface's IP list")
434
print >>outfile, 'IP="static"'
435
print >>outfile, 'ADDR="%s"' % ip
436
print >>outfile, 'NETMASK="%s"' % netmask
438
print >>outfile, 'GATEWAY="%s"' % gateway4
443
enabled = ip_info.get('enabled', '0')
445
ip = ip_info.get('address', ip_info.get('ip'))
448
"Missing IP in interface's IP list")
449
netmask = ip_info.get('netmask')
452
"Missing netmask in interface's IP list")
454
print >>outfile, 'IP6="static"'
455
print >>outfile, 'ADDR6="%s/%s"' % (ip, netmask)
457
gateway6 = ip_info.get('gateway', gateway6)
459
print >>outfile, 'GATEWAY6="%s"' % gateway6
337
print >>outfile, 'IP="static"'
338
print >>outfile, 'ADDR="%(address)s"' % ip4
339
print >>outfile, 'NETMASK="%(netmask)s"' % ip4
342
print >>outfile, 'GATEWAY="%s"' % gateway4
346
print >>outfile, 'IP6="static"'
347
print >>outfile, 'ADDR6="%(address)s/%(prefixlen)s"' % ip6
350
print >>outfile, 'GATEWAY6="%s"' % gateway6
461
353
if not ifname_suffix_num:
462
354
# Add routes to first interface
464
for route in interface.get('routes', []):
465
network = route['route']
466
netmask = route['netmask']
467
gateway = route['gateway']
468
routes.append('"%s/%s via %s"' % (network, netmask, gateway))
356
for route in interface['routes']:
357
routes.append('"%(network)s/%(netmask)s via %(gateway)s"' %
471
361
print >>outfile, 'ROUTES=(%s)' % ' '.join(routes)
554
444
if version == 'netcfg':
555
445
update_files = {}
557
for interface in interfaces:
558
ifaces = _get_file_data_netcfg(interface)
447
for ifname, interface in interfaces.iteritems():
448
subifaces = _get_file_data_netcfg(ifname, interface)
560
for ifname, data in ifaces:
450
for ifname, data in subifaces:
561
451
filename = ifname.replace(':', '_')
562
452
filepath = os.path.join(NETWORK_DIR, filename)
563
453
update_files[filepath] = data
594
484
remove_files.add(filepath)
597
for interface in interfaces:
598
subifaces = _get_file_data_netcfg(interface)
487
for ifname, interface in interfaces.iteritems():
488
subifaces = _get_file_data_netcfg(ifname, interface)
600
490
for ifname, data in subifaces:
601
491
filename = ifname.replace(':', '_')