From 7ca989fd8d8439fe0b540268805cff353bfdf03d Mon Sep 17 00:00:00 2001 From: Mikhail Klementev Date: Tue, 23 May 2023 16:54:34 +0000 Subject: [PATCH] feat: use distro info to create the container --- container/container.go | 88 ++++++++++++++++++++--- distro/centos/centos.go | 12 +--- distro/centos/centos_test.go | 3 +- distro/debian/debian.go | 12 +--- distro/debian/debian_test.go | 3 +- distro/oraclelinux/oraclelinux.go | 12 +--- distro/oraclelinux/oraclelinux_test.go | 3 +- distro/ubuntu/ubuntu.go | 13 +--- distro/ubuntu/ubuntu_test.go | 2 +- fs/fs.go | 30 ++++++++ kernel/kernel.go | 98 ++------------------------ kernel/kernel_linux.go | 4 +- 12 files changed, 130 insertions(+), 150 deletions(-) diff --git a/container/container.go b/container/container.go index 32b85d0..df19cf2 100644 --- a/container/container.go +++ b/container/container.go @@ -8,6 +8,7 @@ import ( "bufio" "errors" "fmt" + "io/ioutil" "os" "os/exec" "path" @@ -21,6 +22,7 @@ import ( "code.dumpstack.io/tools/out-of-tree/config" "code.dumpstack.io/tools/out-of-tree/distro" + "code.dumpstack.io/tools/out-of-tree/fs" ) var Runtime = "docker" @@ -73,16 +75,13 @@ func Images() (diis []Image, err error) { return } -func ImagePath(sk config.Target) string { - return config.Dir("containers", sk.Distro.ID.String(), sk.Distro.Release) -} - type Volume struct { Src, Dest string } type Container struct { name string + dist distro.Distro Volumes []Volume @@ -92,25 +91,29 @@ type Container struct { Log zerolog.Logger } -func New(name string) (c Container, err error) { +func New(dist distro.Distro) (c Container, err error) { + distro := strings.ToLower(dist.ID.String()) + release := strings.Replace(dist.Release, ".", "__", -1) + c.name = fmt.Sprintf("out_of_tree_%s_%s", distro, release) + c.Log = log.With(). - Str("container", name). + Str("container", c.name). Logger() - c.name = name + c.dist = dist c.Volumes = append(c.Volumes, Volume{ - Src: config.Dir("volumes", name, "lib", "modules"), + Src: config.Dir("volumes", c.name, "lib", "modules"), Dest: "/lib/modules", }) c.Volumes = append(c.Volumes, Volume{ - Src: config.Dir("volumes", name, "usr", "src"), + Src: config.Dir("volumes", c.name, "usr", "src"), Dest: "/usr/src", }) c.Volumes = append(c.Volumes, Volume{ - Src: config.Dir("volumes", name, "boot"), + Src: config.Dir("volumes", c.name, "boot"), Dest: "/boot", }) @@ -319,3 +322,68 @@ func (c Container) Run(workdir string, command string) (output string, err error return } + +func (c Container) Kernels() (kernels []config.KernelInfo, err error) { + var libmodules, boot string + for _, volume := range c.Volumes { + switch volume.Dest { + case "/lib/modules": + libmodules = volume.Src + case "/boot": + boot = volume.Src + } + } + + moddirs, err := ioutil.ReadDir(libmodules) + if err != nil { + return + } + + bootfiles, err := ioutil.ReadDir(boot) + if err != nil { + return + } + + for _, krel := range moddirs { + c.Log.Debug().Msgf("generate config entry for %s", krel.Name()) + + var kernelFile, initrdFile string + kernelFile, err = fs.FindKernel(bootfiles, krel.Name()) + if err != nil { + c.Log.Warn().Msgf("cannot find kernel %s", krel.Name()) + continue + } + + initrdFile, err = fs.FindInitrd(bootfiles, krel.Name()) + if err != nil { + c.Log.Warn().Msgf("cannot find initrd %s", krel.Name()) + continue + } + + ki := config.KernelInfo{ + Distro: c.dist, + KernelVersion: krel.Name(), + KernelRelease: krel.Name(), + ContainerName: c.name, + + KernelPath: filepath.Join(boot, kernelFile), + InitrdPath: filepath.Join(boot, initrdFile), + ModulesPath: filepath.Join(libmodules, krel.Name()), + + RootFS: config.File("images", c.name+".img"), + } + + kernels = append(kernels, ki) + } + + for _, cmd := range []string{ + "find /boot -type f -exec chmod a+r {} \\;", + } { + _, err = c.Run(config.Dir("tmp"), cmd) + if err != nil { + return + } + } + + return +} diff --git a/distro/centos/centos.go b/distro/centos/centos.go index ae98e3e..74aa058 100644 --- a/distro/centos/centos.go +++ b/distro/centos/centos.go @@ -15,18 +15,12 @@ func init() { releases := []string{"6", "7", "8"} for _, release := range releases { - container := "out_of_tree_centos_" + release - - distro.Register(CentOS{ - release: release, - container: container, - }) + distro.Register(CentOS{release: release}) } } type CentOS struct { - release string - container string + release string } func (centos CentOS) Equal(d distro.Distro) bool { @@ -38,7 +32,7 @@ func (centos CentOS) Distro() distro.Distro { } func (centos CentOS) Packages() (pkgs []string, err error) { - c, err := container.New(centos.container) + c, err := container.New(centos.Distro()) if err != nil { return } diff --git a/distro/centos/centos_test.go b/distro/centos/centos_test.go index 75926f6..b0c0e8b 100644 --- a/distro/centos/centos_test.go +++ b/distro/centos/centos_test.go @@ -11,8 +11,7 @@ import ( func TestCentOS(t *testing.T) { assert := assert.New(t) - u := CentOS{release: "7", container: "out_of_tree_centos_7"} - + u := CentOS{release: "7"} assert.True(u.Equal(distro.Distro{Release: "7", ID: distro.CentOS})) diff --git a/distro/debian/debian.go b/distro/debian/debian.go index d058be5..48ec47a 100644 --- a/distro/debian/debian.go +++ b/distro/debian/debian.go @@ -29,18 +29,12 @@ func init() { } for _, release := range releases { - container := fmt.Sprintf("out_of_tree_debian_%d", release) - - distro.Register(Debian{ - release: release, - container: container, - }) + distro.Register(Debian{release: release}) } } type Debian struct { - release Release - container string + release Release } func (d Debian) Equal(dd distro.Distro) bool { @@ -56,7 +50,7 @@ func (d Debian) Distro() distro.Distro { } func (d Debian) Packages() (packages []string, err error) { - c, err := container.New(d.container) + c, err := container.New(d.Distro()) if err != nil { return } diff --git a/distro/debian/debian_test.go b/distro/debian/debian_test.go index b8b58f2..88b6396 100644 --- a/distro/debian/debian_test.go +++ b/distro/debian/debian_test.go @@ -46,8 +46,7 @@ func TestKernelRelease(t *testing.T) { func TestDebian(t *testing.T) { assert := assert.New(t) - u := Debian{release: Wheezy, container: "out_of_tree_debian_7"} - + u := Debian{release: Wheezy} assert.True(u.Equal(distro.Distro{Release: "wheezy", ID: distro.Debian})) diff --git a/distro/oraclelinux/oraclelinux.go b/distro/oraclelinux/oraclelinux.go index f2cd857..f9673d4 100644 --- a/distro/oraclelinux/oraclelinux.go +++ b/distro/oraclelinux/oraclelinux.go @@ -15,18 +15,12 @@ func init() { releases := []string{"6", "7", "8", "9"} for _, release := range releases { - container := "out_of_tree_oraclelinux_" + release - - distro.Register(OracleLinux{ - release: release, - container: container, - }) + distro.Register(OracleLinux{release: release}) } } type OracleLinux struct { - release string - container string + release string } func (ol OracleLinux) Equal(d distro.Distro) bool { @@ -38,7 +32,7 @@ func (ol OracleLinux) Distro() distro.Distro { } func (ol OracleLinux) Packages() (pkgs []string, err error) { - c, err := container.New(ol.container) + c, err := container.New(ol.Distro()) if err != nil { return } diff --git a/distro/oraclelinux/oraclelinux_test.go b/distro/oraclelinux/oraclelinux_test.go index 5dce273..5fb40ee 100644 --- a/distro/oraclelinux/oraclelinux_test.go +++ b/distro/oraclelinux/oraclelinux_test.go @@ -11,8 +11,7 @@ import ( func TestOracleLinux(t *testing.T) { assert := assert.New(t) - u := OracleLinux{release: "9", container: "out_of_tree_oraclelinux_9"} - + u := OracleLinux{release: "9"} assert.True(u.Equal(distro.Distro{Release: "9", ID: distro.OracleLinux})) diff --git a/distro/ubuntu/ubuntu.go b/distro/ubuntu/ubuntu.go index 690232a..302cd80 100644 --- a/distro/ubuntu/ubuntu.go +++ b/distro/ubuntu/ubuntu.go @@ -20,19 +20,12 @@ func init() { } for _, release := range releases { - container := "out_of_tree_ubuntu_" + release - container = strings.Replace(container, ".", "__", -1) - - distro.Register(Ubuntu{ - release: release, - container: container, - }) + distro.Register(Ubuntu{release: release}) } } type Ubuntu struct { - release string - container string + release string } func (u Ubuntu) Equal(d distro.Distro) bool { @@ -44,7 +37,7 @@ func (u Ubuntu) Distro() distro.Distro { } func (u Ubuntu) Packages() (pkgs []string, err error) { - c, err := container.New(u.container) + c, err := container.New(u.Distro()) if err != nil { return } diff --git a/distro/ubuntu/ubuntu_test.go b/distro/ubuntu/ubuntu_test.go index 24f74b2..f688a50 100644 --- a/distro/ubuntu/ubuntu_test.go +++ b/distro/ubuntu/ubuntu_test.go @@ -11,7 +11,7 @@ import ( func TestUbuntu(t *testing.T) { assert := assert.New(t) - u := Ubuntu{release: "22.04", container: "out_of_tree_ubuntu_22__04"} + u := Ubuntu{release: "22.04"} assert.True(u.Equal(distro.Distro{Release: "22.04", ID: distro.Ubuntu})) diff --git a/fs/fs.go b/fs/fs.go index 6b27e99..75e3393 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -70,3 +70,33 @@ func FindBySubstring(dir, substring string) (k string, err error) { err = errors.New("not found") return } + +func FindKernel(files []os.FileInfo, kname string) (name string, err error) { + for _, file := range files { + if strings.HasPrefix(file.Name(), "vmlinuz") { + if strings.Contains(file.Name(), kname) { + name = file.Name() + return + } + } + } + + err = errors.New("cannot find kernel") + return +} + +func FindInitrd(files []os.FileInfo, kname string) (name string, err error) { + for _, file := range files { + if strings.HasPrefix(file.Name(), "initrd") || + strings.HasPrefix(file.Name(), "initramfs") { + + if strings.Contains(file.Name(), kname) { + name = file.Name() + return + } + } + } + + err = errors.New("cannot find kernel") + return +} diff --git a/kernel/kernel.go b/kernel/kernel.go index 732aaaa..f319d87 100644 --- a/kernel/kernel.go +++ b/kernel/kernel.go @@ -5,7 +5,6 @@ package kernel import ( - "errors" "fmt" "io/ioutil" "math/rand" @@ -76,7 +75,7 @@ func installKernel(sk config.Target, pkgname string, force, headers bool) (err e Str("pkg", pkgname). Logger() - c, err := container.New(sk.DockerName()) // TODO conf + c, err := container.New(sk.Distro) // TODO conf if err != nil { return } @@ -182,36 +181,6 @@ func installKernel(sk config.Target, pkgname string, force, headers bool) (err e return } -func findKernelFile(files []os.FileInfo, kname string) (name string, err error) { - for _, file := range files { - if strings.HasPrefix(file.Name(), "vmlinuz") { - if strings.Contains(file.Name(), kname) { - name = file.Name() - return - } - } - } - - err = errors.New("cannot find kernel") - return -} - -func findInitrdFile(files []os.FileInfo, kname string) (name string, err error) { - for _, file := range files { - if strings.HasPrefix(file.Name(), "initrd") || - strings.HasPrefix(file.Name(), "initramfs") { - - if strings.Contains(file.Name(), kname) { - name = file.Name() - return - } - } - } - - err = errors.New("cannot find kernel") - return -} - func GenRootfsImage(d container.Image, download bool) (rootfs string, err error) { imagesPath := config.Dir("images") imageFile := d.Name + ".img" @@ -289,76 +258,17 @@ func UpdateKernelsCfg(host, download bool) (err error) { func listContainersKernels(dii container.Image, newkcfg *config.KernelConfig, download bool) (err error) { - rootfs, err := GenRootfsImage(dii, download) + c, err := container.New(dii.Distro) if err != nil { return } - c, err := container.New(dii.Name) + kernels, err := c.Kernels() if err != nil { return } - var libmodules, boot string - for _, volume := range c.Volumes { - switch volume.Dest { - case "/lib/modules": - libmodules = volume.Src - case "/boot": - boot = volume.Src - } - } - - moddirs, err := ioutil.ReadDir(libmodules) - if err != nil { - return - } - - bootfiles, err := ioutil.ReadDir(boot) - if err != nil { - return - } - - for _, krel := range moddirs { - log.Debug().Msgf("generate config entry for %s", krel.Name()) - - var kernelFile, initrdFile string - kernelFile, err = findKernelFile(bootfiles, krel.Name()) - if err != nil { - log.Warn().Msgf("cannot find kernel %s", krel.Name()) - continue - } - - initrdFile, err = findInitrdFile(bootfiles, krel.Name()) - if err != nil { - log.Warn().Msgf("cannot find initrd %s", krel.Name()) - continue - } - - ki := config.KernelInfo{ - Distro: dii.Distro, - KernelVersion: krel.Name(), - KernelRelease: krel.Name(), - ContainerName: dii.Name, - - KernelPath: filepath.Join(boot, kernelFile), - InitrdPath: filepath.Join(boot, initrdFile), - ModulesPath: filepath.Join(libmodules, krel.Name()), - - RootFS: rootfs, - } - newkcfg.Kernels = append(newkcfg.Kernels, ki) - } - - for _, cmd := range []string{ - "find /boot -type f -exec chmod a+r {} \\;", - } { - _, err = c.Run(config.Dir("tmp"), cmd) - if err != nil { - return - } - } - + newkcfg.Kernels = append(newkcfg.Kernels, kernels...) return } diff --git a/kernel/kernel_linux.go b/kernel/kernel_linux.go index 3a96a4f..90405ca 100644 --- a/kernel/kernel_linux.go +++ b/kernel/kernel_linux.go @@ -64,13 +64,13 @@ func genHostKernels(download bool) (kcfg config.KernelConfig, err error) { log.Debug().Msgf("generate config entry for %s", krel) var kernelFile, initrdFile string - kernelFile, err = findKernelFile(bootfiles, krel) + kernelFile, err = fs.FindKernel(bootfiles, krel) if err != nil { log.Warn().Msgf("cannot find kernel %s", krel) continue } - initrdFile, err = findInitrdFile(bootfiles, krel) + initrdFile, err = fs.FindInitrd(bootfiles, krel) if err != nil { log.Warn().Msgf("cannot find initrd %s", krel) continue