forked from openshift/os
-
Notifications
You must be signed in to change notification settings - Fork 0
/
verify-kernel-versions
executable file
·141 lines (118 loc) · 4.42 KB
/
verify-kernel-versions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/usr/bin/env python3
"""
Checks to ensure the composed kernel versions and the kernel-rt extension
all have the same version.
We want to ensure we are shipping the same feature set, kmods/drivers,
and errata are applied for those customers who chose to switch between
kernels.
"""
import json
import os
import subprocess
import sys
#: When set to 1, doesn't stop builds when errors are found
IGNORE_KERNEL_MISMATCH = int(os.getenv('IGNORE_KERNEL_MISMATCH', 0))
try:
#: Jenkins provided workspace
WORKSPACE = sys.argv[1]
except Exception as ex:
print('Missing workspace path')
raise ex
#: Path to latest builds
LATEST_BUILDS = os.path.join(WORKSPACE, 'builds/latest/')
def exit_on_error(errors: list, title: str):
"""
Prints errors and exists.
:param errors: List of errors.
:raises: SystemExit
"""
if len(errors) > 0:
print(f'{title} - {len(errors)} error(s):')
for err in errors:
print(f'- {err}')
if not IGNORE_KERNEL_MISMATCH:
raise SystemExit(1)
def get_nevr_from_rpm(rpm_path: str) -> list:
"""
Uses the rpm command to parse Name, Epoch, Version, and Release
from the local package.
:param rpm_path: Path to the local rpm package
:raises: CalledProcessError, FileNotFoundError
"""
# Create a command that makes it easy to parse (-'s are deceiving)
cmd = [
'rpm', '-qp', '--qf',
"%{NAME}|%{EPOCH}|%{VERSION}|%{RELEASE}|%{ARCH}", rpm_path]
parts = subprocess.check_output(cmd).decode('utf8').split('|')
# If rpm says there is no epoch, it's 0
if parts[1] == '(none)':
parts[1] = '0'
return parts
def get_rt_evr() -> list:
"""
Goes through the kernel-rt extensions path, verifies the kernel-rt
packages all have the same version, then returns a list of the
epoch, version, release.
.. note::
If the kernel-rt versions don't match eachother an error
prints and the script exits.
:raises: SystemExit, CalledProcessError, FileNotFoundError
"""
evr = []
errors = []
rt_ext_path = os.path.join(WORKSPACE, 'extensions/extensions/kernel-rt/')
if not os.path.isdir(rt_ext_path):
exit_on_error([
f'{rt_ext_path} is not a directory or does not exist'],
'verify rt extensions directory')
for p, d, f in os.walk(rt_ext_path):
for fname in f:
if fname.endswith('.rpm'):
pkg = os.path.join(p, fname)
nevr = get_nevr_from_rpm(pkg)
# Remove the rt specific string
nevr[3] = nevr[3].replace(
nevr[3][nevr[3].index('.rt'):nevr[3].index('.el')], '')
if evr:
if evr != nevr[1:]:
errors.append(
f'{pkg} version differs from other rt packages:'
f' {evr} != {nevr[1:]}')
evr = nevr[1:]
exit_on_error(errors, 'rt kernel version check')
if not IGNORE_KERNEL_MISMATCH:
print('rt packages have consistent versions...')
return evr
def main():
"""
Main entry point.
:raises: FileNotFoundError, SystemExit
"""
# kernel-rt is only available on x86_64. Exit early on any
# other architecture
arch = subprocess.check_output('arch')[:-1].decode()
if arch != 'x86_64':
print(
f'Skipping kernel/kernel-rt check on non x86_64 platform: {arch}')
return SystemExit()
print('Verifying kernel versions are inline with each other ...')
rt_evr = get_rt_evr()
# Since all the versioning should be consistent we can
# check that the kernel packages match the single kernel-rt version
errors = []
cmj = os.path.join(LATEST_BUILDS, 'x86_64', 'commitmeta.json')
with open(cmj, 'r') as f:
commitmeta = json.load(f)
for i in commitmeta['rpmostree.rpmdb.pkglist']:
if i[0].startswith('kernel'):
if i[1:] != rt_evr:
# version-release.arch.epoch
kernel_pkg = '-'.join(i[2:-1]) + "." + i[1]
rt_kernel_pkg = '-'.join(rt_evr[1:-1]) + "." + rt_evr[0]
errors.append(
f'kernel-rt and {i[0]} version mismatch: '
f'{kernel_pkg} != {rt_kernel_pkg}')
exit_on_error(errors, 'default kernel and rt version check')
print('<3 Kernel versions match <3')
if __name__ == '__main__':
main()