diff --git a/mantle/kola/tests/rhcos/switch-kernel.go b/mantle/kola/tests/rhcos/switch-kernel.go new file mode 100644 index 0000000000..480a41756b --- /dev/null +++ b/mantle/kola/tests/rhcos/switch-kernel.go @@ -0,0 +1,167 @@ +// Copyright 2020 Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package rhcos + +import ( + "encoding/base64" + "fmt" + "io/ioutil" + "log" + "os" + "regexp" + + "github.com/coreos/mantle/kola/cluster" + "github.com/coreos/mantle/kola/register" + "github.com/coreos/mantle/platform" + "github.com/coreos/mantle/platform/conf" + "github.com/pkg/errors" +) + +var ( + homeDir = `/var/home/core` + switchKernelScript = `#!/usr/bin/env bash + # This script is a shameless translation of: https://github.com/openshift/machine-config-operator/blob/f363c7be6d2d506d900e196fa2e2d05ca08b93b6/pkg/daemon/update.go#L651 + # Usage: + # switch-kernel oldkernel newkernel rt-kernel-repo + # {oldkernel, newkernel}: either of {default, rt-kernel} + # rt-kernel-repo (optional): repository of kernel-rt packages + set -xeuo pipefail + + FROM_KERNEL="${1:?old kernel should be either of \{default, rt-kernel\}}" + TO_KERNEL="${2:?new kernel should be either of \{default, rt-kernel\}}" + + DEFAULT_KERNEL_PKG="kernel kernel-core kernel-modules kernel-modules-extra" + RT_KERNEL_PKG="kernel-rt-core kernel-rt-modules kernel-rt-modules-extra" + + if [[ $FROM_KERNEL == "default" && $TO_KERNEL == "rt-kernel" ]]; then + # Switch from default to RT Kernel + # https://github.com/openshift/machine-config-operator/blob/master/pkg/daemon/update.go#L711 + RT_KERNEL_REPO=$3 + if [[ -z $(ls ${RT_KERNEL_REPO}) ]]; then + echo "No kernel-rt package available in the repo: ${RT_KERNEL_REPO}" + exit 1 + fi + + ARGS="override remove ${DEFAULT_KERNEL_PKG}" + for RPM in $(ls ${RT_KERNEL_REPO}) + do + ARGS+=" --install ${RT_KERNEL_REPO}/${RPM}" + done + rpm-ostree ${ARGS} + elif [[ $FROM_KERNEL == "rt-kernel" && $TO_KERNEL == "default" ]]; then + # Switch from RT Kernel to default + # https://github.com/openshift/machine-config-operator/blob/e246be62e7839a086bc4494203472349c406dcae/pkg/daemon/update.go#L667 + ARGS="override reset ${DEFAULT_KERNEL_PKG}" + for PKG in $RT_KERNEL_PKG + do + ARGS+=" --uninstall $PKG" + done + rpm-ostree ${ARGS} + else + echo -e "Invalid options: $@" && exit 1 + fi + ` +) + +func init() { + register.RegisterTest(®ister.Test{ + Run: testSwitchKernel, + ClusterSize: 1, + Name: `rhcos.switch-kernel`, + Flags: []register.Flag{}, + Distros: []string{"rhcos"}, + Platforms: []string{"qemu"}, + UserData: conf.Ignition(fmt.Sprintf(`{ + "ignition": { + "version": "2.2.0" + }, + "storage": { + "files": [ + { + "filesystem": "root", + "path": "/var/home/core/switch-kernel.sh", + "contents": { + "source": "data:text/plain;base64,%s" + }, + "mode": 110 + } + ] + } + }`, base64.StdEncoding.EncodeToString([]byte(switchKernelScript)))), + }) +} + +// Drops Kernel RT RPM files under the directory `localPath` to `$homeDir/kernel-rt-rpms` directory in m +func dropRpmFilesAll(m platform.Machine, localPath string) error { + re := regexp.MustCompile(`^kernel-rt-.*\.rpm$`) + files, err := ioutil.ReadDir(localPath) + if err != nil { + log.Fatal(err) + } + for _, f := range files { + filename := f.Name() + filepath := localPath + filename + targetPath := fmt.Sprintf("%s/kernel-rt-rpms/%s", homeDir, filename) + if re.MatchString(filename) { + in, err := os.Open(filepath) + if err != nil { + return err + } + if err := platform.InstallFile(in, m, targetPath); err != nil { + return errors.Wrapf(err, "uploading %s", filename) + } + } + } + return nil +} + +func switchDefaultToRtKernel(c cluster.TestCluster, m platform.Machine) { + // run the script to switch from default kernel to rt kernel + c.MustSSH(m, "sudo "+homeDir+"/switch-kernel.sh default rt-kernel "+homeDir+"/kernel-rt-rpms/") + + // reboot the machine to switch kernel + err := m.Reboot() + if err != nil { + c.Fatalf("Could not reboot machine: %v", err) + } + + // check if the kernel has switched to rt kernel + c.MustSSH(m, "uname -v | grep -q 'PREEMPT RT'") +} + +func switchRtKernelToDefault(c cluster.TestCluster, m platform.Machine) { + // run the script to switch from rt kernel to default + c.MustSSH(m, "sudo "+homeDir+"/switch-kernel.sh rt-kernel default") + + // reboot the machine to switch kernel + err := m.Reboot() + if err != nil { + c.Fatalf("Could not reboot machine: %v", err) + } + + // check if the kernel has switched back to default kernel + c.MustSSH(m, "! $(uname -v | grep -q 'PREEMPT RT')") +} + +func testSwitchKernel(c cluster.TestCluster) { + m := c.Machines()[0] + kernelRtRpmDir := "/srv/kernel-rt/" + err := dropRpmFilesAll(m, kernelRtRpmDir) + if err != nil { + c.Fatal("Failed dropping Kernel RT RPM files: %v", err) + } + switchDefaultToRtKernel(c, m) + switchRtKernelToDefault(c, m) +}