blob: 68b9bc5b1d27fd8cc082de4bd468dfb25204cd3f [file] [log] [blame]
# we regard the grub file as a preamble, plus a sequence of entry stanzas
# starting in 'title'. Whilst probably not entirely accurate, it works
# well enough, and is designed not to be lossy
import shutil
import re
import os
import os.path
import string
class grub:
config_locations = ['/boot/grub/grub.conf', '/boot/grub/menu.lst',
'/etc/grub.conf']
def __init__(self, config_file=None):
if config_file:
self.config = config_file
else:
self.config = self.detect()
self.read()
def read(self):
conf_file = file(self.config, 'r')
self.lines = conf_file.readlines()
conf_file.close()
self.entries = [] # list of stanzas
self.titles = {} # dictionary of titles
entry = grub_entry(-1)
count = 0
for line in self.lines:
if re.match(r'\s*title', line):
self.entries.append(entry)
entry = grub_entry(count)
count = count + 1
title = line.replace('title ', '')
title = title.rstrip('\n')
entry.set('title', title)
self.titles[title] = entry
# if line.startswith('initrd'):
if re.match(r'\s*initrd', line):
entry.set('initrd',
re.sub(r'\s*initrd\s+', '', line))
if re.match(r'\s*kernel', line):
entry.set('kernel',
re.sub(r'\s*kernel\s+', '', line))
entry.lines.append(line)
self.entries.append(entry)
self.preamble = self.entries.pop(0) # separate preamble
def write(self):
conf_file = file(self.config, 'w')
conf_file.write(self.preamble)
for entry in self.entries:
conf_file.write(entry.lines)
conf_file.close()
def dump(self):
for line in self.preamble.lines:
print line,
for entry in self.entries:
for line in entry.lines:
print line,
def backup(self):
shutil.copyfile(self.config, self.config+'.bak')
restore = file(autodir + '/var/autotest.boot.restore', 'w')
restore.write('cp ' + self.config+'.bak ' + self.config + '\n')
restore.close()
def bootloader(self):
return 'grub'
def detect(self):
for config in grub.config_locations:
if os.path.isfile(config) and not os.path.islink(config):
return config
def list_titles(self):
list = []
for entry in self.entries:
list.append(entry.get('title'))
return list
def print_entry(self, index):
entry = self.entries[index]
entry.print_entry()
def renamed_entry(self, index, newname, args=False):
"print a specified entry, renaming it as specified"
entry = self.entries[index]
entry.set('title', newname)
if args:
entry.set_autotest_kernel()
entry.print_entry()
def omit_markers(self, marker):
# print, ommitting entries between specified markers
print_state = True
for line in lines:
if line.count(marker):
print_state = not print_state
else:
if print_state:
print line
def select(self, title, boot_options=None):
entry = self.titles[title]
print "grub: will boot entry %d (0-based)" % entry.index
self.set_default(entry.index)
self.set_timeout()
def set_default(self, index):
lines = (self.preamble).lines
for i in range(len(lines)):
default = 'default %d' % index
lines[i] = re.sub(r'^\s*default.*',
default, lines[i])
def set_timeout(self):
lines = (self.preamble).lines
for i in range(len(lines)):
lines[i] = re.sub(r'^timeout.*/',
'timeout 60', lines[i])
lines[i] = re.sub(r'^(\s*terminal .*--timeout)=\d+',
r'\1=30', lines[i])
# ----------------------------------------------------------------------
# Note that the lines[] section, whilst fairly foul, is needed to make
# sure we preserve the original entry intact with comments, formatting,
# and bits we don't understand.
class grub_entry:
def __init__(self, count):
self.lines = []
self.fields = {} # title, initrd, kernel, etc
self.index = count
def set(self, field, value):
print "setting '%s' to '%s'" % (field, value)
self.fields[field] = value
for i in range(len(self.lines)):
m = re.match(r'\s*' + field + r'\s+', self.lines[i])
if m:
self.lines[i] = m.group() + value + '\n'
def get(self, field):
return self.fields[field]
def print_entry(self):
print self.lines
def set_kernel_options(self, options):
kernel = self.get('kernel')
re.sub(r'(autotest_args:).*', r'\1'+options, kernel)
self.set('kernel', kernel)
def set_autotest_kernel(self):
kernel_words = []
found_path = False
# Want to copy most of the entry, replacing the 'path'
# part of the entry with vmlinux-autotest in the same
# dir, and make sure autotest_args: is (uniquely) added
for word in (self.get('kernel')).split():
if word.startswith('--'):
kernel_words.append(word)
continue
if not found_path:
word = os.path.dirname(word)+'vmlinuz-autotest'
found_path = True
if re.match(r'auto(bench|test)_args:', word):
break
kernel_words.append(word)
kernel_words.append('autotest_args: ')
self.set('kernel', string.join(kernel_words))