2023-05-11 22:17:46 +00:00
|
|
|
package debian
|
|
|
|
|
2023-05-12 17:26:53 +00:00
|
|
|
import (
|
2023-05-12 20:05:44 +00:00
|
|
|
"errors"
|
2023-05-13 19:51:57 +00:00
|
|
|
"fmt"
|
2023-05-14 21:04:22 +00:00
|
|
|
"os"
|
2023-05-14 22:00:29 +00:00
|
|
|
"path"
|
2023-05-14 21:04:22 +00:00
|
|
|
"path/filepath"
|
2023-05-12 17:26:53 +00:00
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
|
2023-05-16 09:24:34 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/cache"
|
2023-05-12 17:26:53 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/config"
|
2023-05-14 07:19:35 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/container"
|
2023-05-14 21:04:22 +00:00
|
|
|
"code.dumpstack.io/tools/out-of-tree/fs"
|
2023-05-12 17:26:53 +00:00
|
|
|
)
|
|
|
|
|
2023-05-12 20:05:44 +00:00
|
|
|
type Release int
|
2023-05-11 22:17:46 +00:00
|
|
|
|
|
|
|
const (
|
2023-05-12 20:05:44 +00:00
|
|
|
None Release = iota
|
|
|
|
Buzz
|
|
|
|
Hamm
|
|
|
|
Woody
|
|
|
|
Etch
|
|
|
|
Lenny
|
|
|
|
Squeeze
|
|
|
|
Wheezy
|
2023-05-11 22:17:46 +00:00
|
|
|
Jessie
|
|
|
|
Stretch
|
|
|
|
Buster
|
|
|
|
Bullseye
|
|
|
|
Bookworm
|
|
|
|
)
|
|
|
|
|
2023-05-12 20:05:44 +00:00
|
|
|
var ReleaseStrings = [...]string{
|
|
|
|
"",
|
2023-05-13 19:08:46 +00:00
|
|
|
"buzz",
|
|
|
|
"hamm",
|
|
|
|
"woody",
|
|
|
|
"etch",
|
|
|
|
"lenny",
|
|
|
|
"squeeze",
|
|
|
|
"wheezy",
|
|
|
|
"jessie",
|
|
|
|
"stretch",
|
|
|
|
"buster",
|
|
|
|
"bullseye",
|
|
|
|
"bookworm",
|
2023-05-11 22:17:46 +00:00
|
|
|
}
|
|
|
|
|
2023-05-12 20:05:44 +00:00
|
|
|
func (cn Release) String() string {
|
|
|
|
return ReleaseStrings[cn]
|
|
|
|
}
|
|
|
|
|
|
|
|
func releaseFromString(s string) (r Release) {
|
|
|
|
switch strings.ToLower(s) {
|
|
|
|
case "7", "wheezy":
|
|
|
|
r = Wheezy
|
|
|
|
case "8", "jessie":
|
|
|
|
r = Jessie
|
|
|
|
case "9", "stretch":
|
|
|
|
r = Stretch
|
|
|
|
case "10", "buster":
|
|
|
|
r = Buster
|
|
|
|
case "11", "bullseye":
|
|
|
|
r = Bullseye
|
|
|
|
default:
|
|
|
|
r = None
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-14 17:14:05 +00:00
|
|
|
func kernelRelease(deb string) (r Release, err error) {
|
2023-05-12 20:05:44 +00:00
|
|
|
// linux-image-4.17.0-2-amd64 -> 4.17
|
|
|
|
re := regexp.MustCompile(`([0-9]*\.[0-9]*)`)
|
2023-05-14 17:14:05 +00:00
|
|
|
sver := re.FindString(deb)
|
|
|
|
if sver == "" {
|
2023-05-12 20:05:44 +00:00
|
|
|
err = errors.New("empty result")
|
|
|
|
return
|
|
|
|
}
|
2023-05-14 17:14:05 +00:00
|
|
|
version := kver(sver)
|
2023-05-12 20:05:44 +00:00
|
|
|
|
2023-05-14 17:14:05 +00:00
|
|
|
if version.LessThan(kver("3.0-rc0")) {
|
2023-05-12 20:05:44 +00:00
|
|
|
err = errors.New("not supported")
|
|
|
|
return
|
2023-05-13 17:42:25 +00:00
|
|
|
}
|
|
|
|
|
2023-05-14 17:14:05 +00:00
|
|
|
if version.LessThan(kver("3.8-rc0")) {
|
|
|
|
// Wheezy 3.2
|
2023-05-14 10:12:53 +00:00
|
|
|
// >=3.8 breaks initramfs-tools << 0.110~
|
|
|
|
// Wheezy initramfs-tools version is 0.109.1
|
2023-05-14 17:14:05 +00:00
|
|
|
r = Wheezy
|
|
|
|
} else if version.LessThan(kver("4.9-rc0")) {
|
|
|
|
// Jessie 3.16
|
|
|
|
r = Jessie
|
|
|
|
} else if version.LessThan(kver("4.19-rc0")) {
|
|
|
|
// Stretch 4.9
|
|
|
|
r = Stretch
|
|
|
|
} else if version.LessThan(kver("5.10-rc0")) {
|
|
|
|
// Buster 4.19
|
|
|
|
r = Buster
|
|
|
|
} else {
|
|
|
|
// Bullseye 5.10
|
|
|
|
r = Bullseye
|
2023-05-12 20:05:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
2023-05-11 22:17:46 +00:00
|
|
|
}
|
2023-05-12 17:26:53 +00:00
|
|
|
|
|
|
|
func MatchImagePkg(km config.KernelMask) (pkgs []string, err error) {
|
2023-05-14 12:37:45 +00:00
|
|
|
kernels, err := GetKernels()
|
2023-05-12 17:26:53 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("get kernels")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-12 20:05:44 +00:00
|
|
|
release := releaseFromString(km.DistroRelease)
|
|
|
|
|
2023-05-12 17:26:53 +00:00
|
|
|
r := regexp.MustCompile(km.ReleaseMask)
|
|
|
|
|
|
|
|
for _, dk := range kernels {
|
|
|
|
p := strings.Replace(dk.Image.Deb.Name, ".deb", "", -1)
|
2023-05-12 20:05:44 +00:00
|
|
|
|
|
|
|
var kr Release
|
|
|
|
kr, err = kernelRelease(p)
|
|
|
|
if err != nil {
|
|
|
|
log.Warn().Err(err).Msg("")
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if kr != release {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-05-12 17:26:53 +00:00
|
|
|
if r.MatchString(p) {
|
|
|
|
pkgs = append(pkgs, p)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2023-05-13 19:51:57 +00:00
|
|
|
|
2023-05-14 07:00:00 +00:00
|
|
|
func ContainerEnvs(km config.KernelMask) (envs []string) {
|
2023-05-13 19:51:57 +00:00
|
|
|
envs = append(envs, "DEBIAN_FRONTEND=noninteractive")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-14 09:53:59 +00:00
|
|
|
func ContainerImage(km config.KernelMask) (image string) {
|
|
|
|
image += "debian:"
|
2023-05-13 19:51:57 +00:00
|
|
|
|
2023-05-14 09:53:59 +00:00
|
|
|
switch releaseFromString(km.DistroRelease) {
|
|
|
|
case Wheezy:
|
|
|
|
image += "wheezy-20190228"
|
|
|
|
case Jessie:
|
|
|
|
image += "jessie-20210326"
|
|
|
|
case Stretch:
|
|
|
|
image += "stretch-20220622"
|
|
|
|
default:
|
2023-05-14 21:18:26 +00:00
|
|
|
image += km.DistroRelease
|
2023-05-14 09:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func repositories(release Release) (repos []string) {
|
2023-05-13 19:51:57 +00:00
|
|
|
var snapshot string
|
|
|
|
|
|
|
|
switch release {
|
2023-05-14 09:53:59 +00:00
|
|
|
// Latest snapshots that include release
|
2023-05-13 19:51:57 +00:00
|
|
|
case Wheezy:
|
2023-05-14 09:53:59 +00:00
|
|
|
// doesn't include snapshot repos in /etc/apt/source.list
|
|
|
|
snapshot = "20190321T212815Z"
|
2023-05-14 22:20:34 +00:00
|
|
|
case Jessie:
|
|
|
|
snapshot = "20230322T152120Z"
|
|
|
|
case Stretch:
|
|
|
|
snapshot = "20230423T032533Z"
|
2023-05-13 19:51:57 +00:00
|
|
|
default:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-14 09:53:59 +00:00
|
|
|
repo := func(archive, s string) {
|
|
|
|
format := "deb [check-valid-until=no trusted=yes] " +
|
|
|
|
"http://snapshot.debian.org/archive/%s/%s " +
|
|
|
|
"%s%s main"
|
|
|
|
r := fmt.Sprintf(format, archive, snapshot, release, s)
|
|
|
|
repos = append(repos, r)
|
|
|
|
}
|
|
|
|
|
|
|
|
repo("debian", "")
|
|
|
|
repo("debian", "-updates")
|
|
|
|
repo("debian-security", "/updates")
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func ContainerCommands(km config.KernelMask) (commands []string) {
|
|
|
|
release := releaseFromString(km.DistroRelease)
|
2023-05-13 19:51:57 +00:00
|
|
|
|
|
|
|
cmdf := func(f string, s ...interface{}) {
|
|
|
|
commands = append(commands, fmt.Sprintf(f, s...))
|
|
|
|
}
|
|
|
|
|
2023-05-14 09:53:59 +00:00
|
|
|
repos := repositories(release)
|
2023-05-13 19:51:57 +00:00
|
|
|
|
2023-05-14 09:53:59 +00:00
|
|
|
if len(repos) != 0 {
|
|
|
|
cmdf("rm /etc/apt/sources.list")
|
|
|
|
for _, repo := range repos {
|
|
|
|
cmdf("echo '%s' >> /etc/apt/sources.list", repo)
|
|
|
|
}
|
|
|
|
} else {
|
2023-05-14 21:12:24 +00:00
|
|
|
cmdf("sed -i " +
|
|
|
|
"-e '/snapshot/!d' " +
|
|
|
|
"-e 's/# deb/deb [check-valid-until=no trusted=yes]/' " +
|
|
|
|
"/etc/apt/sources.list")
|
2023-05-14 09:53:59 +00:00
|
|
|
}
|
2023-05-13 19:51:57 +00:00
|
|
|
|
2023-05-16 17:52:15 +00:00
|
|
|
cmdf("{ apt-get update || apt-get update || apt-get update }")
|
|
|
|
|
|
|
|
packages := "wget build-essential libelf-dev git kmod linux-base "
|
|
|
|
packages += "initramfs-tools "
|
2023-05-16 09:23:44 +00:00
|
|
|
|
|
|
|
switch release {
|
|
|
|
case Wheezy:
|
2023-05-16 17:52:15 +00:00
|
|
|
packages += "gcc-4.6 "
|
2023-05-16 09:23:44 +00:00
|
|
|
}
|
|
|
|
|
2023-05-14 21:17:21 +00:00
|
|
|
if release < 9 {
|
2023-05-16 17:52:15 +00:00
|
|
|
packages += "module-init-tools "
|
2023-05-14 21:17:21 +00:00
|
|
|
}
|
|
|
|
|
2023-05-16 17:55:30 +00:00
|
|
|
cmdf("{ apt-get install -y %s "+
|
2023-05-16 17:52:15 +00:00
|
|
|
"|| apt-get install -y %s "+
|
|
|
|
"|| apt-get install -y %s }", packages, packages, packages)
|
|
|
|
|
2023-05-13 19:51:57 +00:00
|
|
|
cmdf("mkdir -p /lib/modules")
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2023-05-14 07:19:35 +00:00
|
|
|
|
|
|
|
func ContainerKernels(d container.Image, kcfg *config.KernelConfig) (err error) {
|
2023-05-14 22:00:29 +00:00
|
|
|
cpath := config.Dir("volumes", d.Name)
|
2023-05-14 21:04:22 +00:00
|
|
|
rootfs := config.File("images", d.Name+".img")
|
|
|
|
|
2023-05-14 22:00:29 +00:00
|
|
|
files, err := os.ReadDir(cpath)
|
2023-05-14 21:04:22 +00:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
if !strings.Contains(file.Name(), "linux-image") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
pkgname := file.Name()
|
|
|
|
|
2023-05-14 22:00:29 +00:00
|
|
|
kpkgdir := filepath.Join(cpath, pkgname)
|
2023-05-14 21:04:22 +00:00
|
|
|
|
|
|
|
bootdir := filepath.Join(kpkgdir, "boot")
|
|
|
|
|
|
|
|
vmlinuz, err := fs.FindBySubstring(bootdir, "vmlinuz")
|
|
|
|
if err != nil {
|
|
|
|
log.Warn().Msgf("cannot find vmlinuz for %s", pkgname)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
initrd, err := fs.FindBySubstring(bootdir, "initrd")
|
|
|
|
if err != nil {
|
|
|
|
log.Warn().Msgf("cannot find initrd for %s", pkgname)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
modulesdir := filepath.Join(kpkgdir, "lib/modules")
|
|
|
|
|
|
|
|
modules, err := fs.FindBySubstring(modulesdir, "")
|
|
|
|
if err != nil {
|
|
|
|
log.Warn().Msgf("cannot find modules for %s", pkgname)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Debug().Msgf("%s %s %s", vmlinuz, initrd, modules)
|
|
|
|
|
2023-05-14 22:00:29 +00:00
|
|
|
release := strings.Replace(pkgname, "linux-image-", "", -1)
|
|
|
|
|
2023-05-14 21:04:22 +00:00
|
|
|
ki := config.KernelInfo{
|
|
|
|
DistroType: d.DistroType,
|
|
|
|
DistroRelease: d.DistroRelease,
|
2023-05-14 22:00:29 +00:00
|
|
|
KernelVersion: path.Base(modules),
|
|
|
|
KernelRelease: release,
|
2023-05-14 21:04:22 +00:00
|
|
|
ContainerName: d.Name,
|
|
|
|
|
|
|
|
KernelPath: vmlinuz,
|
|
|
|
InitrdPath: initrd,
|
|
|
|
ModulesPath: modules,
|
|
|
|
|
|
|
|
RootFS: rootfs,
|
|
|
|
}
|
|
|
|
|
|
|
|
kcfg.Kernels = append(kcfg.Kernels, ki)
|
|
|
|
}
|
|
|
|
|
2023-05-14 07:19:35 +00:00
|
|
|
return
|
|
|
|
}
|
2023-05-14 22:15:43 +00:00
|
|
|
|
2023-05-15 09:43:48 +00:00
|
|
|
func ContainerVolumes(km config.KernelMask, pkgname string) (volumes container.Volumes) {
|
|
|
|
pkgdir := filepath.Join("volumes", km.DockerName(), pkgname)
|
2023-05-14 22:15:43 +00:00
|
|
|
|
|
|
|
volumes.LibModules = config.Dir(pkgdir, "/lib/modules")
|
|
|
|
volumes.UsrSrc = config.Dir(pkgdir, "/usr/src")
|
|
|
|
volumes.Boot = config.Dir(pkgdir, "/boot")
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2023-05-16 09:24:34 +00:00
|
|
|
|
|
|
|
func InstallCommands(km config.KernelMask, pkgname string) (cmds []string, err error) {
|
|
|
|
dk, err := getCachedKernel(pkgname + ".deb")
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, pkg := range dk.Packages() {
|
|
|
|
found, newurl := cache.PackageURL(
|
|
|
|
km.DistroType,
|
|
|
|
pkg.Deb.URL,
|
|
|
|
)
|
|
|
|
if found {
|
|
|
|
log.Debug().Msgf("cached deb found %s", newurl)
|
|
|
|
pkg.Deb.URL = newurl
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO use faketime on old releases?
|
|
|
|
pkg.Deb.URL = strings.Replace(pkg.Deb.URL, "https", "http", -1)
|
|
|
|
|
|
|
|
cmds = append(cmds, "wget --no-check-certificate "+pkg.Deb.URL)
|
|
|
|
}
|
|
|
|
|
|
|
|
cmds = append(cmds, "dpkg -i ./*.deb")
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func CleanupFailed(km config.KernelMask, pkgname string) {
|
|
|
|
pkgdir := config.Dir(filepath.Join("volumes", km.DockerName(), pkgname))
|
|
|
|
|
|
|
|
log.Debug().Msgf("cleanup %s", pkgdir)
|
|
|
|
|
|
|
|
err := os.RemoveAll(pkgdir)
|
|
|
|
if err != nil {
|
|
|
|
log.Warn().Err(err).Msg("cleanup")
|
|
|
|
}
|
|
|
|
}
|