Skip to content

Conversation

@roxanan1996
Copy link
Contributor

ktools

Introduction of kt CLI command.

This command is uspposed to be the base of all commands used for kernel
development at CIQ.

To keep things clear, it is introduced as a separate module in
kernel-src-tree-tools and it does not interfere with the current tooling.
By keeping this under the same repo, it will be easier to refactor things.

Setup:

  1. Install dependencies globally (you can also create a venv) :
$ python -m pip install -e ".[dev]"
  1. The command above will install pre-commit. To setup the pre-commit tool
    before you commit something, run this:
$ pre-commit install

Implementation details:

kt/ktlib is the place for common helpers that would be used for kt commands.

kt/ktlib.config.py is where a Config dataclass is implemented. This is crucial
for future commands and for doing the setup of the kernel developer. At the
moment it contains absolute paths to local directories:

  • The working dir (the root directory for the setup)
  • The directory parent for each kernel directory
  • The parent directory where default images are downloaded
  • The parent directory where running vm images for each kernel are stored.

Each developer has to provide their own configuration in json file and keep
the path in KTOOLS_CONFIG_FILE. Otherwise a default one will be used.

Example content of the config file:

{
    "base_path": "~/ciq",
    "kernels_dir": "~/ciq/kernels",
    "images_source_dir": "~/ciq/default_test_images",
    "images_dir": "~/ciq/tmp/virt-images",
    "ssh_key": "~/.ssh/id_ed25519_generic.pub",
}

kt/ktlib/kernels.py is the python representation of the kernels.yaml
in kt/data folder. This should be the only source of truth for the kernels
we currently maintain. Ideally, this should be in its own repo, but to keep
things simple, it is part of the kt tool for the time being.

The information we store for each kernel is:

  • the kernel source tree (at the moment is the same for all)
  • the corresponding branch in the kernel source tree
  • the rocky staging rpm repo ( it can be lts, fips or cbr)
  • the corresponding branch in the rocky staging rpm repo as we support
    multiple lts and fips kernels

For example

kernels:
    cbr-7.9:
    src_tree_root: kernel-src-tree
    src_tree_branch: ciqcbr7_9
    dist_git_root: dist-git-tree-cbr
    dist_git_branch: cbr79-7

src_tree_root and dist_git_root are references to:

common_repos:
    dist-git-tree-cbr: git@gitlab.com:ctrl-iq/linux/centos/cbr/src/kernel.git
    dist-git-tree-lts: git@gitlab.com:ctrl-iq/linux/rocky/lts/src/kernel.git
    dist-git-tree-fips: git@gitlab.com:ctrl-iq/linux/rocky/fips/src/kernel.git
    kernel-src-tree: https://github.com/ctrliq/kernel-src-tree.git

A python dataclass KernelInfo that matches every kernel configuration is
introduced in kt/ktlib/kernels.py. The dataclass contains the absolute
path to the local clone of the repos, to make future work easier. And we
keep track of all kernels in KernelsInfo.

For example, based on the default configuration, the KernelInfo object for the above kernel
will contain the following:

- name: cbr-7.9
- src_tree_root: RepoInfo(~/ciq/kernel-src-tree, git@gitlab.com:ctrl-iq/linux/centos/cbr/src/kernel.git)
- src_tree_branch: ciqcbr7_9
- dist_git_root: RepoInfo(~/ciq/dist-git-tree-cbr, git@gitlab.com:ctrl-iq/linux/rocky/fips/src/kernel.git)
- dist_git_branch: cbr79-7

if the base_path is ~/ciq.

The KernelInfo dataclass will be used later when we set up each kernel working
environment.

Commands

Make sure kt is reachable from anywhere by adding it's location to PATH.
Example

export PATH=$HOME/ciq/kernel-src-tree-tools/bin:$PATH

If you are unsure how to use kt, just run it with --help.
Example:

$ kt --help

Run --help for subcommands as well.

Autocompletion works relatevely well. Make sure it's enabled for your shell.
Check the official doc for click
Example for zsh:

eval "$(_KT_COMPLETE=zsh_source kt)"

A command implementaion is under kt/commands/<command> folder.
To keep things cleaner, the actual logic is done in impl.py,
while command.py is used for the click interface, like argument and helper logic.

kt list-kernels

It shows the kernels we currently maintain. The data is taken from
KernelsInfo object which represents the kernels.yaml file in kt/data.

Example:

$ kt list-kernels
cbr-7.9
fips-8.10
fips-8.6
fips-9.2
fipslegacy-8.6
lts-8.6
lts-8.8
lts-9.2
lts-9.4

kt setup

$ kt setup --help

It prepares the working directory for later commands:

It clones the common_repos from kernels.yaml file in the config.base_path
directory.
If config.base_path = ~/ciq, these will be created:

~/ciq/kernel-src-tree

~/ciq/dist-git-tree-fips

~/ciq/dist-git-tree-cbr

~/ciq/dit-git-tree-lts

~/ciq/kernel-src-tree-tools

~/ciq/kernel-tools

If there's a repo that needs to be cloned relevant for any future command,
this is when it should be cloned.

kt checkout

Prepares the working directory for a kernel.
It uses the KernelInfo dataclass created based on the kernels.yaml file.

The working directory location is based on configuration:
<config.kernels_dir>/<kernel>/

2 git worktrees are created for a kernel:

  • kernel-dist-git

  • kernel-src-tree

They will point out to their root sources. Check kt setup for more info.
They should be located in <config.base_path>.
The worktrees reference the remote from kernels.yaml.
The local branch is {<user>}/<branch>.

If --change-dir or -c option is used, it will also go to the working
directory of the kernel.

If --cleanup option is used, it will delete the worktree and the local branch
before creating it from scratch again.

Example:

$ kt checkout lts9_4

For this configuration

{
    "base_path": "~/ciq",
    "kernels_dir": "~/ciq/kernels",
    "images_source_dir": "~/ciq/default_test_images",
    "images_dir": "~/ciq/tmp/virt-images",
    "ssh_key": "~/.ssh/id_ed25519_generic.pub",
}

This is the working directory for this kernel:
~/ciq/kernels/lts9_4.

2 git worktrees are created:

  1. kernel-dist-git

    This representes branch {<user>}/lts9_4:origin/lts9_4.
    The source repo is ~/ciq/dist-git-tree-lts

  2. kernel-src-tree

    This representes branch {<user>}/ciqlts9_4:origin/ciqlts9_4
    The source repo is ~/ciq/kernel-src-tree

kt vm

It spins up a virtual machine for the corresponding kernel.
If the virtual machine does not exist, it gets created.

First, the vm image base (source) is downloaded if it does not exist
in <config.images_source_dir>.
To spin up the machine, a copy of this qcow2 image is put in
<config.images_dir/. Even if kernels may share the same image base,
they will have their own configuration and image.
cloud-init.yaml configuration is taken from kt/data and modified accordingly
for each user and then put in the same folder.

Make sure your user is part of the libvirt group, otherwise you would need
to type your root password multiple times when getting access to the vm:

$ sudo usermod -a -G libvirt $(whoami)

Example:

$ kt vm lts9_4

For this configuration

{
    "base_path": "~/ciq",
    "kernels_dir": "~/ciq/kernels",
    "images_source_dir": "~/ciq/default_test_images",
    "images_dir": "~/ciq/tmp/virt-images",
    "ssh_key": "~/.ssh/id_ed25519_generic.pub",
}

Here is the qcow2 vm image used as source for other vms as well:

~/ciq/default_test_images/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2

And here are the actual vm configuration and image files:

ciq/tmp/virt-images/lts-9.4/cloud-init.yaml
ciq/tmp/virt-images/lts-9.4/lts-9.4.qcow2

The cloud-init.yaml file is adapted from kt/data/cloud-init.yaml base file.

virt-install command is then used to create the vm.

If --console option is used, then virsh --connect qemu://system console lts9-4
is run (indirectly).

If --test option is used, then we connect to the vm via ssh and run

<config.base_path>/kernel-src-tree-tools/kernel-build.sh -n

reboot
and then

<config.base_path>/kernel-src-tree-tools/kernel-kselftest.sh

Copilot AI review requested due to automatic review settings January 20, 2026 15:24
@roxanan1996 roxanan1996 self-assigned this Jan 20, 2026
@roxanan1996 roxanan1996 marked this pull request as draft January 20, 2026 15:24
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces the KT CLI tool, a comprehensive command-line interface for kernel development workflows at CIQ. The tool provides commands for managing kernel workspaces, setting up development environments, managing virtual machines, and handling git operations across multiple kernel branches.

Changes:

  • New kt/ Python package with library code for configuration, kernel management, git operations, and VM management
  • Five CLI commands: list-kernels, setup, checkout, git-push, and vm
  • Refactored shell scripts to separate dependency installation logic into a standalone script
  • Test coverage for configuration and kernel management modules

Reviewed changes

Copilot reviewed 27 out of 28 changed files in this pull request and generated 25 comments.

Show a summary per file
File Description
bin/kt Main CLI entry point that registers all subcommands
kt/ktlib/*.py Core library modules for config, kernels, repos, workspaces, VMs, SSH, and command execution
kt/commands/*/ Command implementations for list-kernels, setup, checkout, git-push, and vm operations
kt/data/ YAML configuration files for kernel definitions and cloud-init templates
tests/kt/ktlib/ Unit tests for configuration and kernel management
pyproject.toml Project dependencies and packaging configuration
kernel_kselftest.sh Refactored to use separate dependency installation script
kernel_install_dep.sh New script containing dependency installation logic
kt/KT.md Comprehensive documentation for the KT tool

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

It uses click for handling arguments.

Kt implementation is done under its own folder.
It is considered as a submodule for kernel-src-tree-tools for the time
being. And it does not interfere with the rest of our tooling.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Add dataclass Config that would contain the basic configuration for each
kernel developer. It mainly consists of directories path that will be
used do the working setup later.

The configuration is read from a json file. The json file name is stored
in an environment variable "KTOOLS_CONFIG_FILE". If the variable is not
set, or the file does not exists or the format is not correct, it will
use a default configuration.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
kt/data/kernels.yaml is the source of truth for all the kernels we support.
The information we store for each kernel is:
- the kernel source tree (at the moment is the same for all)
- the corresponding branch in the kernel source tree
- the rocky staging rpm repo ( it can be lts, fips or cbr)
- the corresponding branch in the rocky staging rpm repo as we support
 multiple lts and fips kernels

A python dataclass KernelInfo that matches every kernel configuration is
 introduced in kt/ktlib/kernels.py. The dataclass contains the absolute
path to the local clone of the repos, to make future work easier. And we
keep track of all kernels in KernelsInfo.

Note: kt/data folder should be moved to a separate repo in the future.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
It will show all the kernels we support.

The implementation is under kt/commands/list-kernels folder.
To keep things cleaner, the actual logic is done in impl.py,
while command.py is used for the click interface, like argument and helper logic.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Usage: kt setup --help

It will clone all the repos a developer needs for kernel development.

It clones the common_repos from kernels.yaml file in the config.base_path
directory.
If config.base_path = ~/ciq, these will be created:

~/ciq/kernel-src-tree
~/ciq/dist-git-tree-fips
~/ciq/dist-git-tree-cbr
~/ciq/dit-git-tree-lts
~/ciq/kernel-src-tree-tools
~/ciq/kernel-tools

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Usage: kt checkout <kernel>

This will set up the working directory for a kernel.
It will create git worktrees for dist-git-tree and kernel-src-tree repos.
If used if the working directory for a kernel is created,
the two git worktrees are updated.

An --extra option was added if people need 2 working environments for the
same kernel at the same time.

Example without --extra:

$ kt checkout lts9-2
Output:
$KERNELS_DIR/lts-9.2 will be created with 2 git worktrees:
kernel-src-tree -- for branch {USER}/ciqlts9_2
kernel-dist-git -- for branch {USER}/ciqlts9_2

Example with --extra:

$ kt checkout lts9-2 --extra CVE_X
Output:
$KERNELS_DIR/lts-9.2_CVE_X will be created with 2 git worktrees:
kernel-src-tree -- for branch {USER}/ciqlts9_2_CVE_X
kernel-dist-git -- for branch {USER}/ciqlts9_2_CVE_X

TODO: Autocomplete suggests only the kernel in data/kernels.yaml, not the
kernel workspace at the moment. This will be improved later, since
kt checkout may be used to just update en existing kernel workspace.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Pushes the local branch for either the kernel-src-tree or the kernel-dist-tree
for the kernel workspaces selected.
Useful especially if the branch you try to push is long and the remote
is not selected.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
Used to install dependencies needed to operate our kernels based on
rocky 8, 9 and 10. Needed before building the kernel and running the
kselftests.

This is separated from kernel_kselftest.sh because it is also needed
before building the kernel.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
This will create a vm for a kernel workspace created earlier with kt checkout.
If the vm does not exists, it will create it.

It includes options to get console access, to destroy the vm and list
the running vms.

The most relevant one is the --test option that builds the kernel
from kernel-src-tree of the matching kernel workspace, boots it and then
kselftests are run.

TODOs:
1. autocompletion work fine, except if --destroy is used.
Ideally when --destroy is used, only the running vms should be shown.
For now, please check the existing vms with kt vm --list-all
and then run kt vm --destroy <kernel_workspace>
2. The implementation replies a lot of waiting for the vm to boot up,
install depedencies etc. Hence the time.sleep() calls. It would be improved
in the future.

IMPORTANT:
The vm instance needs to have access to this repo because the scripts
for building the kernel, running the kselftests and installing depedencies.
We share <config.kernels_dir> with the vm, so please make sure this repo
is there. That's what the implementation assumes.

Note: Make sure your user is part of the libvirt group, otherwise
you will need to type the root password multiple times, because kt
calls virsh multiple times before getting access to a vm: for checking if
it exists etc.

Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
@roxanan1996 roxanan1996 force-pushed the {rnicolescu}_kt_intro branch from 99966ed to a9232b1 Compare January 21, 2026 15:11
@roxanan1996 roxanan1996 marked this pull request as ready for review January 21, 2026 16:42
Copilot AI review requested due to automatic review settings January 21, 2026 16:42
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants