mbligh | dcd57a8 | 2007-07-11 23:06:47 +0000 | [diff] [blame] | 1 | #!/usr/bin/python |
| 2 | # |
| 3 | # Copyright 2007 Google Inc. Released under the GPL v2 |
| 4 | |
| 5 | """This module defines the Bootloader class. |
| 6 | |
| 7 | Bootloader: a program to boot Kernels on a Host. |
| 8 | """ |
| 9 | |
| 10 | __author__ = """mbligh@google.com (Martin J. Bligh), |
| 11 | poirier@google.com (Benjamin Poirier), |
| 12 | stutsman@google.com (Ryan Stutsman)""" |
| 13 | |
mbligh | 6a64126 | 2007-07-23 23:33:31 +0000 | [diff] [blame^] | 14 | import os.path |
| 15 | import sys |
| 16 | import weakref |
| 17 | |
| 18 | import errors |
| 19 | import utils |
| 20 | |
| 21 | |
| 22 | BOOTTOOL_SRC = '../client/tools/boottool' # Get it from autotest client |
| 23 | |
mbligh | dcd57a8 | 2007-07-11 23:06:47 +0000 | [diff] [blame] | 24 | |
| 25 | class Bootloader(object): |
| 26 | """This class represents a bootloader. |
| 27 | |
| 28 | It can be used to add a kernel to the list of kernels that can be |
| 29 | booted by a bootloader. It can also make sure that this kernel will |
mbligh | 6a64126 | 2007-07-23 23:33:31 +0000 | [diff] [blame^] | 30 | be the one chosen at next reboot.""" |
mbligh | dcd57a8 | 2007-07-11 23:06:47 +0000 | [diff] [blame] | 31 | |
mbligh | 6a64126 | 2007-07-23 23:33:31 +0000 | [diff] [blame^] | 32 | def __init__(self, host, xen_mode=False): |
| 33 | super(Bootloader, self).__init__() |
| 34 | self.__host = weakref.ref(host) |
| 35 | self.__boottool_path = None |
| 36 | self.xen_mode = xen_mode |
mbligh | dcd57a8 | 2007-07-11 23:06:47 +0000 | [diff] [blame] | 37 | |
mbligh | 6a64126 | 2007-07-23 23:33:31 +0000 | [diff] [blame^] | 38 | def get_type(self): |
| 39 | return self.__run_boottool('--bootloader-probe').stdout.strip() |
mbligh | dcd57a8 | 2007-07-11 23:06:47 +0000 | [diff] [blame] | 40 | |
mbligh | 6a64126 | 2007-07-23 23:33:31 +0000 | [diff] [blame^] | 41 | def get_architecture(self): |
| 42 | return self.__run_boottool('--arch-probe').stdout.strip() |
mbligh | dcd57a8 | 2007-07-11 23:06:47 +0000 | [diff] [blame] | 43 | |
mbligh | 6a64126 | 2007-07-23 23:33:31 +0000 | [diff] [blame^] | 44 | def get_titles(self): |
| 45 | return self.__run_boottool('--info all | grep title | ' |
| 46 | 'cut -d " " -f2-').stdout.strip().split('\n') |
| 47 | |
| 48 | def get_default(self): |
| 49 | return self.__run_boottool('--default').stdout.strip() |
| 50 | |
| 51 | def get_info(self, index): |
| 52 | retval= self.__run_boottool( |
| 53 | '--info=%s' % index).stdout.strip().split("\n") |
| 54 | |
| 55 | result= {} |
| 56 | for line in retval: |
| 57 | (key, val,)= line.split(":") |
| 58 | result[key.strip()]= val.strip() |
| 59 | |
| 60 | return result |
| 61 | |
| 62 | def set_default(self, index): |
| 63 | self.__run_boottool('--set-default=%s' % index) |
| 64 | |
| 65 | # 'kernel' can be a position number or a title |
| 66 | def add_args(self, kernel, args): |
| 67 | parameters = '--update-kernel=%s --args="%s"' % (kernel, args) |
| 68 | |
| 69 | #add parameter if this is a Xen entry |
| 70 | if self.xen_mode: |
| 71 | parameters += ' --xen' |
| 72 | |
| 73 | self.__run_boottool(parameters) |
| 74 | |
| 75 | def add_xen_hypervisor_args(self, kernel, args): |
| 76 | self.__run_boottool('--xen --update-xenhyper=%s --xha="%s"' \ |
| 77 | % (kernel, args)) |
| 78 | |
| 79 | def remove_args(self, kernel, args): |
| 80 | params = '--update-kernel=%s --remove-args=%s' % (kernel, args) |
| 81 | |
| 82 | #add parameter if this is a Xen entry |
| 83 | if self.xen_mode: |
| 84 | params += ' --xen' |
| 85 | |
| 86 | self.__run_boottool(params) |
| 87 | |
| 88 | def remove_xen_hypervisor_args(self, kernel, args): |
| 89 | self.__run_boottool('--xen --update-xenhyper=%s ' |
| 90 | '--remove-args="%s"') % (kernel, args) |
| 91 | |
| 92 | def add_kernel(self, path, title='autoserv', root=None, args=None, |
| 93 | initrd=None, xen_hypervisor=None, default=True): |
| 94 | """ |
| 95 | If an entry with the same title is already present, it will be |
| 96 | replaced. |
| 97 | """ |
| 98 | if title in self.get_titles(): |
| 99 | self.__run_boottool('--remove-kernel "%s"' % ( |
| 100 | utils.sh_escape(title),)) |
| 101 | |
| 102 | parameters = '--add-kernel "%s" --title "%s"' % ( |
| 103 | utils.sh_escape(path), utils.sh_escape(title),) |
| 104 | |
| 105 | if root: |
| 106 | parameters += ' --root "%s"' % (utils.sh_escape(root),) |
| 107 | |
| 108 | if args: |
| 109 | parameters += ' --args "%s"' % (utils.sh_escape(args),) |
| 110 | |
| 111 | # add an initrd now or forever hold your peace |
| 112 | if initrd: |
| 113 | parameters += ' --initrd "%s"' % ( |
| 114 | utils.sh_escape(initrd),) |
| 115 | |
| 116 | if default: |
| 117 | parameters += ' --make-default' |
| 118 | |
| 119 | # add parameter if this is a Xen entry |
| 120 | if self.xen_mode: |
| 121 | parameters += ' --xen' |
| 122 | if xen_hypervisor: |
| 123 | parameters += ' --xenhyper "%s"' % ( |
| 124 | utils.sh_escape(xen_hypervisor),) |
| 125 | |
| 126 | self.__run_boottool(parameters) |
| 127 | |
| 128 | def remove_kernel(self, kernel): |
| 129 | self.__run_boottool('--remove-kernel=%s' % kernel) |
| 130 | |
| 131 | def boot_once(self, title): |
| 132 | self.__run_boottool('--boot-once --title=%s' % title) |
| 133 | |
| 134 | def __install_boottool(self): |
| 135 | if self.__host() is None: |
| 136 | raise errors.AutoservError("Host does not exist anymore") |
| 137 | tmpdir = self.__host().get_tmp_dir() |
| 138 | self.__host().send_file(os.path.abspath(os.path.join( |
| 139 | os.path.dirname(sys.argv[0]), BOOTTOOL_SRC)), tmpdir) |
| 140 | self.__boottool_path= os.path.join(tmpdir, |
| 141 | os.path.basename(BOOTTOOL_SRC)) |
| 142 | |
| 143 | def __get_boottool_path(self): |
| 144 | if not self.__boottool_path: |
| 145 | self.__install_boottool() |
| 146 | return self.__boottool_path |
| 147 | |
| 148 | def __set_boottool_path(self, path): |
| 149 | self.__boottool_path = path |
| 150 | |
| 151 | boottool_path = property(__get_boottool_path, __set_boottool_path) |
| 152 | |
| 153 | def __run_boottool(self, cmd): |
| 154 | return self.__host().run(self.boottool_path + ' ' + cmd) |