Detect and send kernel metapackages#276
Conversation
|
@rptrchv Check the Codacity errors. It's complaining about code quality. |
a-martynovich
left a comment
There was a problem hiding this comment.
There are many issues with this.
First, you use regexes for parsing the version from the package name. This will easily break because the package name may contain more dashes than your regex expects (look at https://packages.debian.org/jessie/linux-image-3.16.0-10-amd64 section "similar packages). Second, you're assuming that you can simply compare those packages by one number in their name, which will also break in many cases.
There is an easier and more robust solution. For every installed linux-image-... find its parent (the package which depends on it). Kernels which are not the latest version won't have a parent. Only the kernel of the latest version will have a parent, and that (or a level higher, if Ubuntu) is the meta-package. Also this way you can find out if the currently running kernel package does not match the meta-package, which means reboot is required (the new kernel was just installed).
Those kernels (that don't match my re pattern) are very exotic. Besides, this re pattern can be easily adjusted to support them too:
For kernels of all (available to me for check) platforms and distro versions it works. So this solution is not perfect (will not cover non-standard versions naming) but more than satisfactory.
We can't simply check all installed "linux-image-..." packages because there might be installed several different kernel types on a machine, e.g. "linux-image-4.15.0-XXX-aws" and "linux-image-4.15.0-XXX-generic". So we need to check for parents existence only kernel image packages of the same type as our running kernel (that's what my "get_latest_same_kernel_deb" function does now). Which again relies on re patterns matching, which in turn is not 100% reliable (as you pointed out). So your proposed solution has the same potential issue as mine. |
|
@rptrchv I see your point and I can't come up with any easier solution now. |
69e04f3 to
ffdeed3
Compare
There was a problem hiding this comment.
- Codacy shows 12 new issues, some of which you told me to correct in my PRs.
- I suggest renaming
is_amazon2()to smth likeis_rhel()(and changing detection accordingly to match RHEL, CentOS and Amazon Linux) because the logic will most probably be the same for RHEL, CentOS and Amazon Linux when it comes to RPM packages. - Codacy shows 12 new issues, some of which you told me to correct in my PRs.
| # No systemd - probably yum-cron is not running | ||
| # TODO: use "service" executable which also works without systemd and on older systems | ||
| return False | ||
| from sh import systemctl |
There was a problem hiding this comment.
I wrote this so it wouldn't fail if running in container. Why did you change this?
There was a problem hiding this comment.
I suggest renaming is_amazon2()
I don't agree. We can do that only after testing everything on RHEL and CentOS, not beforehand.
There was a problem hiding this comment.
you replied to a different comment
| if match: | ||
| name_parts = match.groups() # E.g. ('linux-image-4.4.0-', '174', '-generic') | ||
| latest_kernel_pkg = get_latest_same_kernel_deb(name_parts[0], name_parts[2]) | ||
| return apt_pkg.version_compare(latest_kernel_pkg.installed.version, kernel_pkg.installed.version) > 0 |
There was a problem hiding this comment.
why only newer? Can't we install older version? I think this should be != 0 i.e. not equal.
There was a problem hiding this comment.
We need reboot only when we have a newer version of the running kernel package installed. That exactly what my code does. I don't catch your point.
| if kernel_pkg is not None: | ||
| match = DEBIAN_KERNEL_PKG_NAME_RE.match(kernel_pkg.name) | ||
| if match: | ||
| name_parts = match.groups() # E.g. ('linux-image-4.4.0-', '174', '-generic') |
There was a problem hiding this comment.
How about we change this regex to linux-image-\d+\.\d+\.\d+\.-\d+-.+ since we actually expect it to look like that? This way we don't accidentally catch packets which we don't know.
| if __file__.encode() in package_header[rpm.RPMTAG_FILENAMES]: | ||
| return Installation.RPM | ||
| # Other. | ||
| import agent |
There was a problem hiding this comment.
from agent import __version__?
| 'version': kernel_pkg.installed.version, | ||
| 'source_name': kernel_pkg.installed.source_name, | ||
| 'source_version': kernel_pkg.installed.source_version, | ||
| 'arch': kernel_pkg.installed.architecture |
There was a problem hiding this comment.
you don't need .installed because get_kernel_deb_package already checks for that (is_installed).
There was a problem hiding this comment.
.installed here is a quite different thing
| match = DEBIAN_KERNEL_PKG_NAME_RE.match(kernel_pkg.name) | ||
| if match: | ||
| name_parts = match.groups() # E.g. ('linux-image-4.4.0-', '174', '-generic') | ||
| latest_kernel_pkg = get_latest_same_kernel_deb(name_parts[0], name_parts[2]) |
There was a problem hiding this comment.
this may break in case of linux-gcp to linux-gcp-edge upgrade. Basically it will be linux-image-5.0.0-xxxx-gcp -> linux-image-5.3.0-xxxx-gcp.
There was a problem hiding this comment.
Yes. But it's not that simple to properly handle it. That's why I believe the major kernel version upgrade case is out of the scope of this task and deserves a separate task.
a-martynovich
left a comment
There was a problem hiding this comment.
I still do not agree with the way this task was done, but it should work, so I'm not holding it any longer.
|
@a-martynovich can you give me a tl;dr how you think this should be redesigned? In the meantime, I'm merging this. |
|
I think it should build a dependency tree from any known kernel meta-package down to a concrete kernel package and not rely on package names. This also has some edge cases, though. |
|
Ok, I'll create a new ticket for that. |
|
@vpetersson we still need to expand this on Debian support, so yes, a ticket is needed. |
Closes #268