#!/usr/bin/env python3 """Build the latest kernel but only if need be""" import os import shutil import subprocess EMERGE = os.environ["EMERGE"].split() USEPKG = os.environ["USEPKG"].split() def get_latest_available_kernel(): kernel = os.environ["KERNEL"] package_name = "sys-kernel/{}".format(kernel) popen = subprocess.Popen( ["portageq", "best_visible", "/", package_name], stdout=subprocess.PIPE ) cpv = popen.stdout.read().decode().strip() return cpv.rpartition("-")[2] def get_current_kernel(): """what kernel does /boot/vmlinuz point to""" vmlinuz = "/boot/vmlinuz" if not os.path.islink(vmlinuz): return None filename = os.path.basename(os.path.realpath(vmlinuz)) assert filename.startswith("vmlinuz") part_after_vmlinuz = filename[8:] # may have "-gentoo" or whatever in the name version = part_after_vmlinuz.rpartition("-")[0] return version def install_kernel_package_deps(): kernel = os.environ["KERNEL"] package_name = "sys-kernel/{}".format(kernel) cmd = EMERGE + USEPKG + ["--onlydeps", "--oneshot", "--noreplace", package_name] subprocess.check_call(cmd) def copy_kernel_config(): filename = "/root/kernel.config" shutil.copy(filename, "/usr/src/linux/.config") def build_kernel(): makeopts = os.environ.get("MAKEOPTS", "") subprocess.check_call( ["make", "-C", "/usr/src/linux", "MAKEOPTS=" + makeopts, "oldconfig"] ) subprocess.check_call(["make", "-C", "/usr/src/linux", "MAKEOPTS=" + makeopts]) def remove_old_kernels(): kernel_files = ["vmlinuz-", "System.map-", "config-"] for filename in os.listdir("/boot"): for kernel_file in kernel_files: if filename.startswith(kernel_file): path = os.path.join("/boot", filename) os.unlink(path) if os.path.exists("/boot/vmlinuz"): os.unlink("/boot/vmlinuz") ##shutil.rmtree("/lib/modules", ignore_errors=True) def install_kernel(): makeopts = os.environ.get("MAKEOPTS", "") modules_install = False for line in open("/usr/src/linux/.config"): if "CONFIG_MODULES=y" in line: modules_install = True break if modules_install: subprocess.check_call([ 'make', '-C', '/usr/src/linux', 'MAKEOPTS=' + makeopts, 'install', 'modules_install' ]) else: subprocess.check_call([ 'make', '-C', '/usr/src/linux', 'MAKEOPTS=' + makeopts, 'install' ]) # create the symlink. /sbin/installkernel claims this is not used on # "modern" distributions and doesn't create it (unless it already # exists). I still do this however. for filename in os.listdir("/boot"): if filename.startswith("vmlinuz-"): if os.path.lexists("/boot/vmlinuz"): os.unlink("/boot/vmlinuz") os.symlink(filename, "/boot/vmlinuz") break def uninstall_kernel_package_deps(): subprocess.check_call(EMERGE + USEPKG + ["--depclean", "--with-bdeps=n"]) def backup_kernel_config(): shutil.copy("/usr/src/linux/.config", "/root/kernel.config") def main(): latest_kernel = get_latest_available_kernel() current_kernel = get_current_kernel() if current_kernel == latest_kernel: return install_kernel_package_deps() ##copy_kernel_config() build_kernel() remove_old_kernels() install_kernel() backup_kernel_config() uninstall_kernel_package_deps() main()