add scripts
Signed-off-by: Martin Matous <m@matous.dev>
This commit is contained in:
parent
c6c66648ea
commit
5a4419bb4e
12 changed files with 802 additions and 1 deletions
188
kernel-update.py
Executable file
188
kernel-update.py
Executable file
|
|
@ -0,0 +1,188 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import argparse
|
||||
import magic
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from packaging.version import Version
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
BOOT_FILES = {
|
||||
'config': Path('config-gentoo'),
|
||||
'initramfs': Path('initramfs-gentoo.img'),
|
||||
'kernel': Path('vmlinuz-gentoo'),
|
||||
'system_map': Path('System.map-gentoo'),
|
||||
}
|
||||
|
||||
SRC_DIR = Path('/usr/src')
|
||||
BOOT_DIR = Path('/boot')
|
||||
|
||||
|
||||
def backup_kernel(boot_dir: Path, files: Dict[str, Path]) -> None:
|
||||
for f in files.values():
|
||||
src = boot_dir/f
|
||||
dst = boot_dir/(f.name + '.old')
|
||||
print(f'Backing-up {src} to {dst}')
|
||||
shutil.copy2(src, dst)
|
||||
|
||||
|
||||
def rollback_impl(boot_dir: Path, files: Dict[str, Path]) -> None:
|
||||
for f in files.values():
|
||||
src = boot_dir/(f.name + '.old')
|
||||
dst = boot_dir/f
|
||||
print(f'Restoring {src} to {dst}')
|
||||
shutil.copy2(src, dst)
|
||||
|
||||
|
||||
def update_config(old_path: Path, new_path: Path, make_cmd: List[str]) -> None:
|
||||
if old_path == new_path:
|
||||
return
|
||||
old_config = old_path/'.config'
|
||||
new_config = new_path/'.config'
|
||||
while new_config.is_file():
|
||||
response = input('New config present. Overwrite? [y/N]').strip().lower()
|
||||
if response == 'y':
|
||||
break
|
||||
elif response == '' or response == 'n':
|
||||
return
|
||||
else:
|
||||
print("unrecognized option {}", response)
|
||||
print(f'Copying config from {old_config} to {new_config}')
|
||||
shutil.copy2(old_config, new_config)
|
||||
|
||||
print(f'Setting symlink to {new_path}')
|
||||
subprocess.run(['eselect', 'kernel', 'set', new_path.name])
|
||||
print(f'Migrating config options')
|
||||
migrate = make_cmd + ['-C', new_path.as_posix(), 'oldconfig']
|
||||
subprocess.run(migrate)
|
||||
menuconfig = make_cmd + ['-C', new_path.as_posix(), 'menuconfig']
|
||||
while True:
|
||||
subprocess.run(menuconfig)
|
||||
response = input('Stop editing? [Y/n]').strip().lower()
|
||||
if response == '' or response == 'y':
|
||||
break
|
||||
elif response == 'n':
|
||||
continue
|
||||
else:
|
||||
print("unrecognized option {}", response)
|
||||
|
||||
|
||||
def compile_kernel(new_path: Path, make_cmd: List[str]) -> None:
|
||||
cc = make_cmd + ['-C', new_path.as_posix()]
|
||||
subprocess.run(cc)
|
||||
|
||||
|
||||
def install_kernel(kernel_dir: Path, boot_dir: Path, boot_files: Dict[str, Path], make_cmd: List[str]) -> None:
|
||||
make_files = {
|
||||
'config': Path('.config'),
|
||||
'system_map': Path('System.map'),
|
||||
'kernel': Path('arch/x86/boot/bzImage')
|
||||
}
|
||||
|
||||
config = (kernel_dir/make_files['config']).as_posix()
|
||||
# subprocess.run(make_cmd.extend(['-C', kernel_dir, 'install'])) # this would create unwanted entries
|
||||
common_keys = make_files.keys() & boot_files.keys()
|
||||
for key in common_keys:
|
||||
src = kernel_dir/make_files[key]
|
||||
dst = boot_dir/boot_files[key]
|
||||
print(f'Installing {src} to {dst}')
|
||||
shutil.copy2(src, dst)
|
||||
|
||||
install_modules = make_cmd + ['-C', kernel_dir.as_posix(), 'modules_install']
|
||||
subprocess.run(install_modules)
|
||||
|
||||
genkernel = ['genkernel', f'--kernel-config={config}', '--microcode', 'initramfs']
|
||||
subprocess.run(genkernel)
|
||||
|
||||
|
||||
def linux_folder(src_dir: Path, version: str) -> Path:
|
||||
return (src_dir / (f'linux-{version}-gentoo'))
|
||||
|
||||
|
||||
def module_check(boot_dir: Path, boot_files: Dict[str, Path]) -> Tuple[bool, Path]:
|
||||
kernel_name = boot_files['kernel'].name + '.old'
|
||||
old_kernel: Path = boot_dir/kernel_name
|
||||
magic_list = magic.from_file(old_kernel).split()
|
||||
version = Path(magic_list[magic_list.index('version') + 1])
|
||||
modules = Path('/lib/modules')/version
|
||||
if not modules.exists():
|
||||
return (False, version)
|
||||
return (True, version)
|
||||
|
||||
def rollback_kernel(boot_dir: Path, boot_files: Dict[str, Path], _args: Any) -> None:
|
||||
check = module_check(boot_dir, boot_files)
|
||||
if not check[0]:
|
||||
err = f'Module directory not found for {check[1]}.\nRefusing to proceed.'
|
||||
raise RuntimeError(err)
|
||||
rollback_impl(boot_dir, boot_files)
|
||||
|
||||
def update_kernel(boot_dir: Path, boot_files: Dict[str, Path], args: Any) -> None:
|
||||
old_path = linux_folder(SRC_DIR, args.old_version)
|
||||
new_path = linux_folder(SRC_DIR, args.new_version)
|
||||
new_version = new_path.name # rename to new_folder
|
||||
make_cmd = ['make', f'-j{len(os.sched_getaffinity(0))}']
|
||||
clang_env = ['CC=clang', 'LD=ld.lld', 'LLVM=1', 'LLVM_IAS=1']
|
||||
|
||||
if args.llvm:
|
||||
make_cmd.extend(clang_env)
|
||||
none_selected = not (args.backup or args.config or args.compile or args.install or args.rollback)
|
||||
if none_selected:
|
||||
backup_kernel(BOOT_DIR, BOOT_FILES)
|
||||
update_config(old_path, new_path, make_cmd)
|
||||
compile_kernel(new_path, make_cmd)
|
||||
install_kernel(new_path, BOOT_DIR, BOOT_FILES, make_cmd)
|
||||
if args.backup:
|
||||
backup_kernel(BOOT_DIR, BOOT_FILES)
|
||||
if args.config:
|
||||
update_config(old_path, new_path, make_cmd)
|
||||
if args.compile:
|
||||
compile_kernel(new_path, make_cmd)
|
||||
if args.install:
|
||||
install_kernel(new_path, BOOT_DIR, BOOT_FILES, make_cmd)
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description='Convenience for manual kernel updates')
|
||||
subparsers = parser.add_subparsers()
|
||||
|
||||
rollback = subparsers.add_parser('rollback')
|
||||
rollback.set_defaults(func=rollback_kernel)
|
||||
|
||||
update = subparsers.add_parser('update',
|
||||
usage=f'{sys.argv[0]} update 5.15.12 5.16.3',
|
||||
)
|
||||
update.add_argument(
|
||||
'--llvm', '-l', action='store_true',
|
||||
help="Use clang/llvm to compile kernel")
|
||||
update.add_argument(
|
||||
'--backup', '-b', action='store_true',
|
||||
help="Backup old kernel files as .old")
|
||||
update.add_argument(
|
||||
'--rollback', '-r', action='store_true',
|
||||
help='Restore .old kernel files as main boot choice')
|
||||
update.add_argument(
|
||||
'--config', '-C', action='store_true',
|
||||
help='Migrate config from old kernel')
|
||||
update.add_argument(
|
||||
'--compile', '-c', action='store_true',
|
||||
help='Compile new kernel')
|
||||
update.add_argument(
|
||||
'--install', '-i', action='store_true',
|
||||
help='Install new kernel')
|
||||
update.add_argument(
|
||||
'old_version', type=Version,
|
||||
help='Old kernel version')
|
||||
update.add_argument(
|
||||
'new_version', type=Version,
|
||||
help='New kernel version')
|
||||
update.set_defaults(func=update_kernel)
|
||||
|
||||
args = parser.parse_args()
|
||||
args.func(BOOT_DIR, BOOT_FILES, args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue