Skip to content

Commit

Permalink
Refactor KMT tasks (#21283)
Browse files Browse the repository at this point in the history
Refactor KMT tasks
  • Loading branch information
usamasaqib authored Jan 5, 2024
1 parent 09d7fd6 commit f0bec52
Show file tree
Hide file tree
Showing 13 changed files with 592 additions and 584 deletions.
97 changes: 97 additions & 0 deletions tasks/kernel_matrix_testing/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from .kmt_os import get_kmt_os
from .stacks import find_ssh_key
from .tool import Exit, error, info


class CommandRunner:
def __init__(self, ctx, local, vm, remote_ip, remote_ssh_key, log_debug):
self.local = local
self.remote_ip = remote_ip
self.remote_ssh_key = ssh_key_to_path(remote_ssh_key)
self.vm = vm
self.ctx = ctx
self.log_debug = log_debug

def run_cmd(self, cmd, allow_fail=False, verbose=False):
log_debug = self.log_debug or verbose
info(f"[+] {self.vm.ip} -> {cmd}")
if self.vm.arch == "local":
res = run_cmd_local(self.ctx, cmd, self.vm.ip, log_debug)
else:
res = run_cmd_remote(self.ctx, cmd, self.remote_ip, self.vm.ip, self.remote_ssh_key, log_debug)

if not res.ok:
error(f"[-] Failed: {self.vm.ip} -> {cmd}")
if not allow_fail:
print_failed(res.stderr)
raise Exit("command failed")

def copy_files(self, path, dest=None):
if self.vm.arch == "local" and dest is None:
self.ctx.run(f"cp {path} {get_kmt_os().shared_dir}")
elif self.vm.arch == "local" and dest is not None:
self.ctx.run(
f"scp -o StrictHostKeyChecking=no -i /home/kernel-version-testing/ddvm_rsa {path} root@{self.vm.ip}:{dest}"
)
else:
if self.remote_ssh_key == "" or self.remote_ip == "":
raise Exit("remote ssh key and remote ip are required to run command on remote VMs")
self.run_cmd(
f"scp -o StrictHostKeyChecking=no -i {self.remote_ssh_key} {path} ubuntu@{self.remote_ip}:/opt/kernel-version-testing/",
False,
)

def sync_source(self, source, target):
sync_source(self.ctx, source, target, self.remote_ip, self.remote_ssh_key, self.vm.ip, self.vm.arch)


def sync_source(ctx, source, target, instance_ip, ssh_key, ip, arch):
kmt_dir = get_kmt_os().kmt_dir
vm_copy = f"rsync -e \\\"ssh -o StrictHostKeyChecking=no -i {kmt_dir}/ddvm_rsa\\\" --chmod=F644 --chown=root:root -rt --exclude='.git*' --filter=':- .gitignore' ./ root@{ip}:{target}"
if arch == "local":
ctx.run(
f"rsync -e \"ssh -o StrictHostKeyChecking=no -i {kmt_dir}/ddvm_rsa\" -p --chown=root:root -rt --exclude='.git*' --filter=':- .gitignore' {source} root@{ip}:{target}"
)
elif arch == "x86_64" or arch == "arm64":
ctx.run(
f"rsync -e \"ssh -o StrictHostKeyChecking=no -i {ssh_key}\" -p --chown=root:root -rt --exclude='.git*' --filter=':- .gitignore' {source} ubuntu@{instance_ip}:/home/ubuntu/datadog-agent"
)
ctx.run(
f"ssh -i {ssh_key} -o StrictHostKeyChecking=no ubuntu@{instance_ip} \"cd /home/ubuntu/datadog-agent && {vm_copy}\""
)
else:
raise Exit(f"Unsupported arch {arch}")


def run_cmd_local(ctx, cmd, ip, log_debug):
return ctx.run(
f"ssh -o StrictHostKeyChecking=no -i /home/kernel-version-testing/ddvm_rsa root@{ip} '{cmd}'",
warn=True,
hide=(not log_debug),
)


def run_cmd_remote(ctx, cmd, remote_ip, ip, ssh_key, log_debug):
if ssh_key == "" or remote_ip == "":
raise Exit("remote ssh key and remote ip are required to run command on remote VMs")
return ctx.run(
f"ssh -o StrictHostKeyChecking=no -i {ssh_key} ubuntu@{remote_ip} \"ssh -o StrictHostKeyChecking=no -i /home/kernel-version-testing/ddvm_rsa root@{ip} '{cmd}'\"",
warn=True,
hide=(not log_debug),
)


def print_failed(output):
out = list()
for line in output.split("\n"):
out.append(f"\t{line}")
error('\n'.join(out))


def ssh_key_to_path(ssh_key):
ssh_key_path = ""
if ssh_key != "":
ssh_key.rstrip(".pem")
ssh_key_path = find_ssh_key(ssh_key)

return ssh_key_path
44 changes: 44 additions & 0 deletions tasks/kernel_matrix_testing/compiler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
def compiler_built(ctx):
res = ctx.run("docker images kmt:compile | grep -v REPOSITORY | grep kmt", warn=True)
return res.ok


def docker_exec(ctx, cmd, user="compiler", verbose=True, run_dir=None):
if run_dir:
cmd = f"cd {run_dir} && {cmd}"

ctx.run(f"docker exec -u {user} -i kmt-compiler bash -c \"{cmd}\"", hide=(not verbose))


def start_compiler(ctx):
if not compiler_built(ctx):
build_compiler(ctx)

if compiler_running(ctx):
ctx.run("docker rm -f $(docker ps -aqf \"name=kmt-compiler\")")

ctx.run(
"docker run -d --restart always --name kmt-compiler --mount type=bind,source=./,target=/datadog-agent kmt:compile sleep \"infinity\""
)

uid = ctx.run("getent passwd $USER | cut -d ':' -f 3").stdout.rstrip()
gid = ctx.run("getent group $USER | cut -d ':' -f 3").stdout.rstrip()
docker_exec(ctx, f"getent group {gid} || groupadd -f -g {gid} compiler", user="root")
docker_exec(ctx, f"getent passwd {uid} || useradd -m -u {uid} -g {gid} compiler", user="root")
docker_exec(ctx, f"chown {uid}:{gid} /datadog-agent && chown -R {uid}:{gid} /datadog-agent", user="root")
docker_exec(ctx, "apt install sudo", user="root")
docker_exec(ctx, "usermod -aG sudo compiler && echo 'compiler ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers", user="root")
docker_exec(ctx, f"install -d -m 0777 -o {uid} -g {uid} /go", user="root")


def compiler_running(ctx):
res = ctx.run("docker ps -aqf \"name=kmt-compiler\"")
if res.ok:
return res.stdout.rstrip() != ""
return False


def build_compiler(ctx):
ctx.run("docker rm -f $(docker ps -aqf \"name=kmt-compiler\")", warn=True, hide=True)
ctx.run("docker image rm kmt:compile", warn=True, hide=True)
ctx.run("cd ../datadog-agent-buildimages && docker build -f system-probe_x64/Dockerfile -t kmt:compile .")
49 changes: 49 additions & 0 deletions tasks/kernel_matrix_testing/ddvm_rsa
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
116 changes: 58 additions & 58 deletions tasks/kernel_matrix_testing/download.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import filecmp
import json
import os
import platform
import tempfile
Expand All @@ -11,56 +12,21 @@
except ImportError:
requests = None

url_base = "https://dd-agent-omnibus.s3.amazonaws.com/kernel-version-testing/rootfs/"
rootfs_amd64 = {
"custom-bullseye.amd64.qcow2",
"custom-buster.amd64.qcow2",
"jammy-server-cloudimg-amd64.qcow2",
"focal-server-cloudimg-amd64.qcow2",
"bionic-server-cloudimg-amd64.qcow2",
"amzn2-kvm-2.0-amd64-4.14.qcow2",
"amzn2-kvm-2.0-amd64-5.4.qcow2",
"amzn2-kvm-2.0-amd64-5.10.qcow2",
"amzn2-kvm-2.0-amd64-5.15.qcow2",
"Fedora-Cloud-Base-35.amd64.qcow2",
"Fedora-Cloud-Base-36.amd64.qcow2",
"Fedora-Cloud-Base-37.amd64.qcow2",
"Fedora-Cloud-Base-38.amd64.qcow2",
"debian-10-generic-amd64.qcow2",
"debian-11-generic-amd64.qcow2",
}

rootfs_arm64 = {
"custom-bullseye.arm64.qcow2",
"jammy-server-cloudimg-arm64.qcow2",
"focal-server-cloudimg-arm64.qcow2",
"bionic-server-cloudimg-arm64.qcow2",
"amzn2-kvm-2.0-arm64-4.14.qcow2",
"amzn2-kvm-2.0-arm64-5.4.qcow2",
"amzn2-kvm-2.0-arm64-5.10.qcow2",
"amzn2-kvm-2.0-arm64-5.15.qcow2",
"Fedora-Cloud-Base-35.arm64.qcow2",
"Fedora-Cloud-Base-36.arm64.qcow2",
"Fedora-Cloud-Base-37.arm64.qcow2",
"Fedora-Cloud-Base-38.arm64.qcow2",
"debian-10-generic-arm64.qcow2",
"debian-11-generic-arm64.qcow2",
}
platforms_file = "test/new-e2e/system-probe/config/platforms.json"
vmconfig_file = "test/new-e2e/system-probe/config/vmconfig.json"

archs_mapping = {
arch_mapping = {
"amd64": "x86_64",
"x86": "x86_64",
"x86_64": "x86_64",
"arm64": "arm64",
"aarch64": "arm64",
"arm": "arm64",
"local": "local",
"aarch64": "arm64",
}
karch_mapping = {"x86_64": "x86", "arm64": "arm64"}


def requires_update(rootfs_dir, image):
sum_url = url_base + image + ".sum"
def requires_update(url_base, rootfs_dir, image):
sum_url = os.path.join(url_base, "master", image + ".sum")
r = requests.get(sum_url)
new_sum = r.text.rstrip().split(' ')[0]
debug(f"[debug] new_sum: {new_sum}")
Expand All @@ -77,23 +43,47 @@ def requires_update(rootfs_dir, image):


def download_rootfs(ctx, rootfs_dir, backup_dir, revert=False):
with open(platforms_file) as f:
platforms = json.load(f)

with open(vmconfig_file) as f:
vmconfig_template = json.load(f)

url_base = platforms["url_base"]

arch = arch_mapping[platform.machine()]
to_download = list()
if archs_mapping[platform.machine()] == "x86_64":
file_ls = rootfs_amd64
else:
file_ls = rootfs_arm64
file_ls = list()
for tag in platforms[arch]:
path = os.path.basename(platforms[arch][tag])
if path.endswith(".xz"):
path = path[: -len(".xz")]

file_ls.append(os.path.basename(path))

# if file does not exist download it.
for f in file_ls:
path = os.path.join(rootfs_dir, f)
if not os.path.exists(path):
to_download.append(f)

disks_to_download = list()
for vmset in vmconfig_template["vmsets"]:
if vmset["arch"] != arch:
continue

for disk in vmset["disks"]:
d = os.path.basename(disk["source"])
if not os.path.exists(os.path.join(rootfs_dir, d)):
disks_to_download.append(d)

# download and compare hash sums
present_files = list(set(file_ls) - set(to_download))
present_files = list(set(file_ls) - set(to_download)) + disks_to_download
for f in present_files:
if requires_update(rootfs_dir, f):
if requires_update(url_base, rootfs_dir, f):
debug(f"[debug] updating {f} from S3.")
ctx.run(f"rm -f {f}")
ctx.run(f"rm -f {f}.sum")
to_download.append(f)

if len(to_download) == 0:
Expand All @@ -106,18 +96,21 @@ def download_rootfs(ctx, rootfs_dir, backup_dir, revert=False):
with os.fdopen(fd, 'w') as tmp:
for f in to_download:
info(f"[+] {f} needs to be downloaded")
# remove this file
ctx.run(f"rm -f {os.path.join(rootfs_dir, f)}")
xz = ".xz" if f not in disks_to_download else ""
filename = f"{f}{xz}"
sum_file = f"{f}.sum"
# remove this file and sum
ctx.run(f"rm -f {os.path.join(rootfs_dir, filename)}")
ctx.run(f"rm -f {os.path.join(rootfs_dir, sum_file)}")
# download package entry
tmp.write(url_base + f + "\n")
tmp.write(os.path.join(url_base, "master", filename) + "\n")
tmp.write(f" dir={rootfs_dir}\n")
tmp.write(f" out={f}\n")
tmp.write(f" out={filename}\n")
# download sum entry
tmp.write(url_base + f"{f}.sum\n")
tmp.write(os.path.join(url_base, "master", f"{sum_file}") + "\n")
tmp.write(f" dir={rootfs_dir}\n")
tmp.write(f" out={f}.sum\n")
tmp.write(f" out={sum_file}\n")
tmp.write("\n")

ctx.run(f"cat {path}")
res = ctx.run(f"aria2c -i {path} -j {len(to_download)}")
if not res.ok:
Expand All @@ -127,6 +120,13 @@ def download_rootfs(ctx, rootfs_dir, backup_dir, revert=False):
finally:
os.remove(path)

# extract files
res = ctx.run(f"find {rootfs_dir} -name \"*qcow2.xz\" -type f -exec xz -d {{}} \\;")
if not res.ok:
if revert:
revert_rootfs(ctx, rootfs_dir, backup_dir)
raise Exit("Failed to extract qcow2 files")

# set permissions
res = ctx.run(f"find {rootfs_dir} -name \"*qcow*\" -type f -exec chmod 0766 {{}} \\;")
if not res.ok:
Expand All @@ -136,15 +136,15 @@ def download_rootfs(ctx, rootfs_dir, backup_dir, revert=False):


def revert_kernel_packages(ctx, kernel_packages_dir, backup_dir):
arch = archs_mapping[platform.machine()]
arch = arch_mapping[platform.machine()]
kernel_packages_tar = f"kernel-packages-{arch}.tar"
ctx.run(f"rm -rf {kernel_packages_dir}/*")
ctx.run(f"mv {backup_dir}/{kernel_packages_tar} {kernel_packages_dir}")
ctx.run(f"tar xvf {kernel_packages_dir}/{kernel_packages_tar} | xargs -i tar xzf {{}}")


def download_kernel_packages(ctx, kernel_packages_dir, kernel_headers_dir, backup_dir, revert=False):
arch = archs_mapping[platform.machine()]
arch = arch_mapping[platform.machine()]
kernel_packages_sum = f"kernel-packages-{arch}.sum"
kernel_packages_tar = f"kernel-packages-{arch}.tar"

Expand Down Expand Up @@ -198,7 +198,7 @@ def download_kernel_packages(ctx, kernel_packages_dir, kernel_headers_dir, backu


def update_kernel_packages(ctx, kernel_packages_dir, kernel_headers_dir, backup_dir, no_backup):
arch = archs_mapping[platform.machine()]
arch = arch_mapping[platform.machine()]
kernel_packages_sum = f"kernel-packages-{arch}.sum"
kernel_packages_tar = f"kernel-packages-{arch}.tar"

Expand All @@ -213,7 +213,7 @@ def update_kernel_packages(ctx, kernel_packages_dir, kernel_headers_dir, backup_

# backup kernel-packges
if not no_backup:
karch = karch_mapping[archs_mapping[platform.machine()]]
karch = arch_mapping[platform.machine()]
ctx.run(
f"find {kernel_packages_dir} -name \"kernel-*.{karch}.pkg.tar.gz\" -type f | rev | cut -d '/' -f 1 | rev > /tmp/package.ls"
)
Expand Down
Loading

0 comments on commit f0bec52

Please sign in to comment.