From 72bb8df46b26c42868a67a7e3915fe781656e260 Mon Sep 17 00:00:00 2001 From: Mikhail Klementev Date: Tue, 20 Aug 2019 18:57:45 +0000 Subject: [PATCH] Support CentOS kernels Resolves #8 --- examples/kernel-module/.out-of-tree.toml | 5 ++ kernel.go | 101 +++++++++++++++++++++-- tools/qemu-centos-img/{ => 7}/Dockerfile | 14 ++-- 3 files changed, 105 insertions(+), 15 deletions(-) rename tools/qemu-centos-img/{ => 7}/Dockerfile (77%) diff --git a/examples/kernel-module/.out-of-tree.toml b/examples/kernel-module/.out-of-tree.toml index 34bc3ec..96c9954 100644 --- a/examples/kernel-module/.out-of-tree.toml +++ b/examples/kernel-module/.out-of-tree.toml @@ -23,3 +23,8 @@ distro_type = "Ubuntu" distro_release = "18.04" # Also you can use only one kernel release_mask = "4[.]15[.]0-23-generic" + +[[supported_kernels]] +distro_type = "CentOS" +distro_release = "7" +release_mask = "3[.]10[.]0-862.el7.x86_64" diff --git a/kernel.go b/kernel.go index 17ebc4a..3f21df8 100644 --- a/kernel.go +++ b/kernel.go @@ -66,6 +66,28 @@ func matchDebianHeadersPkg(container, mask string, generic bool) ( return } +func matchCentOSDevelPkg(container, mask string, generic bool) ( + pkgs []string, err error) { + + cmd := "yum search kernel-devel --show-duplicates | " + + "grep '^kernel-devel' | cut -d ' ' -f 1" + output, err := dockerRun(time.Minute, container, "/tmp", cmd) + if err != nil { + return + } + + r, err := regexp.Compile("kernel-devel-" + mask) + if err != nil { + return + } + + for _, k := range r.FindAll([]byte(output), -1) { + pkgs = append(pkgs, string(k)) + } + + return +} + func dockerImagePath(sk config.KernelMask) (path string, err error) { usr, err := user.Current() if err != nil { @@ -77,6 +99,16 @@ func dockerImagePath(sk config.KernelMask) (path string, err error) { return } +func vsyscallAvailable() (available bool, err error) { + buf, err := ioutil.ReadFile("/proc/self/maps") + if err != nil { + return + } + + available = strings.Contains(string(buf), "[vsyscall]") + return +} + func generateBaseDockerImage(sk config.KernelMask) (err error) { imagePath, err := dockerImagePath(sk) if err != nil { @@ -101,6 +133,11 @@ func generateBaseDockerImage(sk config.KernelMask) (err error) { sk.DistroRelease, ) + vsyscall, err := vsyscallAvailable() + if err != nil { + return + } + switch sk.DistroType { case config.Ubuntu: d += "ENV DEBIAN_FRONTEND=noninteractive\n" @@ -111,6 +148,24 @@ func generateBaseDockerImage(sk config.KernelMask) (err error) { d += "RUN apt-get install -y libseccomp-dev\n" } d += "RUN mkdir /lib/modules\n" + case config.CentOS: + if sk.DistroRelease < "7" && !vsyscall { + log.Println("Old CentOS requires `vsyscall=emulate` " + + "on the latest kernels") + log.Println("Check out `A note about vsyscall` " + + "at https://hub.docker.com/_/centos") + log.Println("See also https://lwn.net/Articles/446528/") + err = fmt.Errorf("vsyscall is not available") + return + } + + // enable rpms from old minor releases + d += "RUN sed -i 's/enabled=0/enabled=1/' /etc/yum.repos.d/CentOS-Vault.repo\n" + // do not remove old kernels + d += "RUN sed -i 's;installonly_limit=;installonly_limit=100500;' /etc/yum.conf\n" + d += "RUN yum -y update\n" + d += "RUN yum -y groupinstall 'Development Tools'\n" + d += "RUN yum -y install deltarpm\n" default: err = fmt.Errorf("%s not yet supported", sk.DistroType.String()) return @@ -156,12 +211,32 @@ func dockerImageAppend(sk config.KernelMask, pkgname string) (err error) { return } - imagepkg := strings.Replace(pkgname, "headers", "image", -1) + var s string - log.Printf("Start adding kernel %s for %s:%s", - imagepkg, sk.DistroType.String(), sk.DistroRelease) + switch sk.DistroType { + case config.Ubuntu: + imagepkg := strings.Replace(pkgname, "headers", "image", -1) - s := fmt.Sprintf("RUN apt-get install -y %s %s\n", imagepkg, pkgname) + log.Printf("Start adding kernel %s for %s:%s", + imagepkg, sk.DistroType.String(), sk.DistroRelease) + + s = fmt.Sprintf("RUN apt-get install -y %s %s\n", imagepkg, + pkgname) + case config.CentOS: + imagepkg := strings.Replace(pkgname, "-devel", "", -1) + + log.Printf("Start adding kernel %s for %s:%s", + imagepkg, sk.DistroType.String(), sk.DistroRelease) + + version := strings.Replace(pkgname, "kernel-devel-", "", -1) + + s = fmt.Sprintf("RUN yum -y install %s %s\n", imagepkg, + pkgname) + s += fmt.Sprintf("RUN dracut --add-drivers 'e1000 ext4' -f "+ + "/boot/initramfs-%s.img %s\n", version, version) + default: + err = fmt.Errorf("%s not yet supported", sk.DistroType.String()) + } err = ioutil.WriteFile(imagePath+"/Dockerfile", append(raw, []byte(s)...), 0644) @@ -239,7 +314,7 @@ func copyKernels(name string) (err error) { func genKernelPath(files []os.FileInfo, kname string) string { for _, file := range files { - if strings.Contains(file.Name(), "vmlinuz") { + if strings.HasPrefix(file.Name(), "vmlinuz") { if strings.Contains(file.Name(), kname) { return file.Name() } @@ -250,7 +325,9 @@ func genKernelPath(files []os.FileInfo, kname string) string { func genInitrdPath(files []os.FileInfo, kname string) string { for _, file := range files { - if strings.Contains(file.Name(), "initrd") { + if strings.HasPrefix(file.Name(), "initrd") || + strings.HasPrefix(file.Name(), "initramfs") { + if strings.Contains(file.Name(), kname) { return file.Name() } @@ -511,8 +588,16 @@ func generateKernels(km config.KernelMask, max int64, download bool) (err error) } var pkgs []string - pkgs, err = matchDebianHeadersPkg(km.DockerName(), - km.ReleaseMask, true) + switch km.DistroType { + case config.Ubuntu: + pkgs, err = matchDebianHeadersPkg(km.DockerName(), + km.ReleaseMask, true) + case config.CentOS: + pkgs, err = matchCentOSDevelPkg(km.DockerName(), + km.ReleaseMask, true) + default: + err = fmt.Errorf("%s not yet supported", km.DistroType.String()) + } if err != nil { return } diff --git a/tools/qemu-centos-img/Dockerfile b/tools/qemu-centos-img/7/Dockerfile similarity index 77% rename from tools/qemu-centos-img/Dockerfile rename to tools/qemu-centos-img/7/Dockerfile index edb3bfb..c47e494 100644 --- a/tools/qemu-centos-img/Dockerfile +++ b/tools/qemu-centos-img/7/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2018 Mikhail Klementev. All rights reserved. +# Copyright 2019 Mikhail Klementev. All rights reserved. # Use of this source code is governed by a AGPLv3 license # (or later) that can be found in the LICENSE file. # @@ -7,11 +7,13 @@ # $ docker build -t gen-centos7-image . # $ docker run --privileged -v $(pwd):/shared -t gen-centos7-image # -# centos7.img will be created in current directory. You can change $(pwd) to -# different directory to use different destination for image. +# out_of_tree_centos_7.img will be created in current directory. +# You can change $(pwd) to different directory to use different destination +# for image. # FROM centos:7 +RUN yum -y update RUN yum -y groupinstall "Development Tools" RUN yum -y install qemu-img e2fsprogs @@ -26,7 +28,7 @@ RUN yum --installroot=$TMPDIR \ --releasever=7 \ --disablerepo='*' \ --enablerepo=base \ - -y install openssh-server + -y install openssh-server openssh-clients RUN chroot $TMPDIR /bin/sh -c 'useradd -m user' RUN sed -i 's/root:\*:/root::/' $TMPDIR/etc/shadow @@ -37,13 +39,11 @@ RUN sed -i '/PermitRootLogin/d' $TMPDIR/etc/ssh/sshd_config RUN echo PermitRootLogin yes >> $TMPDIR/etc/ssh/sshd_config # network workaround -# FIXME kernel module compatibility issues RUN chmod +x $TMPDIR/etc/rc.local -RUN echo 'find /lib/modules | grep e1000.ko | xargs insmod -f' >> $TMPDIR/etc/rc.local RUN echo 'dhclient' >> $TMPDIR/etc/rc.local ENV IMAGEDIR=/tmp/image -ENV IMAGE=/shared/centos7.img +ENV IMAGE=/shared/out_of_tree_centos_7.img RUN mkdir $IMAGEDIR