[Merge] ~enr0n/ubuntu-release-upgrader:lp2020406 into ubuntu-release-upgrader:ubuntu/main
Nick Rosbrook
mp+445212 at code.launchpad.net
Fri Jun 23 13:09:42 UTC 2023
Thanks for your review! I have responded to all comments.
Diff comments:
> diff --git a/DistUpgrade/DistUpgradeQuirks.py b/DistUpgrade/DistUpgradeQuirks.py
> index 0bd1ef9..dfcd86c 100644
> --- a/DistUpgrade/DistUpgradeQuirks.py
> +++ b/DistUpgrade/DistUpgradeQuirks.py
> @@ -521,6 +523,101 @@ class DistUpgradeQuirks(object):
> self._view.getInstallProgress(self.controller.cache)
> )
>
> + def _disable_dkms_autoinstall(self):
> + if not os.path.exists('/usr/sbin/dkms'):
> + return
> +
> + with open('/etc/dkms/no-autoinstall', 'w'):
> + pass
> +
> + self._installed_dkms_modules = set()
In practice I found that at the end of the upgrade (where dkms autoinstall is disabled), dkms status is empty. So I think this is necessary unless we just assume that everything in /usr/src should be installed. But if someone had a dkms package installed but later ran `dkms uninstall` on that module, then `dkms autoinstall` would normally ignore that on upgrade, so I thought we should do the same.
> +
> + r = subprocess.run(['dkms', 'status'],
> + stdout=subprocess.PIPE,
> + stderr=subprocess.PIPE)
> + if r.returncode != 0:
> + logging.debug('dkms status failed: {}'.format(r.stderr.decode('utf-8')))
> + return
> +
> + for line in [l.decode('utf-8') for l in r.stdout.splitlines()]:
> + # Each line of dkms status output is formatted like this:
> + # $module/$version, $kernel_version, $arch: $install_state
> + parts = [l.strip() for l in line.split(',')]
> + try:
> + module = parts[0].split('/')[0]
> + install_state = parts[2].split(':')[1].strip()
> +
> + if install_state == 'installed':
> + self._installed_dkms_modules.add(module)
> + except IndexError:
> + logging.debug('Unexpected output from dkms status: {}', line)
> +
> + def _reenable_dkms_autoinstall(self):
> + if not os.path.exists('/usr/sbin/dkms'):
> + return
> +
> + try:
> + os.remove('/etc/dkms/no-autoinstall')
> + except OSError as e:
> + logging.debug('Failed to remove /etc/dkms/no-autoinstall: {}'
> + .format(e))
> +
> + if not self._installed_dkms_modules:
> + return
> +
> + # Figure out which kernel we should build against by checking the
> + # dependency of the installed linux-headers metapackage.
> + headers_version = None
> +
> + headers_pkg = self._get_linux_metapackage(self.controller.cache, True)
> + headers_pkg = self.controller.cache[headers_pkg]
> +
> + installed_versions = [v for v in headers_pkg.versions if v.is_installed]
> + target_version = sorted(installed_versions)[-1]
I am pretty sure that the underlying object from python-apt (apt.Version) implements all of the comparison functions (__eq__, __ge__, etc.) so that sorted() will work correctly. I will double check this though.
> +
> + deps = []
> + for d in target_version.dependencies:
> + deps += d
Ah cool, thanks!
> +
> + for dep in deps:
> + if dep.name.startswith('linux-headers'):
> + headers_version = dep.name.removeprefix('linux-headers-')
> + break
> +
> + if headers_version is None:
> + logging.debug('Failed to find installed linux-headers package')
> + return
> +
Yeah, I think for consistency with the rest of the code it is necessary to at least base our decision on the meta package returned by `_get_linux_metapackage()`. If you know of a better way to map `linux-headers-generic` to the latest installed version of `linux-headers-$version-generic`, then I would use that. But from just looking at the meta package itself, it seemed the most reliable way was to look at the dependency.
> + # Now try to re-build/install the previously installed dkms modules
> + # against these newly-installed kernel headers, and if a module fails
> + # to build, leave it uninstalled.
> + failed_modules = []
> + for mod in self._installed_dkms_modules:
> + logging.debug('Attempting to re-install {} dkms module with {}'
> + .format(mod, headers_version))
> +
> + # By this point in the upgrade, the dkms modules may have been
> + # upgraded, so check what versions are installed now.
> + sourcedirs = glob.glob('/usr/src/{}-*'.format(mod))
> + versions = [os.path.basename(p).removeprefix(mod+'-') for p in sourcedirs]
> +
> + for v in versions:
> + mod = '{}/{}'.format(mod, v)
> +
> + r = subprocess.run(['dkms', 'install', mod, '-k', headers_version],
> + stderr=subprocess.PIPE)
> + if r.returncode != 0:
> + logging.debug('dkms install failed for {}:\n{}'
> + .format(mod, r.stderr.decode('utf-8')))
> + failed_modules.append(mod)
> +
See my earlier comment about dkms status being empty after the upgrade. That is a good point about newly installed dkms modules, however.
> + if failed_modules:
> + self._view.information(_('dkms module install failed'),
> + _('The following dkms modules failed to '
> + 'build with the installed kernel headers '
> + 'and will remain disabled:\n{}')
> + .format(' ' + '\n'.join(failed_modules)))
> +
> def _add_apport_ignore_tracker_extract(self):
> path = '/etc/apport/blacklist.d/upgrade-quirk-tracker-extract-3'
>
--
https://code.launchpad.net/~enr0n/ubuntu-release-upgrader/+git/ubuntu-release-upgrader/+merge/445212
Your team Ubuntu Core Development Team is subscribed to branch ubuntu-release-upgrader:ubuntu/main.
More information about the Ubuntu-reviews
mailing list