From c9df190d3f584aca8793f9299cb60913edc9e3d2 Mon Sep 17 00:00:00 2001 From: Kai Lueke Date: Tue, 16 Apr 2024 19:38:30 +0900 Subject: [PATCH] kola: Run qemu and swtpm with the machine folder as working dir The long UNIX socket path caused problems and the workaround was to shorten the test names but a real solution is to ensure that the path is always short. This can be done by setting the current working directory for the swtpm process to the machine folder which also holds the socket and, in addition, setting the current working directory for the qemu process to the same folder. Then we can use 'tpm/socket' as path which is ensured to be below the limit of 108 characters. --- kola/tests/misc/tpm.go | 7 +++---- platform/local/cluster.go | 4 ++-- platform/local/configdrive.go | 7 ++++--- platform/local/tpm.go | 36 ++++++++++++++++++++------------ platform/machine/qemu/cluster.go | 21 ++++++++++++------- platform/machine/qemu/machine.go | 4 +++- system/ns/exec.go | 10 ++++++++- 7 files changed, 58 insertions(+), 31 deletions(-) diff --git a/kola/tests/misc/tpm.go b/kola/tests/misc/tpm.go index f0be77a3d..d1e5a51c6 100644 --- a/kola/tests/misc/tpm.go +++ b/kola/tests/misc/tpm.go @@ -252,19 +252,18 @@ func init() { Run: runRootTPMCryptenroll, ClusterSize: 0, Platforms: []string{"qemu"}, - Name: "cl.tpm.root-ce", + Name: "cl.tpm.root-cryptenroll", Distros: []string{"cl"}, MinVersion: semver.Version{Major: 3913, Minor: 0, Patch: 1}, }) runRootTPMCryptenrollPcrNoUpdate := func(c cluster.TestCluster) { tpmTest(c, IgnitionConfigRootCryptenrollPcrNoUpdate, "/", VariantNoUpdate) } - // The test names are part of the UNIX socket path which is limited to 108 chars register.Register(®ister.Test{ Run: runRootTPMCryptenrollPcrNoUpdate, ClusterSize: 0, Platforms: []string{"qemu"}, - Name: "cl.tpm.root-ce-pcr-noupd", + Name: "cl.tpm.root-cryptenroll-pcr-noupdate", Distros: []string{"cl"}, MinVersion: semver.Version{Major: 3913, Minor: 0, Patch: 1}, }) @@ -275,7 +274,7 @@ func init() { Run: runRootTPMCryptenrollPcrWithUpdate, ClusterSize: 0, Platforms: []string{"qemu"}, - Name: "cl.tpm.root-ce-pcr-w-upd", + Name: "cl.tpm.root-cryptenroll-pcr-withupdate", Distros: []string{"cl"}, MinVersion: semver.Version{Major: 3913, Minor: 0, Patch: 1}, }) diff --git a/platform/local/cluster.go b/platform/local/cluster.go index b2ec81b29..233c4193e 100644 --- a/platform/local/cluster.go +++ b/platform/local/cluster.go @@ -40,8 +40,8 @@ type LocalCluster struct { OmahaServer OmahaWrapper } -func (lc *LocalCluster) NewCommand(name string, arg ...string) exec.Cmd { - cmd := ns.Command(lc.flight.nshandle, name, arg...) +func (lc *LocalCluster) NewCommand(dir string, name string, arg ...string) exec.Cmd { + cmd := ns.CommandWithDir(&dir, lc.flight.nshandle, name, arg...) return cmd } diff --git a/platform/local/configdrive.go b/platform/local/configdrive.go index 65e610578..337be625f 100644 --- a/platform/local/configdrive.go +++ b/platform/local/configdrive.go @@ -22,10 +22,11 @@ import ( ) // MakeConfigDrive creates a config drive directory tree under outputDir -// and returns the path to the top level directory. +// and returns the sub dir path to the top level directory, relative to +// outputDir. func MakeConfigDrive(userdata *conf.Conf, outputDir string) (string, error) { - drivePath := path.Join(outputDir, "config-2") - userPath := path.Join(drivePath, "openstack/latest/user_data") + drivePath := "config-2" + userPath := path.Join(outputDir, drivePath, "openstack/latest/user_data") if err := os.MkdirAll(path.Dir(userPath), 0777); err != nil { os.RemoveAll(drivePath) diff --git a/platform/local/tpm.go b/platform/local/tpm.go index b57afe5aa..1924dc9ba 100644 --- a/platform/local/tpm.go +++ b/platform/local/tpm.go @@ -3,6 +3,7 @@ package local import ( "fmt" "os" + "path/filepath" "github.com/coreos/pkg/capnslog" "github.com/flatcar/mantle/system/exec" @@ -10,19 +11,27 @@ import ( ) type SoftwareTPM struct { - process *exec.ExecCmd - socketPath string - dir string + process *exec.ExecCmd + dirFromKolaCwd string + dirFromTestDir string } -func NewSwtpm(dir string) (*SoftwareTPM, error) { - swtpm := &SoftwareTPM{} +func NewSwtpm(testDir string, tpmDir string) (*SoftwareTPM, error) { + dirFromKolaCwd := filepath.Join(testDir, tpmDir) + swtpm := &SoftwareTPM{dirFromKolaCwd: dirFromKolaCwd, dirFromTestDir: tpmDir} - os.Mkdir(dir, 0700) - swtpm.dir = dir - swtpm.socketPath = fmt.Sprintf("%v/sk", swtpm.dir) + if err := os.Mkdir(swtpm.dirFromKolaCwd, 0700); err != nil { + return nil, fmt.Errorf("Failed to create TPM dir: %v", err) + } - swtpm.process = exec.Command("swtpm", "socket", "--tpmstate", fmt.Sprintf("dir=%v", swtpm.dir), "--ctrl", fmt.Sprintf("type=unixio,path=%v", swtpm.socketPath), "--tpm2") + swtpm.process = exec.Command("swtpm", "socket", "--tpmstate", fmt.Sprintf("dir=./%v", swtpm.dirFromTestDir), "--ctrl", fmt.Sprintf("type=unixio,path=./%v", swtpm.SocketRelativePathFromTestDir()), "--tpm2") + // Use the test directory as current working directory + // so that we don't have a socket path argument that + // exceeds 108 chars which is the limit for UNIX sockets + // (Using ./ as prefix helps to know that these are relative + // path arguments). + swtpm.process.Dir = testDir + plog.Debugf("Prepared swtpm process %q with CWD %q", swtpm.process, swtpm.process.Dir) out, err := swtpm.process.StderrPipe() if err != nil { return nil, err @@ -42,10 +51,11 @@ func (swtpm *SoftwareTPM) Stop() { if err := swtpm.process.Kill(); err != nil { plog.Errorf("Error killing swtpm: %v", err) } - plog.Debugf("Delete swtpm temporary directory %v", swtpm.dir) - os.RemoveAll(swtpm.dir) + plog.Debugf("Delete swtpm temporary directory %v", swtpm.dirFromKolaCwd) + os.RemoveAll(swtpm.dirFromKolaCwd) } -func (swtpm *SoftwareTPM) SocketPath() string { - return swtpm.socketPath +func (swtpm *SoftwareTPM) SocketRelativePathFromTestDir() string { + const socket string = "socket" + return filepath.Join(swtpm.dirFromTestDir, socket) } diff --git a/platform/machine/qemu/cluster.go b/platform/machine/qemu/cluster.go index 3df499663..1d97003c7 100644 --- a/platform/machine/qemu/cluster.go +++ b/platform/machine/qemu/cluster.go @@ -88,10 +88,11 @@ ExecStart=/usr/bin/bash -c 'echo "COREOS_CUSTOM_PRIVATE_IPV4=`+ip+`\nCOREOS_CUST ExecStartPost=/usr/bin/ln -fs /run/metadata/flatcar /run/metadata/coreos `, false) + // confPath is relative to the machine folder var confPath string if conf.IsIgnition() { - confPath = filepath.Join(dir, "ignition.json") - if err := conf.WriteFile(confPath); err != nil { + confPath = "ignition.json" + if err := conf.WriteFile(filepath.Join(dir, confPath)); err != nil { return nil, err } } else { @@ -111,16 +112,17 @@ ExecStartPost=/usr/bin/ln -fs /run/metadata/flatcar /run/metadata/coreos id: id, netif: netif, journal: journal, - consolePath: filepath.Join(dir, "console.txt"), + consolePath: "console.txt", + subDir: dir, } var swtpm *local.SoftwareTPM if options.EnableTPM { - swtpm, err = local.NewSwtpm(filepath.Join(dir, "tpm")) + swtpm, err = local.NewSwtpm(qm.subDir, "tpm") if err != nil { return nil, fmt.Errorf("starting swtpm: %v", err) } - options.SoftwareTPMSocket = swtpm.SocketPath() + options.SoftwareTPMSocket = swtpm.SocketRelativePathFromTestDir() defer func() { if swtpm != nil { swtpm.Stop() @@ -128,6 +130,8 @@ ExecStartPost=/usr/bin/ln -fs /run/metadata/flatcar /run/metadata/coreos }() } + // This uses path arguments with path values being + // relative to the folder created for this machine qmCmd, extraFiles, err := platform.CreateQEMUCommand(qc.flight.opts.Board, qm.id, qc.flight.opts.BIOSImage, qm.consolePath, confPath, qc.flight.diskImagePath, conf.IsIgnition(), options) if err != nil { return nil, err @@ -152,9 +156,12 @@ ExecStartPost=/usr/bin/ln -fs /run/metadata/flatcar /run/metadata/coreos fdnum += 1 extraFiles = append(extraFiles, tap.File) - plog.Debugf("NewMachine: %q, %q, %q", qmCmd, qm.IP(), qm.PrivateIP()) + plog.Debugf("NewMachine: %q, cwd: %q, %q, %q", qmCmd, qm.subDir, qm.IP(), qm.PrivateIP()) - qm.qemu = qm.qc.NewCommand(qmCmd[0], qmCmd[1:]...) + // Set qemu's current working directory to the machine folder + // so that we can use short relative links for the UNIX sockets + // without hitting the 108 char limit. + qm.qemu = qm.qc.NewCommand(qm.subDir, qmCmd[0], qmCmd[1:]...) qc.mu.Unlock() diff --git a/platform/machine/qemu/machine.go b/platform/machine/qemu/machine.go index 8b527e724..35083ac9f 100644 --- a/platform/machine/qemu/machine.go +++ b/platform/machine/qemu/machine.go @@ -16,6 +16,7 @@ package qemu import ( "io/ioutil" + "path/filepath" "golang.org/x/crypto/ssh" @@ -32,6 +33,7 @@ type machine struct { journal *platform.Journal consolePath string console string + subDir string swtpm *local.SoftwareTPM } @@ -76,7 +78,7 @@ func (m *machine) Destroy() { } m.journal.Destroy() - if buf, err := ioutil.ReadFile(m.consolePath); err == nil { + if buf, err := ioutil.ReadFile(filepath.Join(m.subDir, m.consolePath)); err == nil { m.console = string(buf) } else { plog.Errorf("Error reading console for instance %v: %v", m.ID(), err) diff --git a/system/ns/exec.go b/system/ns/exec.go index 7f6e6e4ed..c6560a39f 100644 --- a/system/ns/exec.go +++ b/system/ns/exec.go @@ -26,8 +26,16 @@ type Cmd struct { } func Command(ns netns.NsHandle, name string, arg ...string) *Cmd { + return CommandWithDir(nil, ns, name, arg...) +} + +func CommandWithDir(dir *string, ns netns.NsHandle, name string, arg ...string) *Cmd { + cmd := exec.Command(name, arg...) + if dir != nil { + cmd.Dir = *dir + } return &Cmd{ - ExecCmd: exec.Command(name, arg...), + ExecCmd: cmd, NsHandle: ns, } }