1__author__ = """Copyright Martin J. Bligh, 2006,
2                Copyright IBM Corp. 2006, Ryan Harper <ryanh@us.ibm.com>"""
3
4import os, shutil, copy, pickle, re, glob
5from autotest_lib.client.bin import kernel, kernel_config, os_dep, test
6from autotest_lib.client.bin import utils
7
8
9class xen(kernel.kernel):
10
11    def log(self, msg):
12        print msg
13        self.logfile.write('%s\n' % msg)
14
15
16    def __init__(self, job, base_tree, results_dir, tmp_dir, build_dir,
17                                        leave = False, kjob = None):
18        # call base-class
19        kernel.kernel.__init__(self, job, base_tree, results_dir,
20                                        tmp_dir, build_dir, leave)
21        self.kjob = kjob
22
23
24    def config(self, config_file, config_list = None):
25        raise NotImplementedError('config() not implemented for xen')
26
27
28    def build(self, make_opts = '', logfile = '', extraversion='autotest'):
29        """build xen
30
31        make_opts
32                additional options to make, if any
33        """
34        self.log('running build')
35        os_dep.commands('gcc', 'make')
36        # build xen with extraversion flag
37        os.environ['XEN_EXTRAVERSION'] = '-unstable-%s'% extraversion
38        if logfile == '':
39            logfile = os.path.join(self.log_dir, 'xen_build')
40        os.chdir(self.build_dir)
41        self.log('log_dir: %s ' % self.log_dir)
42        self.job.logging.tee_redirect_debug_dir(self.log_dir, log_name=logfile)
43
44        # build xen hypervisor and user-space tools
45        targets = ['xen', 'tools']
46        threads = 2 * utils.count_cpus()
47        for t in targets:
48            build_string = 'make -j %d %s %s' % (threads, make_opts, t)
49            self.log('build_string: %s' % build_string)
50            utils.system(build_string)
51
52        # make a kernel job out of the kernel from the xen src if one isn't provided
53        if self.kjob is None:
54            # get xen kernel tree ready
55            self.log("prep-ing xen'ified kernel source tree")
56            utils.system('make prep-kernels')
57
58            v = self.get_xen_kernel_build_ver()
59            self.log('building xen kernel version: %s' % v)
60
61            # build xen-ified kernel in xen tree
62            kernel_base_tree = os.path.join(self.build_dir, \
63                    'linux-%s' % self.get_xen_kernel_build_ver())
64
65            self.log('kernel_base_tree = %s' % kernel_base_tree)
66            # fix up XENGUEST value in EXTRAVERSION; we can't have
67            # files with '$(XENGEUST)' in the name, =(
68            self.fix_up_xen_kernel_makefile(kernel_base_tree)
69
70            # make the kernel job
71            self.kjob = self.job.kernel(kernel_base_tree)
72
73            # hardcoding dom0 config (no modules for testing, yay!)
74            # FIXME: probe host to determine which config to pick
75            c = self.build_dir + '/buildconfigs/linux-defconfig_xen0_x86_32'
76            self.log('using kernel config: %s ' % c)
77            self.kjob.config(c)
78
79            # Xen's kernel tree sucks; doesn't use bzImage, but vmlinux
80            self.kjob.set_build_target('vmlinuz')
81
82            # also, the vmlinuz is not out in arch/*/boot, ARGH! more hackery
83            self.kjob.set_build_image(self.job.tmpdir + '/build/linux/vmlinuz')
84
85        self.kjob.build()
86
87        self.job.logging.restore()
88
89        xen_version = self.get_xen_build_ver()
90        self.log('BUILD VERSION: Xen: %s Kernel:%s' % \
91                        (xen_version, self.kjob.get_kernel_build_ver()))
92
93
94    def build_timed(self, *args, **kwds):
95        raise NotImplementedError('build_timed() not implemented')
96
97
98    def install(self, tag='', prefix = '/', extraversion='autotest'):
99        """make install in the kernel tree"""
100        self.log('Installing ...')
101
102        os.chdir(self.build_dir)
103
104        if not os.path.isdir(prefix):
105            os.mkdir(prefix)
106        self.boot_dir = os.path.join(prefix, 'boot')
107        if not os.path.isdir(self.boot_dir):
108            os.mkdir(self.boot_dir)
109
110        # remember what we are going to install
111        xen_version = '%s-%s' % (self.get_xen_build_ver(), extraversion)
112        self.xen_image = self.boot_dir + '/xen-' + xen_version + '.gz'
113        self.xen_syms  = self.boot_dir + '/xen-syms-' + xen_version
114
115        self.log('Installing Xen ...')
116        os.environ['XEN_EXTRAVERSION'] = '-unstable-%s'% extraversion
117
118        # install xen
119        utils.system('make DESTDIR=%s -C xen install' % prefix)
120
121        # install tools
122        utils.system('make DESTDIR=%s -C tools install' % prefix)
123
124        # install kernel
125        ktag = self.kjob.get_kernel_build_ver()
126        kprefix = prefix
127        self.kjob.install(tag=ktag, prefix=kprefix)
128
129
130    def add_to_bootloader(self, tag='autotest', args=''):
131        """ add this kernel to bootloader, taking an
132            optional parameter of space separated parameters
133            e.g.:  kernel.add_to_bootloader('mykernel', 'ro acpi=off')
134        """
135
136        # turn on xen mode
137        self.job.bootloader.enable_xen_mode()
138
139        # remove existing entry if present
140        self.job.bootloader.remove_kernel(tag)
141
142        # add xen and xen kernel
143        self.job.bootloader.add_kernel(
144                self.kjob.image, tag, initrd=self.kjob.initrd,
145                xen_hypervisor=self.xen_image)
146
147        # if no args passed, populate from /proc/cmdline
148        if not args:
149            args = open('/proc/cmdline', 'r').readline().strip()
150
151        # add args to entry one at a time
152        for a in args.split(' '):
153            self.job.bootloader.add_args(tag, a)
154
155        # turn off xen mode
156        self.job.bootloader.disable_xen_mode()
157
158
159    def get_xen_kernel_build_ver(self):
160        """Check xen buildconfig for current kernel version"""
161        version = patchlevel = sublevel = ''
162        extraversion = localversion = ''
163
164        version_file = self.build_dir + '/buildconfigs/mk.linux-2.6-xen'
165
166        for line in open(version_file, 'r').readlines():
167            if line.startswith('LINUX_VER'):
168                start = line.index('=') + 1
169                version = line[start:].strip() + "-xen"
170                break
171
172        return version
173
174
175    def fix_up_xen_kernel_makefile(self, kernel_dir):
176        """Fix up broken EXTRAVERSION in xen-ified Linux kernel Makefile"""
177        xenguest = ''
178        makefile = kernel_dir + '/Makefile'
179
180        for line in open(makefile, 'r').readlines():
181            if line.startswith('XENGUEST'):
182                start = line.index('=') + 1
183                xenguest = line[start:].strip()
184                break;
185
186        # change out $XENGUEST in EXTRAVERSION line
187        utils.system('sed -i.old "s,\$(XENGUEST),%s," %s' % (xenguest,
188                                                             makefile))
189
190
191    def get_xen_build_ver(self):
192        """Check Makefile and .config to return kernel version"""
193        version = patchlevel = sublevel = ''
194        extraversion = localversion = ''
195
196        for line in open(self.build_dir + '/xen/Makefile', 'r').readlines():
197            if line.startswith('export XEN_VERSION'):
198                start = line.index('=') + 1
199                version = line[start:].strip()
200            if line.startswith('export XEN_SUBVERSION'):
201                start = line.index('=') + 1
202                sublevel = line[start:].strip()
203            if line.startswith('export XEN_EXTRAVERSION'):
204                start = line.index('=') + 1
205                extraversion = line[start:].strip()
206
207        return "%s.%s%s" % (version, sublevel, extraversion)
208