~johannes.erdfelt/openstack-guest-agents/gentoo-dns

« back to all changes in this revision

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

  • Committer: Johannes Erdfelt
  • Date: 2011-12-01 16:03:13 UTC
  • mfrom: (98.1.2 arch-fixes)
  • Revision ID: johannes.erdfelt@rackspace.com-20111201160313-m2tpwkm5yyr1qusg
MergeĀ lp:~johannes.erdfelt/openstack-guest-agents/arch-fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
41
41
# of the older style colon interfaces for IP aliasing. So we have to use
42
42
# a hack to get IP aliasing working:
43
43
# https://bbs.archlinux.org/viewtopic.php?pid=951573#p951573
 
44
#
 
45
# Arch is a rolling release, meaning new features and updated packages
 
46
# roll out on a unpredictable schedule. It also means there is no such
 
47
# thing as v1.0 or v2.0. We check if the netcfg package is installed to
 
48
# determine which format should be used.
44
49
 
45
50
import os
46
51
import re
56
61
 
57
62
 
58
63
def _execute(command):
 
64
    logging.info('executing %s' % ' '.join(command))
 
65
 
59
66
    pipe = subprocess.PIPE
60
 
    logging.info('executing %s' % ' '.join(command))
61
67
    p = subprocess.Popen(command, stdin=pipe, stdout=pipe, stderr=pipe, env={})
62
 
    logging.debug('waiting on pid %d' % p.pid)
63
 
    status = os.waitpid(p.pid, 0)[1]
64
 
    logging.debug('status = %d' % status)
65
 
 
66
 
    return status
 
68
 
 
69
    # Wait for process to finish and get output
 
70
    stdout, stderr = p.communicate()
 
71
 
 
72
    logging.debug('status = %d' % p.returncode)
 
73
    if p.returncode:
 
74
        logging.info('stdout = %r' % stdout)
 
75
        logging.info('stderr = %r' % stderr)
 
76
 
 
77
    return p.returncode
67
78
 
68
79
 
69
80
def configure_network(hostname, interfaces):
70
 
    # Arch is a rolling release, meaning new features and updated packages
71
 
    # roll out on a unpredictable schedule. It also means there is no such
72
 
    # thing as v1.0 or v2.0. So, let's try checking if the netcfg package
73
 
    # is installed to see what format should be used.
 
81
    update_files = {}
 
82
 
 
83
    # We need to figure out what style of network configuration is
 
84
    # currently being used by looking at /etc/rc.conf and then look
 
85
    # to see what style of network configuration we want to use by
 
86
    # looking to see if the netcfg package is installed
 
87
 
 
88
    if os.path.exists(CONF_FILE):
 
89
        update_files[CONF_FILE] = open(CONF_FILE).read()
 
90
 
 
91
    infile = StringIO(update_files.get(CONF_FILE, ''))
 
92
 
 
93
    cur_netcfg = True   # Currently using netcfg
 
94
    lines, variables = _parse_config(infile)
 
95
    lineno = variables.get('DAEMONS')
 
96
    if lineno is not None:
 
97
        daemons = _parse_variable(lines[lineno])
 
98
        if 'network' in daemons:
 
99
            # Config uses legacy style networking
 
100
            cur_netcfg = False
 
101
 
74
102
    status = _execute(['/usr/bin/pacman', '-Q', 'netcfg'])
75
103
    use_netcfg = (status == 0)
76
104
    logging.info('using %s style configuration' %
77
105
                 (use_netcfg and 'netcfg' or 'legacy'))
78
106
 
79
 
    update_files = {}
80
 
 
81
 
    if os.path.exists(CONF_FILE):
82
 
        update_files[CONF_FILE] = open(CONF_FILE).read()
83
 
 
84
107
    if use_netcfg:
85
108
        remove_files, netnames = process_interface_files_netcfg(
86
109
                update_files, interfaces)
117
140
 
118
141
    # Down network
119
142
    logging.info('configuring interfaces down')
120
 
    if use_netcfg:
 
143
    if cur_netcfg:
121
144
        for netname in netnames:
122
145
            if not interfaces[netname]['up']:
123
146
                # Don't try to down an interface that isn't already up
145
168
        for netname in netnames:
146
169
            status = _execute(['/usr/bin/netcfg', '-u', netname])
147
170
            if status != 0:
148
 
                logging.info('  %s, failed (status %d)' % (netname, status))
149
 
                errors.add(netname)
 
171
                logging.info('  %s, failed (status %d), trying again' %
 
172
                             (netname, status))
 
173
 
 
174
                # HACK: Migrating from legacy to netcfg configurations is
 
175
                # troublesome because of Arch bugs. Stopping the network
 
176
                # in legacy downs the interface, but doesn't remove the IP
 
177
                # addresses. This causes netcfg to complain and fail when
 
178
                # we go to configure the interface up. As a side-effect, it
 
179
                # will remove the offending IP. A second attempt to configure
 
180
                # the interface up succeeds. So we'll try a second time.
 
181
                status = _execute(['/usr/bin/netcfg', '-u', netname])
 
182
                if status != 0:
 
183
                    logging.info('  %s, failed (status %d)' %
 
184
                                 (netname, status))
 
185
                    errors.add(netname)
 
186
                else:
 
187
                    logging.info('  %s, success' % netname)
150
188
            else:
151
189
                logging.info('  %s, success' % netname)
152
190
    else:
198
236
    return [name.lstrip('!') for name in re.split('\s+', v.strip())]
199
237
 
200
238
 
 
239
def _parse_config(infile):
 
240
    lines = []
 
241
    variables = {}
 
242
    for line in infile:
 
243
        line = line.strip()
 
244
        lines.append(line)
 
245
 
 
246
        # FIXME: This doesn't correctly parse shell scripts perfectly. It
 
247
        # assumes a fairly simple subset
 
248
 
 
249
        if '=' not in line:
 
250
            continue
 
251
 
 
252
        k, v = line.split('=', 1)
 
253
        k = k.strip()
 
254
        variables[k] = len(lines) - 1
 
255
 
 
256
    return lines, variables
 
257
 
 
258
 
201
259
def _update_rc_conf_legacy(infile, interfaces):
202
260
    """
203
261
    Return data for (sub-)interfaces and routes
256
314
        routes.append(('gateway6', 'default gw %s' % gateway6))
257
315
 
258
316
    # Then load old file
259
 
    lines = []
260
 
    variables = {}
261
 
    for line in infile:
262
 
        line = line.strip()
263
 
        lines.append(line)
264
 
 
265
 
        # FIXME: This doesn't correctly parse shell scripts perfectly. It
266
 
        # assumes a fairly simple subset
267
 
 
268
 
        if '=' not in line:
269
 
            continue
270
 
 
271
 
        k, v = line.split('=', 1)
272
 
        k = k.strip()
273
 
        variables[k] = len(lines) - 1
 
317
    lines, variables = _parse_config(infile)
274
318
 
275
319
    # Update INTERFACES
276
320
    lineno = variables.get('INTERFACES')
338
382
    # Filter out any removed lines
339
383
    lines = filter(lambda l: l is not None, lines)
340
384
 
341
 
    # Patch into new file
 
385
    # Serialize into new file
342
386
    outfile = StringIO()
343
387
    for line in lines:
344
388
        print >> outfile, line
413
457
 
414
458
 
415
459
def _update_rc_conf_netcfg(infile, netnames):
416
 
    # Then load old file
417
 
    lines = []
418
 
    variables = {}
419
 
    for line in infile:
420
 
        line = line.strip()
421
 
        lines.append(line)
422
 
 
423
 
        # FIXME: This doesn't correctly parse shell scripts perfectly. It
424
 
        # assumes a fairly simple subset
425
 
 
426
 
        if '=' not in line:
427
 
            continue
428
 
 
429
 
        k, v = line.split('=', 1)
430
 
        k = k.strip()
431
 
        variables[k] = len(lines) - 1
 
460
    # Load old file
 
461
    lines, variables = _parse_config(infile)
432
462
 
433
463
    # Update NETWORKS
434
464
    lineno = variables.get('NETWORKS')
472
502
        except ValueError:
473
503
            pass
474
504
 
475
 
    # Patch into new file
 
505
    # Serialize into new file
476
506
    outfile = StringIO()
477
507
    for line in lines:
478
508
        print >> outfile, line