Viewing file: kerneldetection.py (7.68 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# # kerneldetection.py # # Copyright 2013 Canonical Ltd. # # Author: Alberto Milone <alberto.milone@canonical.com> # # 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_pkg import logging import re
from subprocess import Popen
class KernelDetection(object):
def __init__(self, cache=None): if cache: self.apt_cache = cache self.apt_depcache = apt_pkg.DepCache(cache) else: apt_pkg.init_config() apt_pkg.init_system() self.apt_cache = apt_pkg.Cache(None) self.apt_depcache = apt_pkg.DepCache(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_flavour(self, candidates, image): pattern = re.compile(r'linux-image-([0-9]+\.[0-9]+\.[0-9]+)-([0-9]+)-(.+)') match = pattern.match(image) flavour = '' if match: flavour = match.group(3)
return flavour
def _filter_cache(self, pkg): package_name = pkg.name if (package_name.startswith('linux-image') and 'extra' not in package_name and (pkg.current_ver or self.apt_depcache.marked_install(pkg))): return package_name else: return None
def _get_linux_metapackage(self, target): '''Get the linux headers, linux-image or linux metapackage''' metapackage = '' image_package = '' version = '' prefix = 'linux-%s' % ('headers' if target == 'headers' else 'image')
pattern = re.compile('linux-image-(.+)-([0-9]+)-(.+)')
for package_name in map(self._filter_cache, self.apt_cache.packages): if package_name: match = pattern.match(package_name) # Here we filter out packages other than # the actual image or header packages if match: current_package = match.group(0) 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): version = current_version image_package = current_package
if version: if target == 'headers': target_package = image_package.replace('image', 'headers') else: target_package = image_package
reverse_dependencies = [dep.parent_pkg.name for dep in self.apt_cache[target_package] .rev_depends_list if dep.parent_pkg.name.startswith(prefix)]
if reverse_dependencies: # This should be something like linux-image-$flavour # or linux-headers-$flavour metapackage = '' for candidate in reverse_dependencies: try: candidate_pkg = self.apt_cache[candidate] if (candidate.startswith(prefix) and (candidate_pkg and (candidate_pkg.current_ver or self.apt_depcache.marked_install(candidate_pkg))) and candidate.replace(prefix, '') > metapackage.replace(prefix, '')): metapackage = candidate except KeyError: continue # if we are looking for headers, then we are good if target == 'meta': # Let's get the metapackage reverse_dependencies = [dep.parent_pkg.name for dep in self.apt_cache[metapackage] .rev_depends_list if dep.parent_pkg.name.startswith('linux-')] if reverse_dependencies: flavour = self._get_linux_flavour(reverse_dependencies, target_package) linux_meta = '' for meta in reverse_dependencies: # For example linux-generic-hwe-20.04 if meta.startswith('linux-%s-' % (flavour)): linux_meta = meta break # This should be something like linux-$flavour if not linux_meta: # Try the 1st reverse dependency metapackage = reverse_dependencies[0] else: metapackage = linux_meta return metapackage
def get_linux_headers_metapackage(self): '''Get the linux headers for the newest_kernel installed''' return self._get_linux_metapackage('headers')
def get_linux_image_metapackage(self): '''Get the linux headers for the newest_kernel installed''' return self._get_linux_metapackage('image')
def get_linux_metapackage(self): '''Get the linux metapackage for the newest_kernel installed''' return self._get_linux_metapackage('meta')
def get_linux_version(self): linux_image_meta = self.get_linux_image_metapackage() linux_version = '' try: # dependencies = self.apt_cache[linux_image_meta].candidate.\ # record['Depends'] candidate = self.apt_depcache.get_candidate_ver(self.apt_cache[linux_image_meta]) for dep_list in candidate.depends_list_str.get('Depends'): for dep_name, dep_ver, dep_op in dep_list: if dep_name.startswith('linux-image'): linux_version = dep_name.strip().replace('linux-image-', '') break except KeyError: logging.error('No dependencies can be found for %s' % (linux_image_meta)) return None
# if ', ' in dependencies: # deps = dependencies.split(', ') # for dep in deps: # if dep.startswith('linux-image'): # linux_version = dep.replace('linux-image-', '') # else: # if dependencies.strip().startswith('linux-image'): # linux_version = dependencies.strip().replace('linux-image-', '')
return linux_version
|