This patch adds bootloader functionality to autoserv:
From: Benjamin Poirier <poirier@google.com>
Signed-off-by: Martin J. Bligh <mbligh@google.com>
* removed Lilo and Grub classes
* Bootloader uses boottool, boottool support brought in from autotest, get_title(), get_info() improved, add_kernel() has 'default' parameter to add an entry and make it the default one in one simple step
* Kernel has new methods to ease installation, get_version(), get_initrd_name() and get_image_name()
* DEBKernel changed to implement those method and call the host's bootloader during install()
Installing and booting .deb kernel now works.
Example usage:
rh= hosts.SSHHost("192.168.0.1")
print rh.run("uname -a").stdout
kernel= deb_kernel.DEBKernel()
kernel.get("/home/poirier/linux-2.6.22_2.6.22_amd64.deb")
kernel.install(rh)
rh.reboot()
rh.wait_up()
print rh.run("uname -a").stdout
Credit goes to Ryan for bringing in boottool support.
git-svn-id: http://test.kernel.org/svn/autotest/trunk@574 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/server/hosts/bootloader.py b/server/hosts/bootloader.py
index eeaa5fb..a7f717e 100644
--- a/server/hosts/bootloader.py
+++ b/server/hosts/bootloader.py
@@ -11,23 +11,144 @@
poirier@google.com (Benjamin Poirier),
stutsman@google.com (Ryan Stutsman)"""
+import os.path
+import sys
+import weakref
+
+import errors
+import utils
+
+
+BOOTTOOL_SRC = '../client/tools/boottool' # Get it from autotest client
+
class Bootloader(object):
"""This class represents a bootloader.
It can be used to add a kernel to the list of kernels that can be
booted by a bootloader. It can also make sure that this kernel will
- be the one chosen at next reboot.
+ be the one chosen at next reboot."""
- Implementation details:
- This is an abstract class, leaf subclasses must implement the methods
- listed here. You must not instantiate this class but should
- instantiate one of those leaf subclasses."""
+ def __init__(self, host, xen_mode=False):
+ super(Bootloader, self).__init__()
+ self.__host = weakref.ref(host)
+ self.__boottool_path = None
+ self.xen_mode = xen_mode
- host = None
+ def get_type(self):
+ return self.__run_boottool('--bootloader-probe').stdout.strip()
- def add_entry(self, name, image, initrd, root, options, default=True):
- pass
+ def get_architecture(self):
+ return self.__run_boottool('--arch-probe').stdout.strip()
- def remove_entry(self, name):
- pass
+ def get_titles(self):
+ return self.__run_boottool('--info all | grep title | '
+ 'cut -d " " -f2-').stdout.strip().split('\n')
+
+ def get_default(self):
+ return self.__run_boottool('--default').stdout.strip()
+
+ def get_info(self, index):
+ retval= self.__run_boottool(
+ '--info=%s' % index).stdout.strip().split("\n")
+
+ result= {}
+ for line in retval:
+ (key, val,)= line.split(":")
+ result[key.strip()]= val.strip()
+
+ return result
+
+ def set_default(self, index):
+ self.__run_boottool('--set-default=%s' % index)
+
+ # 'kernel' can be a position number or a title
+ def add_args(self, kernel, args):
+ parameters = '--update-kernel=%s --args="%s"' % (kernel, args)
+
+ #add parameter if this is a Xen entry
+ if self.xen_mode:
+ parameters += ' --xen'
+
+ self.__run_boottool(parameters)
+
+ def add_xen_hypervisor_args(self, kernel, args):
+ self.__run_boottool('--xen --update-xenhyper=%s --xha="%s"' \
+ % (kernel, args))
+
+ def remove_args(self, kernel, args):
+ params = '--update-kernel=%s --remove-args=%s' % (kernel, args)
+
+ #add parameter if this is a Xen entry
+ if self.xen_mode:
+ params += ' --xen'
+
+ self.__run_boottool(params)
+
+ def remove_xen_hypervisor_args(self, kernel, args):
+ self.__run_boottool('--xen --update-xenhyper=%s '
+ '--remove-args="%s"') % (kernel, args)
+
+ def add_kernel(self, path, title='autoserv', root=None, args=None,
+ initrd=None, xen_hypervisor=None, default=True):
+ """
+ If an entry with the same title is already present, it will be
+ replaced.
+ """
+ if title in self.get_titles():
+ self.__run_boottool('--remove-kernel "%s"' % (
+ utils.sh_escape(title),))
+
+ parameters = '--add-kernel "%s" --title "%s"' % (
+ utils.sh_escape(path), utils.sh_escape(title),)
+
+ if root:
+ parameters += ' --root "%s"' % (utils.sh_escape(root),)
+
+ if args:
+ parameters += ' --args "%s"' % (utils.sh_escape(args),)
+
+ # add an initrd now or forever hold your peace
+ if initrd:
+ parameters += ' --initrd "%s"' % (
+ utils.sh_escape(initrd),)
+
+ if default:
+ parameters += ' --make-default'
+
+ # add parameter if this is a Xen entry
+ if self.xen_mode:
+ parameters += ' --xen'
+ if xen_hypervisor:
+ parameters += ' --xenhyper "%s"' % (
+ utils.sh_escape(xen_hypervisor),)
+
+ self.__run_boottool(parameters)
+
+ def remove_kernel(self, kernel):
+ self.__run_boottool('--remove-kernel=%s' % kernel)
+
+ def boot_once(self, title):
+ self.__run_boottool('--boot-once --title=%s' % title)
+
+ def __install_boottool(self):
+ if self.__host() is None:
+ raise errors.AutoservError("Host does not exist anymore")
+ tmpdir = self.__host().get_tmp_dir()
+ self.__host().send_file(os.path.abspath(os.path.join(
+ os.path.dirname(sys.argv[0]), BOOTTOOL_SRC)), tmpdir)
+ self.__boottool_path= os.path.join(tmpdir,
+ os.path.basename(BOOTTOOL_SRC))
+
+ def __get_boottool_path(self):
+ if not self.__boottool_path:
+ self.__install_boottool()
+ return self.__boottool_path
+
+ def __set_boottool_path(self, path):
+ self.__boottool_path = path
+
+ boottool_path = property(__get_boottool_path, __set_boottool_path)
+
+ def __run_boottool(self, cmd):
+ return self.__host().run(self.boottool_path + ' ' + cmd)