Skip to content

Commit 585f29f

Browse files
committed
fix: pick the kernel version compatible to gpfs based on global search instead of hardcoding
Current Issue: - CentOS has rolling builds and it requires manual intervention to identify and hardcode the builds - It shows as test failure which may lead to miss issues Proposed Solution: - To have a generic mechanism to identify the kernel version for the qcow image before loading - Provide the constraint based on GPFS versions - Parse, compare and pick the version that is satisfying the kernel version Signed-off-by: Manimaran-MM <manim@redhat.com>
1 parent d6a790c commit 585f29f

File tree

3 files changed

+106
-7
lines changed

3 files changed

+106
-7
lines changed

ci_utils/common/helpers.py

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import os
22
import json
3+
import re
34
import subprocess
45
from typing import Dict, Any
6+
from distutils.version import LooseVersion
57

68
from ci_utils.common.logger import get_logger
79

@@ -134,4 +136,81 @@ def run_cmd(session, cmd, check=True, timeout=3600, source_bashrc=False):
134136
logger.error(f"Failure Output: {out}")
135137
raise RuntimeError(err)
136138
logger.info(f"[REMOTE] Command output for {cmd_to_run} with return code {code}: Output: {out.strip()} \n {err.strip()}\n")
137-
return out.strip(), code
139+
return out.strip(), code
140+
141+
# -----------------------
142+
# Identify the matching Qcow image from the list of available images
143+
# -----------------------
144+
def identify_matching_qcow_image(session,centos_arch, centos_version, image_base_url, backend_type="gpfs", version_constraints=None):
145+
"""
146+
Identify the matching Qcow image from the list of available images
147+
Args:
148+
centos_arch (str): CentOS architecture (x86_64, aarch64)
149+
centos_version (str): CentOS version (9, 8, 7)
150+
image_base_url (str): Base URL of the image list
151+
backend_type (str): Backend type (gpfs, pjdfs)
152+
Returns:
153+
str: Matching Qcow image name
154+
"""
155+
logger.info(f"[STEP]: Identifying matching Qcow image for CentOS {centos_version} {centos_arch} {backend_type} with version constraints {version_constraints}")
156+
run_cmd(session, "systemctl enable --now libvirtd")
157+
run_cmd(session, "dnf install -y libguestfs-tools-c")
158+
available_images = run_cmd(
159+
session,
160+
rf"curl -s {image_base_url} | grep -oP 'CentOS-Stream-GenericCloud-{centos_arch}-{centos_version}.*?\.qcow2(?=\")'"
161+
)
162+
163+
logger.info(f"[INFO] Available images: {available_images}")
164+
165+
# Parse available_images output into a list (assuming it's a string with newlines)
166+
# Note: available_images is a tuple (output, code) from run_cmd, so we need to extract the output
167+
images_list = available_images[0].strip().split('\n') if isinstance(available_images, tuple) else available_images.strip().split('\n')
168+
images_list = [img for img in images_list if img.strip()] # Remove empty strings
169+
170+
# Create the destination directory if it doesn't exist
171+
run_cmd(session, "mkdir -p /var/lib/libguestfs/images/")
172+
173+
# Iterate from the last image backwards
174+
for image_name in reversed(images_list):
175+
image_name = image_name.strip()
176+
if not image_name:
177+
continue
178+
179+
logger.info(f"Processing image: {image_name}")
180+
181+
# wget operation with baseurl + image name
182+
image_url = f"{image_base_url.rstrip('/')}/{image_name}"
183+
run_cmd(session, f"wget -q {image_url}")
184+
185+
# Move the downloaded image to /var/lib/libguestfs/images/
186+
run_cmd(session, f"mv {image_name} /var/lib/libguestfs/images/")
187+
188+
# chmod 644 on all qcow2 images in the directory
189+
run_cmd(session, "chmod 644 /var/lib/libguestfs/images/*.qcow2")
190+
191+
# Check kernel version using guestfish
192+
image_path = f"/var/lib/libguestfs/images/{image_name}"
193+
kernel_version, _ = run_cmd(session, f'virt-ls -a "{image_path}" /usr/lib/modules/')
194+
logger.info(f"[INFO] Kernel version for {image_name}: {kernel_version}")
195+
196+
if version_constraints:
197+
198+
kernel_ver_str = kernel_version[0].strip() if isinstance(kernel_version, tuple) else kernel_version.strip()
199+
200+
# Normalize both versions
201+
kernel_normalized = re.match(r"(\d+\.\d+\.\d+-\d+)", kernel_ver_str).group(1)
202+
constraint_normalized = re.match(r"(\d+\.\d+\.\d+-\d+)", version_constraints).group(1)
203+
204+
logger.info(f"[INFO] Comparing kernel {kernel_ver_str} (normalized: {kernel_normalized}) with constraint {version_constraints} (normalized: {constraint_normalized})")
205+
206+
# Use LooseVersion for comparison
207+
if LooseVersion(kernel_normalized) <= LooseVersion(constraint_normalized):
208+
logger.info(f"[INFO] Kernel version meets constraint. Returning image URL: {image_url}")
209+
return image_url
210+
else:
211+
logger.info(f"[INFO] Kernel version does NOT meet constraint, trying next image")
212+
run_cmd(session, f"rm -f {image_path}")
213+
continue
214+
else:
215+
logger.info(f"[INFO] No version constraints specified, returning image URL: {image_url}")
216+
return image_url

ci_utils/gpfs/gpfs_setup.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,26 @@ def _install_on_node(node, sess):
119119
run_cmd(sess, "dnf install -y kernel-devel-$(uname -r) kernel-headers-$(uname -r)")
120120
else:
121121
logger.info(f"Attempting Koji fetch...")
122-
run_cmd(sess, "wget https://kojihub.stream.centos.org/kojifiles/packages/kernel/5.14.0/639.el9/x86_64/kernel-devel-5.14.0-639.el9.x86_64.rpm")
123-
run_cmd(sess, "wget https://kojihub.stream.centos.org/kojifiles/packages/kernel/5.14.0/639.el9/x86_64/kernel-headers-5.14.0-639.el9.x86_64.rpm")
124-
run_cmd(sess, "ls -la")
125-
run_cmd(sess, "dnf -y install openssl-fips-provider ./kernel-devel-5.14.0-639.el9.x86_64.rpm ./kernel-headers-5.14.0-639.el9.x86_64.rpm")
122+
# Get kernel version and extract components for Koji URL
123+
# Example: 5.14.0-658.el9.x86_64 -> major=5.14.0, build=658, release=el9
124+
kernel_ver, _ = run_cmd(sess, "uname -r")
125+
kernel_ver = kernel_ver.strip()
126+
# Parse: 5.14.0-658.el9.x86_64 -> extract 5.14.0, 658, el9
127+
match = re.match(r'(\d+\.\d+\.\d+)-(\d+)\.(el\d+)', kernel_ver)
128+
if match:
129+
major, build, release = match.groups()
130+
koji_base = f"https://kojihub.stream.centos.org/kojifiles/packages/kernel/{major}/{build}.{release}/x86_64"
131+
kernel_pkg_ver = f"{major}-{build}.{release}"
132+
run_cmd(sess, f"wget {koji_base}/kernel-devel-{kernel_pkg_ver}.x86_64.rpm")
133+
run_cmd(sess, f"wget {koji_base}/kernel-headers-{kernel_pkg_ver}.x86_64.rpm")
134+
run_cmd(sess, "ls -la")
135+
run_cmd(sess, f"dnf -y install openssl-fips-provider ./kernel-devel-{kernel_pkg_ver}.x86_64.rpm ./kernel-headers-{kernel_pkg_ver}.x86_64.rpm")
136+
else:
137+
logger.warning(f"Could not parse kernel version {kernel_ver}, falling back to default")
138+
run_cmd(sess, "wget https://kojihub.stream.centos.org/kojifiles/packages/kernel/5.14.0/570.el9/x86_64/kernel-devel-5.14.0-570.el9.x86_64.rpm")
139+
run_cmd(sess, "wget https://kojihub.stream.centos.org/kojifiles/packages/kernel/5.14.0/570.el9/x86_64/kernel-headers-5.14.0-570.el9.x86_64.rpm")
140+
run_cmd(sess, "ls -la")
141+
run_cmd(sess, "dnf -y install openssl-fips-provider ./kernel-devel-5.14.0-570.el9.x86_64.rpm ./kernel-headers-5.14.0-570.el9.x86_64.rpm")
126142
run_cmd(
127143
sess,
128144
"yum -y install "

tests/test_pynfs_cthon.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ def test_pynfs_gpfs(create_session, cmake_flags):
367367
vm_name = "centos9-vm"
368368
username = "root"
369369
ssh_key = "/root/.ssh/id_rsa.pub"
370+
version_constraints = "5.14.0-570.62.1.el9_6" #Assuming GPFS 6.0 https://www.ibm.com/docs/en/STXKQY/gpfsclustersfaq.html#fsi
370371
gerrit_host = os.getenv("GERRIT_HOST", "review.gerrithub.io")
371372
gerrit_project = os.getenv("GERRIT_PROJECT", "ffilz/nfs-ganesha")
372373
gerrit_refspec = os.getenv("GERRIT_REFSPEC", "")
@@ -386,13 +387,16 @@ def test_pynfs_gpfs(create_session, cmake_flags):
386387
# -----------------------
387388
# VM Setup
388389
# -----------------------
390+
image_url = identify_matching_qcow_image(server_session, "x86_64", "9", "https://cloud.centos.org/centos/9-stream/x86_64/images/", version_constraints=version_constraints)
391+
logger.info("Image URL: %s", image_url)
392+
389393
logger.info("Setting up VM on baremetal node: %s", server_node)
390394
vm = VMManager(
391395
session=server_session,
392396
workspace=server_workspace,
393397
vm_name=vm_name,
394-
image_url="https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-x86_64-9-20251117.0.x86_64.qcow2",
395-
image_name="CentOS-Stream-GenericCloud-x86_64-9-20251117.0.x86_64.qcow2",
398+
image_url=image_url,
399+
image_name=image_url.split("/")[-1],
396400
vm_cpu="2",
397401
vm_ram="8192",
398402
vm_disk="30G",

0 commit comments

Comments
 (0)