From d457a617ee3b7b53f2edfc07d0cf83e68bcc977a Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Fri, 22 May 2026 12:29:38 +0200 Subject: [PATCH 1/3] kt vm: Use different qcow images for rocky kernels based on minor versions as well. Rocky 9.4 will use a 9.4 base instead of the latest rocky 9 base. Same for the other kernels. Signed-off-by: Roxana Nicolescu --- kt/KT.md | 4 ++-- kt/ktlib/util.py | 4 ++-- kt/ktlib/vm.py | 26 ++++++++++++++++++++------ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/kt/KT.md b/kt/KT.md index 9a66386..1d3aed8 100644 --- a/kt/KT.md +++ b/kt/KT.md @@ -261,10 +261,10 @@ For this configuration } ``` -Here is the qcow2 vm image used as source for other vms as well: +Here is the qcow2 vm image used as source for other vms for 9.4 kernels as well: ``` -~/ciq/default_test_images/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2 +~/ciq/default_test_images/Rocky-9.4-GenericCloud.latest.x86_64.qcow2 ``` And here are the actual vm configuration and image files: diff --git a/kt/ktlib/util.py b/kt/ktlib/util.py index 784271e..8284970 100644 --- a/kt/ktlib/util.py +++ b/kt/ktlib/util.py @@ -7,8 +7,8 @@ class Constants: COMMON_REPOS = "common_repos" KERNELS = "kernels" - BASE_URL = "https://download.rockylinux.org/pub/rocky" - QCOW2_TRAIL = "GenericCloud-Base.latest.x86_64.qcow2" + BASE_URL = "https://dl.rockylinux.org/vault/rocky" + QCOW2_TRAIL = "GenericCloud.latest.x86_64.qcow2" DEFAULT_VM_BASE = "Rocky" CLOUD_INIT = "cloud_init.yaml" diff --git a/kt/ktlib/vm.py b/kt/ktlib/vm.py index b6d7c84..ec1adbc 100644 --- a/kt/ktlib/vm.py +++ b/kt/ktlib/vm.py @@ -31,12 +31,14 @@ class Vm: qcow2_source_path: qcow2 path to the vm image used as source vm_major_version: major vm version (9 for Rocky 9) + vm_major_version: major.minor vm version (9.2 for Rocky 9.2) qcow2_path: the qcow2 path of the vm image copied from qcow2_source_path cloud_init_path: cloud_init.yaml config, adapted from data/cloud_init.yaml """ qcow2_source_path: Path vm_major_version: str + vm_major_minor_version: str qcow2_path: Path cloud_init_path: Path name: str @@ -47,9 +49,12 @@ def load(cls, config: Config, kernel_workspace: KernelWorkspace): kernel_workspace_str = kernel_workspace.folder.name kernel_name = cls._extract_kernel_name(kernel_workspace_str) vm_major_version = cls._extract_major(kernel_name) + vm_major_minor_version = cls._extract_major_minor(kernel_name) # Image source paths construction - qcow2_source_path = config.images_source_dir / Path(cls._qcow2_name(vm_major_version=vm_major_version)) + qcow2_source_path = config.images_source_dir / Path( + cls._qcow2_name(vm_major_minor_version=vm_major_minor_version) + ) # Actual current image paths construction work_dir = config.images_dir / Path(kernel_workspace_str) @@ -59,6 +64,7 @@ def load(cls, config: Config, kernel_workspace: KernelWorkspace): return cls( qcow2_source_path=qcow2_source_path, vm_major_version=vm_major_version, + vm_major_minor_version=vm_major_minor_version, qcow2_path=qcow2_path, cloud_init_path=cloud_init_path, name=kernel_workspace_str, @@ -76,8 +82,13 @@ def _extract_major(cls, full_version): return full_version.split("-")[-1].split(".")[0] @classmethod - def _qcow2_name(cls, vm_major_version: str): - return f"{Constants.DEFAULT_VM_BASE}-{vm_major_version}-{Constants.QCOW2_TRAIL}" + def _extract_major_minor(cls, full_version): + # lts-9.4 -> return 9.4 + return full_version.split("-")[-1] + + @classmethod + def _qcow2_name(cls, vm_major_minor_version: str): + return f"{Constants.DEFAULT_VM_BASE}-{vm_major_minor_version}-{Constants.QCOW2_TRAIL}" @classmethod def load_from_workspace(cls, kernel_workspace_name: str): @@ -121,7 +132,7 @@ def setup_and_spinup(cls, kernel_workspace_name: str, override: bool = False, vc return vm_instance def _get_vm_url(self): - return f"{Constants.BASE_URL}/{self.vm_major_version}/images/x86_64/{self.qcow2_source_path.name}" + return f"{Constants.BASE_URL}/{self.vm_major_minor_version}/images/x86_64/{Constants.DEFAULT_VM_BASE}-{self.vm_major_version}-{Constants.QCOW2_TRAIL}" def _download_source_image(self): if self.qcow2_source_path.exists(): @@ -131,8 +142,11 @@ def _download_source_image(self): # Make sure the folder exists self.qcow2_source_path.parent.mkdir(parents=True, exist_ok=True) - logging.info("Downloading image") - wget.download(self._get_vm_url(), out=str(self.qcow2_source_path.parent)) + # Delete existing image if it exists + self.qcow2_source_path.unlink(missing_ok=True) + + logging.info(f"Downloading image from {self._get_vm_url()}") + wget.download(self._get_vm_url(), out=str(self.qcow2_source_path)) def _setup_cloud_init(self, config: Config): data = None From 0957c1b0ab2947a9ee973b1c8f0aa2b849b1f5ce Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Fri, 22 May 2026 12:32:56 +0200 Subject: [PATCH 2/3] kt vm: Introduce --override-base This will destroy the vm first if it already exists, but it will also delete the base image from and download it again, instead of reusing the same base. Signed-off-by: Roxana Nicolescu --- kt/commands/vm/command.py | 17 +++++++++++++++-- kt/commands/vm/impl.py | 5 ++++- kt/ktlib/vm.py | 22 +++++++++++++++------- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/kt/commands/vm/command.py b/kt/commands/vm/command.py index 8ba2eff..ad3d2e6 100644 --- a/kt/commands/vm/command.py +++ b/kt/commands/vm/command.py @@ -17,6 +17,12 @@ cloud-init.yaml configuration is taken from kt/data and modified accordingly for each user and then put in the same folder. +If the base image exists at , it will be reused +forever, unless parameter --override-base is used to download the +base image and replace it. Note, this won't interfere with existing +vms that share the same base because their own image is copied in their +own / folder. + Examples: \b @@ -29,7 +35,8 @@ $ kt vm lts9_4 --destroy \b $ kt vm lts9_4 -c --override - +\b +$ kt vm lts9_4 -c --override-base """ @@ -51,6 +58,11 @@ is_flag=True, help="It destroys the vm if it exists and creates a new one", ) +@click.option( + "--override-base", + is_flag=True, + help="It destroys the vm if it exists and creates a new one, but it will also override the base qcow image", +) @click.option( "--list-all", is_flag=True, @@ -60,7 +72,7 @@ @click.option("--vcpus", type=int, default=12, help="Number of virtual CPUs (default: 12)") @click.option("--memory", type=int, default=32768, help="Memory in MiB (default: 32768)") @click.argument("kernel_workspace", required=False, shell_complete=ShellCompletion.show_kernel_workspaces) -def vm(kernel_workspace, console, destroy, override, list_all, test, vcpus, memory): +def vm(kernel_workspace, console, destroy, override, override_base, list_all, test, vcpus, memory): if not list_all and not kernel_workspace: raise click.UsageError("kernel_workspace is required unless --list-all is specified") @@ -69,6 +81,7 @@ def vm(kernel_workspace, console, destroy, override, list_all, test, vcpus, memo console=console, destroy=destroy, override=override, + override_base=override_base, list_all=list_all, test=test, vcpus=vcpus, diff --git a/kt/commands/vm/impl.py b/kt/commands/vm/impl.py index 3eec174..2c125fc 100644 --- a/kt/commands/vm/impl.py +++ b/kt/commands/vm/impl.py @@ -11,6 +11,7 @@ def main( console: bool, destroy: bool, override: bool, + override_base: bool, list_all: bool, test: bool = False, vcpus: int = 12, @@ -29,7 +30,9 @@ def main( vm.destroy() return - vm_instance = Vm.setup_and_spinup(kernel_workspace_name=name, override=override, vcpus=vcpus, memory=memory) + vm_instance = Vm.setup_and_spinup( + kernel_workspace_name=name, override=override, override_base=override_base, vcpus=vcpus, memory=memory + ) config = Config.load() if test: diff --git a/kt/ktlib/vm.py b/kt/ktlib/vm.py index ec1adbc..e09de8d 100644 --- a/kt/ktlib/vm.py +++ b/kt/ktlib/vm.py @@ -107,13 +107,21 @@ def load_from_workspace(cls, kernel_workspace_name: str): return cls.load(config=config, kernel_workspace=kernel_workspace) @classmethod - def setup_and_spinup(cls, kernel_workspace_name: str, override: bool = False, vcpus: int = 12, memory: int = 32768): + def setup_and_spinup( + cls, + kernel_workspace_name: str, + override: bool = False, + override_base: bool = False, + vcpus: int = 12, + memory: int = 32768, + ): """ Setup and spin up a VM from a kernel workspace name. Args: kernel_workspace_name: The name of the kernel workspace override: If True, destroy and recreate the VM + override_base: If True, destroy and recreate the VM but override the base image as well vcpus: Number of virtual CPUs memory: Memory in MiB @@ -123,10 +131,10 @@ def setup_and_spinup(cls, kernel_workspace_name: str, override: bool = False, vc vm = cls.load_from_workspace(kernel_workspace_name) config = Config.load() - if override: + if override or override_base: vm.destroy() - vm.setup(config=config) + vm.setup(override_base=override_base) vm_instance = vm.spin_up(config=config, vcpus=vcpus, memory=memory) return vm_instance @@ -134,8 +142,8 @@ def setup_and_spinup(cls, kernel_workspace_name: str, override: bool = False, vc def _get_vm_url(self): return f"{Constants.BASE_URL}/{self.vm_major_minor_version}/images/x86_64/{Constants.DEFAULT_VM_BASE}-{self.vm_major_version}-{Constants.QCOW2_TRAIL}" - def _download_source_image(self): - if self.qcow2_source_path.exists(): + def _download_source_image(self, override_base: bool = False): + if self.qcow2_source_path.exists() and not override_base: logging.info(f"Image {self.qcow2_source_path} already exists, nothing to do") return @@ -217,8 +225,8 @@ def _resize_disk(self): except RuntimeError as e: raise RuntimeError(f"Failed to resize disk image: {e}") - def setup(self, config: Config): - self._download_source_image() + def setup(self, override_base: bool = False): + self._download_source_image(override_base=override_base) def spin_up(self, config: Config, vcpus: int = 12, memory: int = 32768) -> VmInstance: if not VirtHelper.exists(vm_name=self.name): From 7523cafef3452cdd4a46abc428c75eaaeacfbca1 Mon Sep 17 00:00:00 2001 From: Roxana Nicolescu Date: Fri, 22 May 2026 12:55:16 +0200 Subject: [PATCH 3/3] kt: Fix typo in helpers and doc. Replaced lts9_4 as kernel parameter instead of lts-9.4. Signed-off-by: Roxana Nicolescu --- kt/KT.md | 6 +++--- kt/commands/checkout/command.py | 12 ++++++------ kt/commands/git_push/command.py | 10 +++++----- kt/commands/vm/command.py | 12 ++++++------ 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/kt/KT.md b/kt/KT.md index 1d3aed8..87b24eb 100644 --- a/kt/KT.md +++ b/kt/KT.md @@ -197,7 +197,7 @@ before creating it from scratch again. #### Example: ``` -$ kt checkout lts9_4 +$ kt checkout lts-9.4 ``` For this configuration @@ -212,7 +212,7 @@ For this configuration ``` This is the working directory for this kernel: -`~/ciq/kernels/lts9_4`. +`~/ciq/kernels/lts-9.4`. 2 git worktrees are created: @@ -247,7 +247,7 @@ $ sudo usermod -a -G libvirt $(whoami) #### Example: ``` -$ kt vm lts9_4 +$ kt vm lts-9.4 ``` For this configuration diff --git a/kt/commands/checkout/command.py b/kt/commands/checkout/command.py index f29e39f..d0d6a85 100644 --- a/kt/commands/checkout/command.py +++ b/kt/commands/checkout/command.py @@ -25,16 +25,16 @@ Examples: \b -$ kt checkout lts9_4 +$ kt checkout lts-9.4 \b -$ kt checkout lts9_4 --cleanup +$ kt checkout lts-9.4 --cleanup \b -$ kt checkout lts9_4 --cleanup -c +$ kt checkout lts-9.4 --cleanup -c \b -$ kt checkout lts9_4 --cleanup --change-dir +$ kt checkout lts-9.4 --cleanup --change-dir \b -$ kt checkout lts9_4 -e CVE-2022-49909 -Will create folder lts9_4_CVE-2022-49909 instead of lts9_4. +$ kt checkout lts-9.4 -e CVE-2022-49909 +Will create folder lts-9.4_CVE-2022-49909 instead of lts-9.4. """ diff --git a/kt/commands/git_push/command.py b/kt/commands/git_push/command.py index a5c3107..deecdf9 100644 --- a/kt/commands/git_push/command.py +++ b/kt/commands/git_push/command.py @@ -15,17 +15,17 @@ Examples: \b -$ kt git-push lts9_4 -k -Will push the branch {USER}_ciqlts9_4 from kernel-src-tree from lts9_4 kernel +$ kt git-push lts-9.4 -k +Will push the branch {USER}_ciqlts-9.4 from kernel-src-tree from lts-9.4 kernel workspace. \b -$ kt git-push lts9_4 -k -f +$ kt git-push lts-9.4 -k -f Same as above but it will force push \b -$ kt git-push lts9_4 -d -Will push the branch {USER}_lts94-9 from kernel-dist-tree from lts9_4 kernel +$ kt git-push lts-9.4 -d +Will push the branch {USER}_lts94-9 from kernel-dist-tree from lts-9.4 kernel workspace. """ diff --git a/kt/commands/vm/command.py b/kt/commands/vm/command.py index ad3d2e6..206050b 100644 --- a/kt/commands/vm/command.py +++ b/kt/commands/vm/command.py @@ -26,17 +26,17 @@ Examples: \b -$ kt vm lts9_4 +$ kt vm lts-9.4 \b -$ kt vm lts9_4 --console +$ kt vm lts-9.4 --console \b -$ kt vm lts9_4 -c +$ kt vm lts-9.4 -c \b -$ kt vm lts9_4 --destroy +$ kt vm lts-9.4 --destroy \b -$ kt vm lts9_4 -c --override +$ kt vm lts-9.4 -c --override \b -$ kt vm lts9_4 -c --override-base +$ kt vm lts-9.4 -c --override-base """