~rackspace-ozone/openstack-guest-agents/trunk

« back to all changes in this revision

Viewing changes to unix/commands/arch/network.py

  • Committer: Johannes Erdfelt
  • Date: 2011-10-21 16:50:41 UTC
  • mfrom: (88.3.17 networking-refactor)
  • Revision ID: johannes.erdfelt@rackspace.com-20111021165041-smmnytu2xezh2751
MergeĀ lp:~johannes.erdfelt/openstack-guest-agents/networking-refactor

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
arch linux network helper module
21
21
"""
22
22
 
 
23
# Arch has two different kinds of network configuration. More recently,
 
24
# there's 'netcfg' and previously (for lack of a better term) 'legacy'.
 
25
#
 
26
# legacy uses:
 
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
 
32
#
 
33
# netcfg uses:
 
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)
 
39
 
23
40
import os
24
41
import re
25
42
import time
31
48
 
32
49
CONF_FILE = "/etc/rc.conf"
33
50
NETWORK_DIR = "/etc/network.d"
34
 
RESOLV_FILE = "/etc/resolv.conf"
35
 
 
36
 
INTERFACE_LABELS = {"public": "eth0",
37
 
                    "private": "eth1"}
38
51
 
39
52
 
40
53
def _execute(command):
48
61
    return status
49
62
 
50
63
 
51
 
def configure_network(network_config, *args, **kwargs):
52
 
 
53
 
    # Update config file with new interface configuration
54
 
    interfaces = network_config.get('interfaces', [])
55
 
 
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)
59
71
 
70
82
        remove_files = set()
71
83
 
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)
 
86
        if data:
 
87
            update_files[filepath] = data
75
88
 
76
89
    # Update config file with new hostname
77
 
    hostname = network_config.get('hostname')
78
 
 
79
90
    infile = StringIO(update_files.get(CONF_FILE, ''))
80
91
 
81
92
    data = get_hostname_file(infile, hostname)
136
147
    return outfile.read()
137
148
 
138
149
 
139
 
def _get_resolv_conf(interfaces):
140
 
    resolv_data = ''
141
 
    for interface in interfaces:
142
 
        if interface['label'] != 'public':
143
 
            continue
144
 
 
145
 
        for nameserver in interface.get('dns', []):
146
 
            resolv_data += 'nameserver %s\n' % nameserver
147
 
 
148
 
    if not resolv_data:
149
 
        return ''
150
 
 
151
 
    return '# Automatically generated, do not edit\n' + resolv_data
152
 
 
153
 
 
154
150
def _parse_variable(line):
155
151
    k, v = line.split('=')
156
152
    v = v.strip()
176
172
    ifaces = []
177
173
    routes = []
178
174
 
179
 
    for interface in interfaces:
180
 
        try:
181
 
            label = interface['label']
182
 
        except KeyError:
183
 
            raise SystemError("No interface label found")
184
 
 
185
 
        try:
186
 
            ifname_prefix = INTERFACE_LABELS[label]
187
 
        except KeyError:
188
 
            raise SystemError("Invalid label '%s'" % label)
189
 
 
190
 
        ip4s = interface.get('ips', [])
191
 
        ip6s = interface.get('ip6s', [])
192
 
 
193
 
        if not ip4s and not ip6s:
194
 
            raise SystemError("No IPs found for interface")
195
 
 
196
 
        try:
197
 
            mac = interface['mac']
198
 
        except KeyError:
199
 
            raise SystemError("No mac address found for interface")
200
 
 
201
 
        if label == "public":
202
 
            gateway4 = interface.get('gateway')
203
 
            gateway6 = interface.get('gateway6')
204
 
 
205
 
            if not gateway4 and not gateway6:
206
 
                raise SystemError("No gateway found for public interface")
207
 
 
208
 
            try:
209
 
                dns = interface['dns']
210
 
            except KeyError:
211
 
                raise SystemError("No DNS found for public interface")
212
 
        else:
213
 
            gateway4 = gateway6 = None
 
175
    gateway4, gateway6 = commands.network.get_gateways(interfaces)
 
176
 
 
177
    ifnames = interfaces.keys()
 
178
    ifnames.sort()
 
179
 
 
180
    for ifname_prefix in ifnames:
 
181
        interface = interfaces[ifname_prefix]
 
182
 
 
183
        ip4s = interface['ip4s']
 
184
        ip6s = interface['ip6s']
214
185
 
215
186
        ifname_suffix_num = 0
216
187
 
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)
220
191
            else:
221
192
                ifname = ifname_prefix
222
193
 
223
194
            line = [ifname]
224
 
            if i < len(ip4s):
225
 
                ip_info = ip4s[i]
226
 
 
227
 
                enabled = ip_info.get('enabled', '0')
228
 
                if enabled != '0':
229
 
                    try:
230
 
                        ip = ip_info['ip']
231
 
                        netmask = ip_info['netmask']
232
 
                    except KeyError:
233
 
                        raise SystemError(
234
 
                                "Missing IP or netmask in interface's IP list")
235
 
 
236
 
                    line.append('%s netmask %s' % (ip, netmask))
237
 
 
238
 
            if i < len(ip6s):
239
 
                ip_info = ip6s[i]
240
 
 
241
 
                enabled = ip_info.get('enabled', '0')
242
 
                if enabled != '0':
243
 
                    ip = ip_info.get('address', ip_info.get('ip'))
244
 
                    if not ip:
245
 
                        raise SystemError(
246
 
                                "Missing IP in interface's IP list")
247
 
                    netmask = ip_info.get('netmask')
248
 
                    if not netmask:
249
 
                        raise SystemError(
250
 
                                "Missing netmask in interface's IP list")
251
 
 
252
 
                    if not gateway6:
253
 
                        gateway6 = ip_info.get('gateway', gateway6)
254
 
 
255
 
                    line.append('add %s/%s' % (ip, netmask))
 
195
            if ip4:
 
196
                line.append('%(address)s netmask %(netmask)s' % ip4)
 
197
 
 
198
            if ip6:
 
199
                line.append('add %(address)s/%(prefixlen)s' % ip6)
256
200
 
257
201
            ifname_suffix_num += 1
258
202
 
259
203
            ifaces.append((ifname.replace(':', '_'), ' '.join(line)))
260
204
 
261
 
        for i, route in enumerate(interface.get('routes', [])):
262
 
            network = route['route']
263
 
            netmask = route['netmask']
264
 
            gateway = route['gateway']
265
 
 
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" % \
 
207
                    route
267
208
 
268
209
            routes.append(('%s_route%d' % (ifname_prefix, i), line))
269
210
 
364
305
    return outfile.read()
365
306
 
366
307
 
367
 
def _get_file_data_netcfg(interface):
 
308
def _get_file_data_netcfg(ifname_prefix, interface):
368
309
    """
369
310
    Return data for (sub-)interfaces
370
311
    """
371
312
 
372
313
    ifaces = []
373
314
 
374
 
    try:
375
 
        label = interface['label']
376
 
    except KeyError:
377
 
        raise SystemError("No interface label found")
378
 
 
379
 
    try:
380
 
        ifname_prefix = INTERFACE_LABELS[label]
381
 
    except KeyError:
382
 
        raise SystemError("Invalid label '%s'" % label)
383
 
 
384
 
    ip4s = interface.get('ips', [])
385
 
    ip6s = interface.get('ip6s', [])
386
 
 
387
 
    if not ip4s and not ip6s:
388
 
        raise SystemError("No IPs found for interface")
389
 
 
390
 
    try:
391
 
        mac = interface['mac']
392
 
    except KeyError:
393
 
        raise SystemError("No mac address found for interface")
394
 
 
395
 
    if label == "public":
396
 
        gateway4 = interface.get('gateway')
397
 
        gateway6 = interface.get('gateway6')
398
 
 
399
 
        if not gateway4 and not gateway6:
400
 
            raise SystemError("No gateway found for public interface")
401
 
 
402
 
        try:
403
 
            dns = interface['dns']
404
 
        except KeyError:
405
 
            raise SystemError("No DNS found for public interface")
406
 
    else:
407
 
        gateway4 = gateway6 = dns = None
 
315
    ip4s = interface['ip4s']
 
316
    ip6s = interface['ip6s']
 
317
 
 
318
    gateway4 = interface['gateway4']
 
319
    gateway6 = interface['gateway6']
 
320
 
 
321
    dns = interface['dns']
408
322
 
409
323
    ifname_suffix_num = 0
410
324
 
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)
414
328
        else:
419
333
        print >>outfile, 'CONNECTION="ethernet"'
420
334
        print >>outfile, 'INTERFACE=%s' % ifname
421
335
 
422
 
        if i < len(ip4s):
423
 
            ip_info = ip4s[i]
424
 
 
425
 
            enabled = ip_info.get('enabled', '0')
426
 
            if enabled != '0':
427
 
                try:
428
 
                    ip = ip_info['ip']
429
 
                    netmask = ip_info['netmask']
430
 
                except KeyError:
431
 
                    raise SystemError(
432
 
                            "Missing IP or netmask in interface's IP list")
433
 
 
434
 
                print >>outfile, 'IP="static"'
435
 
                print >>outfile, 'ADDR="%s"' % ip
436
 
                print >>outfile, 'NETMASK="%s"' % netmask
437
 
                if gateway4:
438
 
                    print >>outfile, 'GATEWAY="%s"' % gateway4
439
 
 
440
 
        if i < len(ip6s):
441
 
            ip_info = ip6s[i]
442
 
 
443
 
            enabled = ip_info.get('enabled', '0')
444
 
            if enabled != '0':
445
 
                ip = ip_info.get('address', ip_info.get('ip'))
446
 
                if not ip:
447
 
                    raise SystemError(
448
 
                            "Missing IP in interface's IP list")
449
 
                netmask = ip_info.get('netmask')
450
 
                if not netmask:
451
 
                    raise SystemError(
452
 
                            "Missing netmask in interface's IP list")
453
 
 
454
 
                print >>outfile, 'IP6="static"'
455
 
                print >>outfile, 'ADDR6="%s/%s"' % (ip, netmask)
456
 
 
457
 
                gateway6 = ip_info.get('gateway', gateway6)
458
 
                if gateway6:
459
 
                    print >>outfile, 'GATEWAY6="%s"' % gateway6
 
336
        if ip4:
 
337
            print >>outfile, 'IP="static"'
 
338
            print >>outfile, 'ADDR="%(address)s"' % ip4
 
339
            print >>outfile, 'NETMASK="%(netmask)s"' % ip4
 
340
 
 
341
            if gateway4:
 
342
                print >>outfile, 'GATEWAY="%s"' % gateway4
 
343
                gateway4 = None
 
344
 
 
345
        if ip6:
 
346
            print >>outfile, 'IP6="static"'
 
347
            print >>outfile, 'ADDR6="%(address)s/%(prefixlen)s"' % ip6
 
348
 
 
349
            if gateway6:
 
350
                print >>outfile, 'GATEWAY6="%s"' % gateway6
 
351
                gateway6 = None
460
352
 
461
353
        if not ifname_suffix_num:
462
354
            # Add routes to first interface
463
355
            routes = []
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"' %
 
358
                        route)
469
359
 
470
360
            if routes:
471
361
                print >>outfile, 'ROUTES=(%s)' % ' '.join(routes)
554
444
    if version == 'netcfg':
555
445
        update_files = {}
556
446
        netnames = []
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)
559
449
 
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)
595
485
 
596
486
    netnames = []
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)
599
489
 
600
490
        for ifname, data in subifaces:
601
491
            filename = ifname.replace(':', '_')