Created
March 27, 2011 09:45
-
-
Save simon-engledew/889091 to your computer and use it in GitHub Desktop.
snack based ncurses script for configuring ubuntu networking, first pass
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import with_statement | |
import snack, ipaddr, optparse, re, shlex | |
parser = optparse.OptionParser() | |
parser.add_option('--no-cancel', action='store_true', dest='no_cancel', help='Do not display a cancel button') | |
parser.add_option('--title', action='store', dest='title', default='Configure Networking', help='set the form title') | |
parser.add_option('--interface', action='store', dest='interface', default='eth0', help='interface to edit') | |
parser.add_option('--interfaces-file', action='store', dest='interfaces_file', default='/etc/network/interfaces', help='target interfaces file to edit') | |
parser.add_option('--dns-file', action='store', dest='dns_file', default='/etc/resolvconf/resolv.conf.d/base', help='target dns file to edit') | |
options, args = parser.parse_args() | |
def bind(object, **kwargs): | |
for key, value in kwargs.items(): | |
setattr(object, key, value) | |
return object | |
VALUES = dict() | |
ERRORS = dict() | |
OUTPUT = dict() | |
screen = snack.SnackScreen() | |
def LabelledEntry(name, label): | |
return ( | |
bind(snack.Label(label), name=name, label=label, form=dict(padding=(2, 0, 1, 0), anchorRight=1)), | |
bind(snack.Entry(width=20), name=name, form=dict(padding=(0, 0, 1, 0))) | |
) | |
def to_ip_address(s): | |
try: | |
return ipaddr.IPAddress(s) | |
except ValueError: | |
return None | |
def to_ip_network(address, netmask): | |
try: | |
return ipaddr.IPNetwork('%s/%s' % (address, netmask)) | |
except ValueError: | |
return None | |
try: | |
screen.pushHelpLine(' <Tab>/<Alt-Tab> between elements | * Optional Address') | |
while True: | |
fields = [ | |
LabelledEntry('address', 'IP Address '), | |
LabelledEntry('netmask', 'Netmask '), | |
LabelledEntry('gateway', 'Gateway '), | |
LabelledEntry('dns[0]', 'Primary DNS '), | |
LabelledEntry('dns[1]', '* Secondary DNS '), | |
] | |
form = snack.GridForm(screen, options.title, 1, 2) | |
grid = snack.Grid(max(len(row) for row in fields), len(fields)) | |
if not options.no_cancel: | |
button_grid = snack.Grid(2, 1) | |
button_grid.setField(bind(snack.Button('OK'), name='ok'), 0, 0, padding=(0, 2, 2, 0)) | |
button_grid.setField(bind(snack.Button('Canel'), name='cancel'), 1, 0, padding=(2, 2, 0, 0)) | |
else: | |
button_grid = snack.Grid(1, 1) | |
button_grid.setField(bind(snack.Button('OK'), name='ok'), 0, 0, padding=(0, 2, 0, 0)) | |
if len(ERRORS) > 0: | |
screen.pushHelpLine(' <Tab>/<Alt-Tab> between elements | * Optional Address | ! Invalid Address') | |
for y, row in enumerate(fields): | |
for x, field in enumerate(row): | |
if isinstance(field, snack.Entry): | |
field.set(VALUES.get(field.name, '')) | |
elif isinstance(field, snack.Label) and hasattr(field, 'name') and field.name in ERRORS: | |
field.setText('! ' + field.label) | |
grid.setField(field, x, y, **field.__dict__.get('form', {})) | |
form.add(grid, 0, 0) | |
form.add(button_grid, 0, 1) | |
result = form.runOnce() | |
for row in fields: | |
for field in row: | |
if isinstance(field, snack.Entry): | |
VALUES[field.name] = field.value() | |
if len(ERRORS) > 0: | |
screen.popHelpLine() | |
ERRORS = dict() | |
address = to_ip_address(VALUES['address']) | |
if not address: ERRORS['address'] = True | |
else: | |
OUTPUT['address'] = address | |
network = to_ip_network(address, VALUES['netmask']) | |
if not network: ERRORS['netmask'] = True | |
else: OUTPUT['netmask'] = network.netmask | |
for key in ['gateway', 'dns[0]']: | |
address = to_ip_address(VALUES[key]) | |
if not address: ERRORS[key] = True | |
else: OUTPUT[key] = address | |
for key in ['dns[1]']: | |
if len(VALUES[key]) > 0: | |
address = to_ip_address(VALUES[key]) | |
if not address: ERRORS[key] = True | |
else: OUTPUT[key] = address | |
if result.name == 'cancel': break | |
if len(ERRORS) == 0: | |
with open(options.interfaces_file, 'r') as f: | |
tokens = ' '.join(shlex.split(f.read(), comments=True)) | |
tokens = re.compile(' (?=auto|iface)').split(tokens) | |
# filter out the interface we are working on | |
tokens = [interface for interface in tokens if not re.search('^(?:auto|iface) %(interface)s' % options.__dict__, interface)] | |
with open(options.interfaces_file, 'w+') as f: | |
result = [] | |
result.append('iface %(interface)s inet static' % options.__dict__) | |
result.append('address %(address)s netmask %(netmask)s gateway %(gateway)s' % OUTPUT) | |
result.append('dns-nameservers %(dns[0])s' % OUTPUT) | |
if 'dns[1]' in OUTPUT: | |
result.append(' %(dns[1])s' % OUTPUT) | |
tokens.append(' '.join(result)) | |
print >> f, '\n'.join(tokens) | |
break | |
finally: | |
screen.finish() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment