1# Copyright 2007 Google Inc. Released under the GPL v2
2
3"""
4This module defines the Kernel class
5
6        Kernel: an os kernel
7"""
8
9import os, os.path, time
10from autotest_lib.client.common_lib import error
11from autotest_lib.server import kernel, utils
12
13
14class DEBKernel(kernel.Kernel):
15    """
16    This class represents a .deb pre-built kernel.
17
18    It is used to obtain a built kernel and install it on a Host.
19
20    Implementation details:
21    This is a leaf class in an abstract class hierarchy, it must
22    implement the unimplemented methods in parent classes.
23    """
24    def __init__(self):
25        super(DEBKernel, self).__init__()
26
27
28    def install(self, host, **kwargs):
29        """
30        Install a kernel on the remote host.
31
32        This will also invoke the guest's bootloader to set this
33        kernel as the default kernel.
34
35        Args:
36                host: the host on which to install the kernel
37                [kwargs]: remaining keyword arguments will be passed
38                        to Bootloader.add_kernel()
39
40        Raises:
41                AutoservError: no package has yet been obtained. Call
42                        DEBKernel.get() with a .deb package.
43        """
44        if self.source_material is None:
45            raise error.AutoservError("A kernel must first be "
46                                      "specified via get()")
47
48        remote_tmpdir = host.get_tmp_dir()
49        basename = os.path.basename(self.source_material)
50        remote_filename = os.path.join(remote_tmpdir, basename)
51        host.send_file(self.source_material, remote_filename)
52        host.run('dpkg -i "%s"' % (utils.sh_escape(remote_filename),))
53        host.run('mkinitramfs -o "%s" "%s"' % (
54                utils.sh_escape(self.get_initrd_name()),
55                utils.sh_escape(self.get_version()),))
56
57        host.bootloader.add_kernel(self.get_image_name(),
58                initrd=self.get_initrd_name(), **kwargs)
59
60
61    def get_version(self):
62        """Get the version of the kernel to be installed.
63
64        Returns:
65                The version string, as would be returned
66                by 'make kernelrelease'.
67
68        Raises:
69                AutoservError: no package has yet been obtained. Call
70                        DEBKernel.get() with a .deb package.
71        """
72        if self.source_material is None:
73            raise error.AutoservError("A kernel must first be "
74                                      "specified via get()")
75
76        retval= utils.run('dpkg-deb -f "%s" version' %
77                utils.sh_escape(self.source_material),)
78        return retval.stdout.strip()
79
80
81    def get_image_name(self):
82        """Get the name of the kernel image to be installed.
83
84        Returns:
85                The full path to the kernel image file as it will be
86                installed on the host.
87
88        Raises:
89                AutoservError: no package has yet been obtained. Call
90                        DEBKernel.get() with a .deb package.
91        """
92        return "/boot/vmlinuz-%s" % (self.get_version(),)
93
94
95    def get_initrd_name(self):
96        """Get the name of the initrd file to be installed.
97
98        Returns:
99                The full path to the initrd file as it will be
100                installed on the host. If the package includes no
101                initrd file, None is returned
102
103        Raises:
104                AutoservError: no package has yet been obtained. Call
105                        DEBKernel.get() with a .deb package.
106        """
107        if self.source_material is None:
108            raise error.AutoservError("A kernel must first be "
109                                      "specified via get()")
110
111        return "/boot/initrd.img-%s" % (self.get_version(),)
112
113    def extract(self, host):
114        """Extract the kernel package.
115
116        This function is only useful to access the content of the
117        package (for example the kernel image) without
118        installing it. It is not necessary to run this function to
119        install the kernel.
120
121        Args:
122                host: the host on which to extract the kernel package.
123
124        Returns:
125                The full path to the temporary directory on host where
126                the package was extracted.
127
128        Raises:
129                AutoservError: no package has yet been obtained. Call
130                        DEBKernel.get() with a .deb package.
131        """
132        if self.source_material is None:
133            raise error.AutoservError("A kernel must first be "
134                                      "specified via get()")
135
136        remote_tmpdir = host.get_tmp_dir()
137        basename = os.path.basename(self.source_material)
138        remote_filename = os.path.join(remote_tmpdir, basename)
139        host.send_file(self.source_material, remote_filename)
140        content_dir= os.path.join(remote_tmpdir, "contents")
141        host.run('dpkg -x "%s" "%s"' % (utils.sh_escape(remote_filename),
142                                        utils.sh_escape(content_dir),))
143
144        return content_dir
145