Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ Welcome to the CIQ kernel-src-tree-tools package. This is a collection of script

These are just scripts we have used internally and have decided to share with the community to encourage other to contribute to our requirements more easily.

## KT (Kernel Tools)
In this repo there is a directory called `KT` which contains a "kernel tools"
python package that should be installed into your python environment. Its purpose
is to consolidate all of the one off or single purpose scripts to share more
common code and functionality. Please see the KT directions in KT/kt.md for
setup directions.
Comment on lines +7 to +11

## ciq-cherry-pick
This script is used to cherry-pick a commit from a remote repository to the current branch.
It is a wrapper around `git cherry-pick -nsx <sha>` command but sets up the incoming commit with the header information we require.
Expand Down
5 changes: 3 additions & 2 deletions kernel_install_dep.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,13 @@ install_kselftest_deps_8() {
traceroute \
wget

# Doesn't work for 8.6?
# Not available on all 8.x minor releases
sudo dnf -y install --enablerepo=devel \
fuse-devel \
gcc-toolset-13-libasan-devel \
glibc-static \
kernel-selftests-internal
kernel-selftests-internal \
|| echo "Optional packages not available or install failed; continuing."

pip3 install --user \
jsonschema \
Expand Down
58 changes: 55 additions & 3 deletions kt/KT.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,68 @@ 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) :
1. Install dependencies globally (you can also create a venv) in the repository
root directory:
```
$ python -m pip install -e ".[dev]"
[kernel-src-tree-tools]$ python -m pip install -e ".[dev]"
```
2. The command above will install pre-commit. To setup the pre-commit tool
before you commit something, run this:
```
$ pre-commit install
[kernel-src-tree-tools]$ pre-commit install
```

3. Set up the configuration file for kt.
There is a default one in kt/data/config.json but you can create your own by
defining the KTOOLS_CONFIG_FILE enviroment varriable to point to your own config
file.
Comment on lines +26 to +28
```bash
$ echo $KTOOLS_CONFIG_FILE
/home/jmaple/.config/kt/test_config.json

(.venv) [jmaple@devbox kernel-src-tree-tools]$ cat $KTOOLS_CONFIG_FILE
{
"base_path": "~/workspace/kt_test",
"kernels_dir": "~/workspace/kt_test/kernels",
"images_source_dir": "~/workspace/kt_test/images_source",
"images_dir": "~/workspace/kt_test/images",
"ssh_key": "~/.ssh/test.pub",
"user": "USER"
}
```
user defaults to $USER, set this if you wish for your user on the vms to be
different then define.
Comment on lines +43 to +44

4. Private Repos
By default, kt will use the public repos defined in kt/data/kernels.yaml. If
you have access to our private repos, you can create a .private_repos.yaml in
the base_path directory and define the private repos and branches should they
differ from the public ones. For example:
```yaml
private_repos:
dist-git-tree-lts: <gitlab_private_repo_url>

kernel_override:
lts-9.2:
dist_git_branch: <private_branch>
dist_git_root: dist-git-tree-lts
```

Optional is if you have an active depot account you can define the channels you
wish to use for each kernel. For example:
```yaml
kernel_override:
lts-9.2:
dist_git_branch: <private_branch>
dist_git_root: dist-git-tree-lts
depot_channels:
- <channel_name>
```

5. Setup needs to be run first.
```bash
$ kt setup
```
## Implementation details:

kt/ktlib is the place for common helpers that would be used for kt commands.
Expand Down
3 changes: 2 additions & 1 deletion kt/commands/list_kernels/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ def main(automated: bool = False):

for k in sorted(kernels.values(), key=lambda k: k.name):
if not automated or k.automated:
print(k.name)
label = f"{k.name} (override)" if k.overridden else f"{k.name} (default)"
print(label)
Comment on lines +11 to +12
53 changes: 53 additions & 0 deletions kt/data/cloud_init_centos7.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#cloud-config
users:
- name: USER_PLACEHOLDER
sudo: ALL=(ALL) NOPASSWD:ALL
groups: mock
ssh_authorized_keys:
- SSH_KEY_PLACEHOLDER
chpasswd:
expire: false
list:
- USER_PLACEHOLDER:test

ssh_pwauth: true

# Ensure the system does not update on boot.
package_upgrade: False

mounts:
- - NFS_SOURCE_PLACEHOLDER
- SHARED_DIR_PLACEHOLDER
- nfs
- defaults
- - SHARED_DIR_PLACEHOLDER
- /var/lib/mock
- bind
- defaults,bind

# Change working directory after boot
write_files:
- path: /etc/profile.d/change_dir.sh
content: |
cd WORKING_DIR_PLACEHOLDER
permissions: '0644'

# if homedir already exists, cloud-init does nothing about it
# and then root is the owner
# workaround to change the owner to user
runcmd:
- - chown
- USER_PLACEHOLDER:USER_PLACEHOLDER
- HOMEDIR_PLACEHOLDER
- sudo sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/CentOS-*.repo
- sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/CentOS-*.repo
- sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/CentOS-*.repo
- [sudo, yum, install, -y, mock, git, vim]
- [sudo, yum, install, -y, ncurses-devel, make, gcc, bc, bison, flex, elfutils-libelf-devel, openssl-devel]
- [sudo, yum, update, -y]

power_state:
mode: reboot
message: "Rebooting after install"
timeout: 30
condition: true
26 changes: 12 additions & 14 deletions kt/data/kernels.yaml
Original file line number Diff line number Diff line change
@@ -1,49 +1,47 @@
common_repos:
dist-git-tree-fips: git@gitlab.com:ctrl-iq-public/fips/src/kernel.git
dist-git-tree: git@github.com:ciq-rocky-lts/kernel.git
kernel-src-tree: https://github.com/ctrliq/kernel-src-tree.git
kernel-src-tree-tools: https://github.com/ctrliq/kernel-src-tree-tools.git

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
dist_git_root: dist-git-tree
dist_git_branch: el-7.9
mock_config: centos-cbr79
automated: true
vm_image_url: https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud-2211.qcow2
os_variant: centos7
use_nfs: true

lts-8.6:
src_tree_root: kernel-src-tree
src_tree_branch: ciqlts8_6
dist_git_root: dist-git-tree-lts
dist_git_branch: lts86-8
dist_git_root: dist-git-tree
dist_git_branch: el-8.6
mock_config: rocky-lts86
automated: true
vm_image_url: https://dl.rockylinux.org/vault/rocky/8.6/images/Rocky-8-GenericCloud-8.6.20220702.0.x86_64.qcow2
depot_channels:
- lts-8.6

lts-9.2:
src_tree_root: kernel-src-tree
src_tree_branch: ciqlts9_2
dist_git_root: dist-git-tree-lts
dist_git_branch: lts92-9
dist_git_root: dist-git-tree
dist_git_branch: el-9.2
mock_config: rocky-lts92
automated: true
vm_image_url: https://dl.rockylinux.org/vault/rocky/9.2/images/x86_64/Rocky-9-GenericCloud-Base-9.2-20230513.0.x86_64.qcow2
depot_channels:
- lts-9.2

lts-9.6:
src_tree_root: kernel-src-tree
src_tree_branch: ciqlts9_6
dist_git_root: dist-git-tree-lts
dist_git_branch: lts96-9
dist_git_root: dist-git-tree
dist_git_branch: el-9.6
mock_config: rocky-lts96
automated: true
vm_image_url: https://dl.rockylinux.org/vault/rocky/9.6/images/x86_64/Rocky-9-GenericCloud-Base-9.6-20250531.0.x86_64.qcow2
depot_channels:
- lts-9.6

fipslegacy-8.6:
src_tree_root: kernel-src-tree
Expand Down
14 changes: 14 additions & 0 deletions kt/ktlib/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import os
import sys
import warnings
from dataclasses import dataclass
from typing import ClassVar, Optional
Expand Down Expand Up @@ -43,8 +44,21 @@ class Config:
"user": os.environ["USER"],
}

REQUIRED_KEYS: ClassVar = {"base_path", "kernels_dir", "images_source_dir", "images_dir", "ssh_key"}

@classmethod
def from_str_dict(cls, data: dict[str, str]):
missing = cls.REQUIRED_KEYS - data.keys()
if missing:
example = json.dumps(cls.DEFAULT, indent=2)
sys.exit(
f"Error: config is missing required keys:\n\t{', '.join(sorted(missing))}"
f"\n\nExample config (note user is optional):\n{example}"
)
Comment on lines +51 to +57

if "user" not in data:
data = {**data, "user": os.environ["USER"]}

# Transform the str values to Path except for user
non_path_keys = {"user"}
new_data = {k: (Path(v).expanduser() if k not in non_path_keys else v) for k, v in data.items()}
Expand Down
26 changes: 17 additions & 9 deletions kt/ktlib/kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class KernelInfo:

vm_image_url: str | None = None
depot_channels: list[str] | None = None
os_variant: str | None = None
use_nfs: bool = False
overridden: bool = False


@dataclass
Expand All @@ -49,17 +52,17 @@ class KernelsInfo:
repos: dict[str, RepoInfo]

@classmethod
def _load_private_repos(cls, config: Config) -> dict[str, str]:
"""Load private repository URLs from local config"""
def _load_private_config(cls, config: Config) -> tuple[dict[str, str], dict[str, dict]]:
"""Load private repository URLs and kernel overrides from local config"""
private_repos_path = config.base_path / Constants.PRIVATE_REPOS_CONFIG_FILE

Comment on lines +55 to 58
if not private_repos_path.exists():
logging.info(f"{private_repos_path} does not exist")
return {}
return {}, {}

with open(private_repos_path) as f:
data = yaml.safe_load(f)
return data.get("private_repos", {})
return data.get("private_repos", {}), data.get("kernel_overrides", {})
Comment on lines 63 to +65

@classmethod
def _get_repos(cls, data: dict, private_data: dict, config: Config):
Expand All @@ -83,8 +86,9 @@ def _get_repos(cls, data: dict, private_data: dict, config: Config):
return repos

@classmethod
def _get_kernels_info(cls, data: dict, repos: dict[str, RepoInfo]):
def _get_kernels_info(cls, data: dict, repos: dict[str, RepoInfo], kernel_overrides: dict[str, dict] = None):
kernels_info = {}
kernel_overrides = kernel_overrides or {}

try:
items = data[Constants.KERNELS].items()
Expand All @@ -94,6 +98,10 @@ def _get_kernels_info(cls, data: dict, repos: dict[str, RepoInfo]):
for kernel, info in items:
k_info_dict = {"name": kernel, **info}

if kernel in kernel_overrides:
k_info_dict.update(kernel_overrides[kernel])
k_info_dict["overridden"] = True

# Make the src_tree_root and dist_git_root absolute paths to the
# local clone of these repos (transformation from src to Path)
# repos dictionary contains the proper absolute paths
Expand Down Expand Up @@ -129,13 +137,13 @@ def from_yaml(cls, config: Config):
with open(KERNEL_INFO_YAML_PATH) as f:
data = yaml.safe_load(f)

private_data = cls._load_private_repos(config=config)
private_data, kernel_overrides = cls._load_private_config(config=config)

return cls.from_dict(data=data, private_data=private_data, config=config)
return cls.from_dict(data=data, private_data=private_data, config=config, kernel_overrides=kernel_overrides)

@classmethod
def from_dict(cls, data: dict, private_data: dict, config: Config):
def from_dict(cls, data: dict, private_data: dict, config: Config, kernel_overrides: dict[str, dict] = None):
repos = cls._get_repos(data=data, private_data=private_data, config=config)
kernels_info = cls._get_kernels_info(data=data, repos=repos)
kernels_info = cls._get_kernels_info(data=data, repos=repos, kernel_overrides=kernel_overrides)

return cls(kernels=kernels_info, repos=repos)
3 changes: 3 additions & 0 deletions kt/ktlib/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ class Constants:
DEFAULT_VM_BASE = "Rocky"

CLOUD_INIT = "cloud_init.yaml"
LIBVIRT_HOST_IP = "192.168.122.1"

VM_STARTUP_WAIT_SECONDS = 60
VM_REBOOT_WAIT_SECONDS = 120
VM_POLL_INTERVAL_SECONDS = 15
VM_POLL_MAX_ATTEMPTS = 20
20 changes: 13 additions & 7 deletions kt/ktlib/virt.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,19 @@ def install(
cls,
name: str,
qcow2_path: Path,
vm_major_version: str,
os_variant: str,
cloud_init_path: Path,
common_dir: Path,
vcpus: int = 12,
memory: int = 32768,
use_nfs: bool = False,
):
command = [
"--name",
name,
"--disk",
f"{qcow2_path},device=disk,bus=virtio",
f"--os-variant=rocky{vm_major_version}",
f"--os-variant={os_variant}",
"--virt-type",
"kvm",
"--vcpus",
Expand All @@ -59,13 +60,18 @@ def install(
"--vnc",
"--cloud-init",
f"user-data={cloud_init_path}",
"--filesystem",
f"source={common_dir},target=mount_tag_mock_scratch,accessmode=passthrough,driver.type=virtiofs,driver.queue=1024,binary.path=/usr/libexec/virtiofsd,binary.xattr=on",
"--memorybacking",
"source.type=memfd,access.mode=shared",
"--noautoconsole",
]

if not use_nfs:
command += [
"--filesystem",
f"source={common_dir},target=mount_tag_mock_scratch,accessmode=passthrough,driver.type=virtiofs,driver.queue=1024,binary.path=/usr/libexec/virtiofsd,binary.xattr=on",
"--memorybacking",
"source.type=memfd,access.mode=shared",
]

command.append("--noautoconsole")

cls.run(command_type=VmCommandType.VIRT_INSTALL, command=command)

@classmethod
Expand Down
Loading