diff -u jockey-0.9.7/jockey/oslib.py jockey-0.9.7/jockey/oslib.py --- jockey-0.9.7/jockey/oslib.py +++ jockey-0.9.7/jockey/oslib.py @@ -24,6 +24,8 @@ warnings.simplefilter('ignore', FutureWarning) import apt +from jockey.kerneldetection import KernelDetection + class _CapturedInstallProgress(apt.InstallProgress): def __init__(self): apt.InstallProgress.__init__(self) @@ -123,15 +125,10 @@ #self.gpg_key_server = 'keys.gnupg.net' self.gpg_key_server = 'hkp://keyserver.ubuntu.com:80' - # Package which provides include files for the currently running - # kernel. If the system ensures that kernel headers are always - # available, or being pulled in via dependencies (and there are not - # multiple kernel flavors), it is ok to set this to "None". This should - # use self.target_kernel instead of os.uname()[2]. - # Note that we want to install the metapackage here, to ensure upgrades - # will keep working. - flavour = '-'.join(self.target_kernel.split('-')[2:]) - self.kernel_header_package = 'linux-headers-' + flavour + # We want to install the linux flavour metapackage here, to ensure + # upgrades will keep working. + kernel_detection = KernelDetection() + self.kernel_header_package = kernel_detection.get_linux_metapackage() self.apt_show_cache = {} self.apt_sources = '/etc/apt/sources.list' diff -u jockey-0.9.7/debian/changelog jockey-0.9.7/debian/changelog --- jockey-0.9.7/debian/changelog +++ jockey-0.9.7/debian/changelog @@ -1,3 +1,28 @@ +jockey (0.9.7-0ubuntu7.9) precise-proposed; urgency=low + + * jockey/kerneldetection.py: + - Catch KeyError in get_linux_metapackage() (LP: #1123107). + Sometimes the "Source" key is not available. + * tests/kerneldetection.py: + - Add two tests to make sure that get_linux_metapackage() + doesn't raise a KeyError when dealing with packages + without a "Source" field and that the function doesn't + stop if one or two packages don't have the said field. + + -- Alberto Milone Tue, 16 Apr 2013 11:19:02 +0200 + +jockey (0.9.7-0ubuntu7.8) precise-proposed; urgency=low + + * Add jockey/kerneldetection.py, tests/kerneldetection.py, + tests/fakesysfs.py and tests/testarchive.py: + - This is a backport of code originally written for the + ubuntu-drivers-common package. + * jockey/oslib.py: + - Use kerneldetection.KernelDetection() to get the + linux metapackage (LP: #1123107). + + -- Alberto Milone Tue, 12 Feb 2013 16:51:27 +0100 + jockey (0.9.7-0ubuntu7.7) precise-proposed; urgency=low * data/handlers/fglrx.py: only in patch2: unchanged: --- jockey-0.9.7.orig/tests/fakesysfs.py +++ jockey-0.9.7/tests/fakesysfs.py @@ -0,0 +1,91 @@ +'''Provide a fake sysfs directory for testing.''' + +# (C) 2011, 2012 Martin Pitt +# Adapted from upower's integration test suite (src/linux/integration-test) +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +import tempfile +import shutil +import os + +class SysFS: + def __init__(self): + '''Construct a fake sysfs tree. + + The tree is initially empty. You can populate it with @add and + manipulate it with the other methods on this object. + + It is kept in a temporary directory which gets removed when the SysFS + object gets deleted. + + To use this with e. g. libudev, export the SYSFS_PATH environment + variable to self.sysfs. + ''' + self.sysfs = tempfile.mkdtemp() + + def __del__(self): + shutil.rmtree(self.sysfs) + + def add(self, subsystem, name, attributes, properties=None): + '''Add a new device to the local sysfs tree. + + attributes and (optionally) properties are specified as a normal Python + dictionary. + + Return the device path. + ''' + dev_dir = os.path.join(self.sysfs, 'devices', name) + if not os.path.isdir(dev_dir): + os.makedirs(dev_dir) + class_dir = os.path.join(self.sysfs, 'class', subsystem) + if not os.path.isdir(class_dir): + os.makedirs(class_dir) + + os.symlink(os.path.join('..', '..', 'devices', name), os.path.join(class_dir, name)) + os.symlink(os.path.join('..', '..', 'class', subsystem), os.path.join(dev_dir, 'subsystem')) + + attributes['uevent'] = self._props_to_str(properties) + + for a, v in attributes.items(): + self.set_attribute(dev_dir, a, v) + + return dev_dir + + def get_attribute(self, devpath, name): + '''Get device attribute''' + + with open(os.path.join(devpath, name), 'r') as f: + return f.read() + + def set_attribute(self, devpath, name, value): + '''Set device attribute''' + + with open(os.path.join(devpath, name), 'w') as f: + f.write(value) + + def set_property(self, devpath, name, value): + '''Set device udev property''' + + prop_str = self.get_attribute(devpath, 'uevent') + props = {} + for l in prop_str.splitlines(): + (k, v) = l.split('=') + props[k] = v.rstrip() + + props[name] = value + + self.set_attribute(devpath, 'uevent', self._props_to_str(props)) + + @classmethod + def _props_to_str(cls, properties): + '''Convert a properties dictionary to uevent text representation.''' + + prop_str = '' + if properties: + for k, v in properties.items(): + prop_str += '%s=%s\n' % (k, v) + return prop_str only in patch2: unchanged: --- jockey-0.9.7.orig/tests/testarchive.py +++ jockey-0.9.7/tests/testarchive.py @@ -0,0 +1,119 @@ +'''Provide a fake package archive for testing.''' + +# (C) 2012 Martin Pitt +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +import tempfile +import shutil +import os +import subprocess +import atexit + +class Archive: + def __init__(self): + '''Construct a local package test archive. + + The archive is initially empty. You can create new packages with + create_deb(). self.path contains the path of the archive, and + self.apt_source provides an apt source "deb" line. + + It is kept in a temporary directory which gets removed when the Archive + object gets deleted. + ''' + self.path = tempfile.mkdtemp() + atexit.register(shutil.rmtree, self.path) + self.apt_source = 'deb file://%s /' % self.path + + def create_deb(self, name, version='1', architecture='all', + dependencies={}, description='test package', extra_tags={}, + files={}, update_index=True): + '''Build a deb package and add it to the archive. + + The only mandatory argument is the package name. You can additionall + specify the package version (default '1'), architecture (default + 'all'), a dictionary with dependencies (empty by default; for example + {'Depends': 'foo, bar', 'Conflicts: baz'}, a short description + (default: 'test package'), and arbitrary extra tags. + + By default the package is empty. It can get files by specifying a path -> + contents dictionary in 'files'. Paths must be relative. Example: + files={'etc/foo.conf': 'enable=true'} + + The newly created deb automatically gets added to the "Packages" index, + unless update_index is False. + + Return the path to the newly created deb package, in case you only need + the deb itself, not the archive. + ''' + d = tempfile.mkdtemp() + os.mkdir(os.path.join(d, 'DEBIAN')) + with open(os.path.join(d, 'DEBIAN', 'control'), 'w') as f: + f.write('''Package: %s +Maintainer: Test User +Version: %s +Priority: optional +Section: devel +Architecture: %s +''' % (name, version, architecture)) + + for k, v in dependencies.items(): + f.write('%s: %s\n' % (k, v)) + + f.write('''Description: %s + Test dummy package. +''' % description) + + for k, v in extra_tags.items(): + f.write('%s: %s\n' % (k, v)) + + for path, contents in files.items(): + if type(contents) == bytes: + mode = 'wb' + else: + mode = 'w' + pathdir = os.path.join(d, os.path.dirname(path)) + if not os.path.isdir(pathdir): + os.makedirs(pathdir) + with open(os.path.join(d, path), mode) as f: + f.write(contents) + + debpath = os.path.join(self.path, '%s_%s_%s.deb' % (name, version, architecture)) + dpkg = subprocess.Popen(['dpkg', '-b', d, debpath], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + dpkg.communicate() + assert dpkg.returncode == 0 + + shutil.rmtree(d) + assert os.path.exists(debpath) + + if update_index: + self.update_index() + + return debpath + + def update_index(self): + '''Update the "Packages" index. + + This usually gets done automatically by create_deb(), but needs to be + done if you manually copy debs into the archive or call create_deb with + update_index==False. + ''' + old_cwd = os.getcwd() + try: + os.chdir(self.path) + with open('Packages', 'w') as f: + subprocess.check_call(['apt-ftparchive', 'packages', '.'], stdout=f) + finally: + os.chdir(old_cwd) + +#a = Archive() +#a.create_deb('vanilla') +#a.create_deb('chocolate', dependencies={'Depends': 'foo'}, +# extra_tags={'Modaliases': 'pci-1'}, +# files={'usr/share/doc/chocolate/README': 'hello'}) +#print(a.apt_source) +#subprocess.call(['bash', '-i'], cwd=a.path) only in patch2: unchanged: --- jockey-0.9.7.orig/tests/kerneldetection.py +++ jockey-0.9.7/tests/kerneldetection.py @@ -0,0 +1,877 @@ +# +# kerneldetection.py +# +# Copyright 2013 Canonical Ltd. +# +# Author: Alberto Milone +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +import os +import shutil +import tempfile +import unittest +import apt +import aptdaemon.test +import aptdaemon.pkcompat + +import jockey.kerneldetection + +import fakesysfs +import testarchive + + +def gen_fakesys(): + '''Generate a fake SysFS object for testing''' + + s = fakesysfs.SysFS() + # covered by vanilla.deb + s.add('pci', 'white', {'modalias': 'pci:v00001234d00sv00000001sd00bc00sc00i00'}) + # covered by chocolate.deb + s.add('usb', 'black', {'modalias': 'usb:v9876dABCDsv01sd02bc00sc01i05'}) + # covered by nvidia-{current,old}.deb + s.add('pci', 'graphics', {'modalias': 'pci:nvidia', + 'vendor': '0x10DE', + 'device': '0x10C3', + }) + # not covered by any driver package + s.add('pci', 'grey', {'modalias': 'pci:vDEADBEEFd00'}) + s.add('ssb', 'yellow', {}, {'MODALIAS': 'pci:vDEADBEEFd00'}) + + return s + + +def gen_fakearchive(): + '''Generate a fake archive for testing''' + + a = testarchive.Archive() + a.create_deb('vanilla', extra_tags={'Modaliases': + 'vanilla(pci:v00001234d*sv*sd*bc*sc*i*, pci:v0000BEEFd*sv*sd*bc*sc*i*)'}) + a.create_deb('chocolate', dependencies={'Depends': 'xserver-xorg-core'}, + extra_tags={'Modaliases': + 'chocolate(usb:v9876dABCDsv*sd*bc00sc*i*, pci:v0000BEEFd*sv*sd*bc*sc*i00)'}) + + # packages for testing X.org driver ABI installability + a.create_deb('xserver-xorg-core', version='99:1', # higher than system installed one + dependencies={'Provides': 'xorg-video-abi-4'}) + a.create_deb('nvidia-current', dependencies={'Depends': 'xorg-video-abi-4'}, + extra_tags={'Modaliases': 'nv(pci:nvidia, pci:v000010DEd000010C3sv00sd01bc03sc00i00)'}) + a.create_deb('nvidia-old', dependencies={'Depends': 'xorg-video-abi-3'}, + extra_tags={'Modaliases': 'nv(pci:nvidia, pci:v000010DEd000010C3sv00sd01bc03sc00i00)'}) + + # packages not covered by modalises, for testing detection plugins + a.create_deb('special') + a.create_deb('picky') + a.create_deb('special-uninst', dependencies={'Depends': 'xorg-video-abi-3'}) + + return a + + +class KernelDectionTest(unittest.TestCase): + '''Test jockey.kerneldetection''' + + def setUp(self): + '''Create a fake sysfs''' + + self.sys = gen_fakesys() + os.environ['SYSFS_PATH'] = self.sys.sysfs + + # no custom detection plugins by default + self.plugin_dir = tempfile.mkdtemp() + os.environ['UBUNTU_DRIVERS_DETECT_DIR'] = self.plugin_dir + + def tearDown(self): + try: + del os.environ['SYSFS_PATH'] + except KeyError: + pass + shutil.rmtree(self.plugin_dir) + + def test_linux_headers_detection_chroot(self): + '''get_linux_headers_metapackage() for test package repository''' + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-3.2.0-23-generic', + extra_tags={'Source': 'linux'}) + archive.create_deb('linux-image-3.2.0-33-generic', + extra_tags={'Source': 'linux'}) + archive.create_deb('linux-image-3.5.0-18-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-3.5.0-19-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-generic', + extra_tags={'Source': + 'linux-meta'}) + archive.create_deb('linux-image-generic-lts-quantal', + extra_tags={'Source': + 'linux-meta-lts-quantal'}) + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, '') + + # Install kernel packages + for pkg in ('linux-image-3.2.0-23-generic', + 'linux-image-3.2.0-33-generic', + 'linux-image-3.5.0-18-generic', + 'linux-image-3.5.0-19-generic', + 'linux-image-generic', + 'linux-image-generic-lts-quantal'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, 'linux-headers-generic-lts-quantal') + finally: + chroot.remove() + + def test_linux_headers_detection_names_chroot1(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-nexus7', + extra_tags={'Source': 'linux-meta-nexus7'}) + archive.create_deb('linux-image-3.1.10-9-nexus7', + extra_tags={'Source': 'linux-nexus7'}) + archive.create_deb('linux-image-omap4', + extra_tags={'Source': + 'linux-meta-ti-omap4'}) + archive.create_deb('linux-image-3.2.0-1419-omap4', + extra_tags={'Source': + 'linux-ti-omap4'}) + archive.create_deb('linux-image-3.5.0-17-highbank', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-highbank', + extra_tags={'Source': + 'linux-meta-highbank'}) + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-meta-powerpc-smp'}) + archive.create_deb('linux-image-3.5.0-18-powerpc-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-powerpc64-smp', + extra_tags={'Source': + 'linux-meta-powerpc64-smp'}) + archive.create_deb('linux-image-3.5.0-17-powerpc64-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-ac100', + extra_tags={'Source': + 'linux-meta-ac100'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, '') + + # Install kernel packages + for pkg in ('linux-image-nexus7', + 'linux-image-3.1.10-9-nexus7', + 'linux-image-omap4', + 'linux-image-3.2.0-1419-omap4', + 'linux-image-highbank', + 'linux-image-3.5.0-17-highbank', + 'linux-image-powerpc-smp', + 'linux-image-3.5.0-18-powerpc-smp', + 'linux-image-powerpc64-smp', + 'linux-image-3.5.0-17-powerpc64-smp', + 'linux-image-ac100', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, 'linux-headers-powerpc-smp') + finally: + chroot.remove() + + def test_linux_headers_detection_names_chroot2(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-nexus7', + extra_tags={'Source': 'linux-meta-nexus7'}) + archive.create_deb('linux-image-3.1.10-9-nexus7', + extra_tags={'Source': 'linux-nexus7'}) + archive.create_deb('linux-image-omap4', + extra_tags={'Source': + 'linux-meta-ti-omap4'}) + archive.create_deb('linux-image-3.2.0-1419-omap4', + extra_tags={'Source': + 'linux-ti-omap4'}) + archive.create_deb('linux-image-3.5.0-17-highbank', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-highbank', + extra_tags={'Source': + 'linux-meta-highbank'}) + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-meta-powerpc-smp'}) + archive.create_deb('linux-image-3.5.0-18-powerpc-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-powerpc64-smp', + extra_tags={'Source': + 'linux-meta-powerpc64-smp'}) + archive.create_deb('linux-image-3.5.0-19-powerpc64-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-ac100', + extra_tags={'Source': + 'linux-meta-ac100'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, '') + + # Install kernel packages + for pkg in ('linux-image-nexus7', + 'linux-image-3.1.10-9-nexus7', + 'linux-image-omap4', + 'linux-image-3.2.0-1419-omap4', + 'linux-image-highbank', + 'linux-image-3.5.0-17-highbank', + 'linux-image-powerpc-smp', + 'linux-image-3.5.0-18-powerpc-smp', + 'linux-image-powerpc64-smp', + 'linux-image-3.5.0-19-powerpc64-smp', + 'linux-image-ac100', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, 'linux-headers-powerpc64-smp') + finally: + chroot.remove() + + def test_linux_headers_detection_names_chroot3(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-nexus7', + extra_tags={'Source': 'linux-meta-nexus7'}) + archive.create_deb('linux-image-3.1.10-9-nexus7', + extra_tags={'Source': 'linux-nexus7'}) + archive.create_deb('linux-image-omap4', + extra_tags={'Source': + 'linux-meta-ti-omap4'}) + archive.create_deb('linux-image-3.8.0-1419-omap4', + extra_tags={'Source': + 'linux-ti-omap4'}) + archive.create_deb('linux-image-3.5.0-17-highbank', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-highbank', + extra_tags={'Source': + 'linux-meta-highbank'}) + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-meta-powerpc-smp'}) + archive.create_deb('linux-image-3.5.0-18-powerpc-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-powerpc64-smp', + extra_tags={'Source': + 'linux-meta-powerpc64-smp'}) + archive.create_deb('linux-image-3.5.0-19-powerpc64-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-ac100', + extra_tags={'Source': + 'linux-meta-ac100'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, '') + + # Install kernel packages + for pkg in ('linux-image-nexus7', + 'linux-image-3.1.10-9-nexus7', + 'linux-image-omap4', + 'linux-image-3.8.0-1419-omap4', + 'linux-image-highbank', + 'linux-image-3.5.0-17-highbank', + 'linux-image-powerpc-smp', + 'linux-image-3.5.0-18-powerpc-smp', + 'linux-image-powerpc64-smp', + 'linux-image-3.5.0-19-powerpc64-smp', + 'linux-image-ac100', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, 'linux-headers-omap4') + finally: + chroot.remove() + + def test_linux_headers_detection_names_chroot4(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.8.0-3-powerpc-e500', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.8.0-1-powerpc-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.5.0-19-powerpc64-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.8.0-2-powerpc64-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, '') + + # Install kernel packages + for pkg in ('linux-image-powerpc-smp', + 'linux-image-3.8.0-3-powerpc-e500', + 'linux-image-3.8.0-1-powerpc-smp', + 'linux-image-3.5.0-19-powerpc64-smp', + 'linux-image-3.8.0-2-powerpc64-smp', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, 'linux-headers-powerpc-e500') + finally: + chroot.remove() + + def test_linux_headers_detection_names_chroot5(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-3.2.0-36-lowlatency-pae', + extra_tags={'Source': 'linux-lowlatency'}) + archive.create_deb('linux-image-3.8.0-0-lowlatency', + extra_tags={'Source': 'linux-lowlatency'}) + archive.create_deb('linux-image-3.5.0-18-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-3.5.0-19-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-generic', + extra_tags={'Source': + 'linux-meta'}) + archive.create_deb('linux-image-generic-lts-quantal', + extra_tags={'Source': + 'linux-meta-lts-quantal'}) + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, '') + + # Install kernel packages + for pkg in ('linux-image-3.2.0-36-lowlatency-pae', + 'linux-image-3.8.0-0-lowlatency', + 'linux-image-3.5.0-18-generic', + 'linux-image-3.5.0-19-generic', + 'linux-image-generic', + 'linux-image-generic-lts-quantal'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux_headers = kernel_detection.get_linux_headers_metapackage() + self.assertEqual(linux_headers, 'linux-headers-lowlatency') + finally: + chroot.remove() + + def test_linux_detection_chroot(self): + '''get_linux_metapackage() for test package repository''' + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-3.2.0-23-generic', + extra_tags={'Source': 'linux'}) + archive.create_deb('linux-image-3.2.0-33-generic', + extra_tags={'Source': 'linux'}) + archive.create_deb('linux-image-3.5.0-18-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-3.5.0-19-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-generic', + extra_tags={'Source': + 'linux-meta'}) + archive.create_deb('linux-image-generic-lts-quantal', + extra_tags={'Source': + 'linux-meta-lts-quantal'}) + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-3.2.0-23-generic', + 'linux-image-3.2.0-33-generic', + 'linux-image-3.5.0-18-generic', + 'linux-image-3.5.0-19-generic', + 'linux-image-generic', + 'linux-image-generic-lts-quantal'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, 'linux-generic-lts-quantal') + finally: + chroot.remove() + + def test_linux_detection_names_chroot1(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-nexus7', + extra_tags={'Source': 'linux-meta-nexus7'}) + archive.create_deb('linux-image-3.1.10-9-nexus7', + extra_tags={'Source': 'linux-nexus7'}) + archive.create_deb('linux-image-omap4', + extra_tags={'Source': + 'linux-meta-ti-omap4'}) + archive.create_deb('linux-image-3.2.0-1419-omap4', + extra_tags={'Source': + 'linux-ti-omap4'}) + archive.create_deb('linux-image-3.5.0-17-highbank', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-highbank', + extra_tags={'Source': + 'linux-meta-highbank'}) + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-meta-powerpc-smp'}) + archive.create_deb('linux-image-3.5.0-18-powerpc-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-powerpc64-smp', + extra_tags={'Source': + 'linux-meta-powerpc64-smp'}) + archive.create_deb('linux-image-3.5.0-17-powerpc64-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-ac100', + extra_tags={'Source': + 'linux-meta-ac100'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-nexus7', + 'linux-image-3.1.10-9-nexus7', + 'linux-image-omap4', + 'linux-image-3.2.0-1419-omap4', + 'linux-image-highbank', + 'linux-image-3.5.0-17-highbank', + 'linux-image-powerpc-smp', + 'linux-image-3.5.0-18-powerpc-smp', + 'linux-image-powerpc64-smp', + 'linux-image-3.5.0-17-powerpc64-smp', + 'linux-image-ac100', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, 'linux-powerpc-smp') + finally: + chroot.remove() + + def test_linux_detection_names_chroot2(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-nexus7', + extra_tags={'Source': 'linux-meta-nexus7'}) + archive.create_deb('linux-image-3.1.10-9-nexus7', + extra_tags={'Source': 'linux-nexus7'}) + archive.create_deb('linux-image-omap4', + extra_tags={'Source': + 'linux-meta-ti-omap4'}) + archive.create_deb('linux-image-3.2.0-1419-omap4', + extra_tags={'Source': + 'linux-ti-omap4'}) + archive.create_deb('linux-image-3.5.0-17-highbank', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-highbank', + extra_tags={'Source': + 'linux-meta-highbank'}) + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-meta-powerpc-smp'}) + archive.create_deb('linux-image-3.5.0-18-powerpc-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-powerpc64-smp', + extra_tags={'Source': + 'linux-meta-powerpc64-smp'}) + archive.create_deb('linux-image-3.5.0-19-powerpc64-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-ac100', + extra_tags={'Source': + 'linux-meta-ac100'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-nexus7', + 'linux-image-3.1.10-9-nexus7', + 'linux-image-omap4', + 'linux-image-3.2.0-1419-omap4', + 'linux-image-highbank', + 'linux-image-3.5.0-17-highbank', + 'linux-image-powerpc-smp', + 'linux-image-3.5.0-18-powerpc-smp', + 'linux-image-powerpc64-smp', + 'linux-image-3.5.0-19-powerpc64-smp', + 'linux-image-ac100', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, 'linux-powerpc64-smp') + finally: + chroot.remove() + + def test_linux_detection_names_chroot3(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-nexus7', + extra_tags={'Source': 'linux-meta-nexus7'}) + archive.create_deb('linux-image-3.1.10-9-nexus7', + extra_tags={'Source': 'linux-nexus7'}) + archive.create_deb('linux-image-omap4', + extra_tags={'Source': + 'linux-meta-ti-omap4'}) + archive.create_deb('linux-image-3.8.0-1419-omap4', + extra_tags={'Source': + 'linux-ti-omap4'}) + archive.create_deb('linux-image-3.5.0-17-highbank', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-highbank', + extra_tags={'Source': + 'linux-meta-highbank'}) + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-meta-powerpc-smp'}) + archive.create_deb('linux-image-3.5.0-18-powerpc-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-powerpc64-smp', + extra_tags={'Source': + 'linux-meta-powerpc64-smp'}) + archive.create_deb('linux-image-3.5.0-19-powerpc64-smp', + extra_tags={'Source': + 'linux'}) + archive.create_deb('linux-image-ac100', + extra_tags={'Source': + 'linux-meta-ac100'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-nexus7', + 'linux-image-3.1.10-9-nexus7', + 'linux-image-omap4', + 'linux-image-3.8.0-1419-omap4', + 'linux-image-highbank', + 'linux-image-3.5.0-17-highbank', + 'linux-image-powerpc-smp', + 'linux-image-3.5.0-18-powerpc-smp', + 'linux-image-powerpc64-smp', + 'linux-image-3.5.0-19-powerpc64-smp', + 'linux-image-ac100', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, 'linux-omap4') + finally: + chroot.remove() + + def test_linux_detection_names_chroot4(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-powerpc-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.8.0-3-powerpc-e500', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.8.0-1-powerpc-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.5.0-19-powerpc64-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.8.0-2-powerpc64-smp', + extra_tags={'Source': + 'linux-ppc'}) + archive.create_deb('linux-image-3.0.27-1-ac100', + extra_tags={'Source': + 'linux-ac100'}) + + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-powerpc-smp', + 'linux-image-3.8.0-3-powerpc-e500', + 'linux-image-3.8.0-1-powerpc-smp', + 'linux-image-3.5.0-19-powerpc64-smp', + 'linux-image-3.8.0-2-powerpc64-smp', + 'linux-image-3.0.27-1-ac100'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, 'linux-powerpc-e500') + finally: + chroot.remove() + + def test_linux_detection_names_chroot5(self): + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-3.2.0-36-lowlatency-pae', + extra_tags={'Source': 'linux-lowlatency'}) + archive.create_deb('linux-image-3.8.0-0-lowlatency', + extra_tags={'Source': 'linux-lowlatency'}) + archive.create_deb('linux-image-3.5.0-18-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-3.5.0-19-generic', + extra_tags={'Source': + 'linux-lts-quantal'}) + archive.create_deb('linux-image-generic', + extra_tags={'Source': + 'linux-meta'}) + archive.create_deb('linux-image-generic-lts-quantal', + extra_tags={'Source': + 'linux-meta-lts-quantal'}) + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-3.2.0-36-lowlatency-pae', + 'linux-image-3.8.0-0-lowlatency', + 'linux-image-3.5.0-18-generic', + 'linux-image-3.5.0-19-generic', + 'linux-image-generic', + 'linux-image-generic-lts-quantal'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, 'linux-lowlatency') + finally: + chroot.remove() + + def test_linux_detection_names_chroot6(self): + '''get_linux_metapackage() does not raise a KeyError''' + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-3.2.0-36-lowlatency-pae') + archive.create_deb('linux-image-3.8.0-0-lowlatency') + archive.create_deb('linux-image-3.5.0-18-generic') + archive.create_deb('linux-image-3.5.0-19-generic') + archive.create_deb('linux-image-generic') + archive.create_deb('linux-image-generic-lts-quantal') + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-3.2.0-36-lowlatency-pae', + 'linux-image-3.8.0-0-lowlatency', + 'linux-image-3.5.0-18-generic', + 'linux-image-3.5.0-19-generic', + 'linux-image-generic', + 'linux-image-generic-lts-quantal'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + try: + kernel_detection.get_linux_metapackage() + except KeyError: + self.fail("get_linux_metapackage() raised KeyError!") + finally: + chroot.remove() + + def test_linux_detection_names_chroot7(self): + '''get_linux_metapackage() continues despite a KeyError''' + chroot = aptdaemon.test.Chroot() + try: + chroot.setup() + chroot.add_test_repository() + archive = gen_fakearchive() + archive.create_deb('linux-image-3.2.0-36-lowlatency-pae') + archive.create_deb('linux-image-3.8.0-0-lowlatency', + extra_tags={'Source': 'linux-lowlatency'}) + archive.create_deb('linux-image-3.5.0-18-generic') + archive.create_deb('linux-image-3.5.0-19-generic') + archive.create_deb('linux-image-generic') + archive.create_deb('linux-image-generic-lts-quantal') + chroot.add_repository(archive.path, True, False) + + cache = apt.Cache(rootdir=chroot.path) + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, '') + + # Install kernel packages + for pkg in ('linux-image-3.2.0-36-lowlatency-pae', + 'linux-image-3.8.0-0-lowlatency', + 'linux-image-3.5.0-18-generic', + 'linux-image-3.5.0-19-generic', + 'linux-image-generic', + 'linux-image-generic-lts-quantal'): + cache[pkg].mark_install() + + kernel_detection = jockey.kerneldetection.KernelDetection(cache) + linux = kernel_detection.get_linux_metapackage() + self.assertEqual(linux, 'linux-lowlatency') + finally: + chroot.remove() + +if __name__ == '__main__': + unittest.main() only in patch2: unchanged: --- jockey-0.9.7.orig/jockey/kerneldetection.py +++ jockey-0.9.7/jockey/kerneldetection.py @@ -0,0 +1,118 @@ +# +# kerneldetection.py +# +# Copyright 2013 Canonical Ltd. +# +# Author: Alberto Milone +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. + +import apt +import logging +import re + +from subprocess import Popen + + +class KernelDetection(object): + + def __init__(self, cache=None): + if cache: + self.apt_cache = cache + else: + self.apt_cache = apt.Cache() + + def _is_greater_than(self, term1, term2): + # We don't want to take into account + # the flavour + pattern = re.compile('(.+)-([0-9]+)-(.+)') + match1 = pattern.match(term1) + match2 = pattern.match(term2) + if match1: + term1 = '%s-%s' % (match1.group(1), + match1.group(2)) + term2 = '%s-%s' % (match2.group(1), + match2.group(2)) + + logging.debug('Comparing %s with %s' % (term1, term2)) + command = 'dpkg --compare-versions %s gt %s' % \ + (term1, term2) + process = Popen(command.split(' ')) + process.communicate() + return not process.returncode + + def _get_linux_metapackage(self, headers): + '''Get the linux headers or linux metapackage''' + suffix = headers and '-headers' or '' + pattern = re.compile('linux-image-(.+)-([0-9]+)-(.+)') + source_pattern = re.compile('linux-(.+)') + + metapackage = '' + version = '' + for pkg in self.apt_cache: + if ('linux-image' in pkg.name and + 'extra' not in pkg.name and + self.apt_cache[pkg.name].is_installed or + self.apt_cache[pkg.name].marked_install): + match = pattern.match(pkg.name) + # Here we filter out packages such as + # linux-generic-lts-quantal + if match: + current_version = '%s-%s' % (match.group(1), + match.group(2)) + # See if the current version is greater than + # the greatest that we've found so far + if self._is_greater_than(current_version, + version): + try: + source = self.apt_cache[pkg.name].\ + candidate.record['Source'] + except KeyError: + # Sometimes the Source key is not + # available, see LP: #1123107 + continue + + version = current_version + match_source = source_pattern.match(source) + # Set the linux-headers metapackage + if '-lts-' in source and match_source: + # This is the case of packages such as + # linux-image-3.5.0-18-generic which + # comes from linux-lts-quantal. + # Therefore the linux-headers-generic + # metapackage would be wrong here and + # we should use + # linux-headers-generic-lts-quantal + # instead + metapackage = 'linux%s-%s-%s' % ( + suffix, + match.group(3), + match_source.group(1)) + else: + # The scheme linux-headers-$flavour works + # well here + metapackage = 'linux%s-%s' % ( + suffix, + match.group(3)) + return metapackage + + def get_linux_headers_metapackage(self): + '''Get the linux headers for the newest_kernel installed''' + return self._get_linux_metapackage(True) + + def get_linux_metapackage(self): + '''Get the linux metapackage for the newest_kernel installed''' + return self._get_linux_metapackage(False)