Skip to content

Commit

Permalink
updater: remove obsolete kernels from debian
Browse files Browse the repository at this point in the history
fixes QubesOS/qubes-issues/issues/6676

(cherry picked from commit 0d25c99)
  • Loading branch information
piotrbartman authored and marmarek committed Nov 5, 2024
1 parent 578a9fc commit ed1217c
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
3 changes: 3 additions & 0 deletions vmupdate/agent/source/apt/apt_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def upgrade_internal(self, remove_obsolete: bool) -> ProcessResult:
"An error occurred while upgrading packages: %s", str(exc))
result += ProcessResult(EXIT.ERR_VM_UPDATE, out="", err=str(exc))

if remove_obsolete:
result += self.remove_obsolete_kernels()

return result


Expand Down
42 changes: 42 additions & 0 deletions vmupdate/agent/source/apt/apt_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,17 @@ def get_packages(self):

return packages

def upgrade_internal(self, remove_obsolete: bool) -> ProcessResult:
"""
Additionally remove obsolete kernels.
"""
result = super().upgrade_internal(remove_obsolete)

if remove_obsolete:
result += self.remove_obsolete_kernels()

return result

def get_action(self, remove_obsolete: bool) -> List[str]:
"""
Return command `upgrade` or `dist-upgrade` if `remove_obsolete`.
Expand All @@ -90,3 +101,34 @@ def clean(self) -> int:
result = self.run_cmd(cmd, realtime=False)
return_code = EXIT.ERR_VM_CLEANUP if result.code != 0 else 0
return return_code

def remove_obsolete_kernels(self) -> ProcessResult:
"""
Remove old kernel packages in a little hacky way.
Usage of `apt autoremove` is not always safe and definitely
should not be run automatically. However, we want at lest remove
old kernels since they are heavy and clutter template vms.
"""
# dry run of autoremove to print which packages will be removed
# (printed with `Remv ` prefix). It's a simple way to keep apt logic
# which by default keep 2 newest versions of kernel.
cmd = [self.package_manager, "autoremove", "-s"]
result = self.run_cmd(cmd, realtime=False)

if not result: # no error
obsoletes = set()
for line in result.out.splitlines():
if line.startswith("Remv"):
package_name = line[len("Remv "):]
# consider using wider pattern
if package_name.startswith("linux-image"):
obsoletes.add(package_name.split(" ")[0])
if obsoletes:
cmd = [self.package_manager, "remove", "-y", *obsoletes]
result = self.run_cmd(cmd, realtime=False)
else:
result = ProcessResult.OK

result.code = EXIT.ERR_VM_CLEANUP if result.code != 0 else 0
return result

0 comments on commit ed1217c

Please sign in to comment.