treewide: replace hardcoded runfiles paths
We hardcoded some of the runfiles paths to find specific files. This replaces the hardcoded paths by a call to rlocationpath. This prevents running a target without the correct dependencies at build time instead of at runtime
Change-Id: I7ce56935ac80be6b28b824ccb0781ab401bd6521
Reviewed-on: https://review.monogon.dev/c/monogon/+/3301
Reviewed-by: Serge Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/test/e2e/suites/core/BUILD.bazel b/metropolis/test/e2e/suites/core/BUILD.bazel
index e3ccc59..a8c90ad 100644
--- a/metropolis/test/e2e/suites/core/BUILD.bazel
+++ b/metropolis/test/e2e/suites/core/BUILD.bazel
@@ -4,9 +4,7 @@
name = "core_test",
srcs = ["run_test.go"],
data = [
- "//metropolis/node:image",
"//metropolis/test/e2e:testimages_manifest",
- "//third_party/edk2:firmware",
],
tags = [
"resources:iops:5000",
@@ -14,6 +12,9 @@
# 2x2048 for nodes plus some extra.
"resources:ram:4500",
],
+ x_defs = {
+ "xTestImagesManifestPath": "$(rlocationpath //metropolis/test/e2e:testimages_manifest )",
+ },
deps = [
"//metropolis/node",
"//metropolis/node/core/rpc",
diff --git a/metropolis/test/e2e/suites/core/run_test.go b/metropolis/test/e2e/suites/core/run_test.go
index 21640a6..c8f654f 100644
--- a/metropolis/test/e2e/suites/core/run_test.go
+++ b/metropolis/test/e2e/suites/core/run_test.go
@@ -28,6 +28,25 @@
cpb "source.monogon.dev/metropolis/proto/common"
)
+var (
+ // These are filled by bazel at linking time with the canonical path of
+ // their corresponding file. Inside the init function we resolve it
+ // with the rules_go runfiles package to the real path.
+ xTestImagesManifestPath string
+)
+
+func init() {
+ var err error
+ for _, path := range []*string{
+ &xTestImagesManifestPath,
+ } {
+ *path, err = runfiles.Rlocation(*path)
+ if err != nil {
+ panic(err)
+ }
+ }
+}
+
const (
// Timeout for the global test context.
//
@@ -49,11 +68,7 @@
ctx, cancel := context.WithTimeout(context.Background(), globalTestTimeout)
defer cancel()
- rPath, err := runfiles.Rlocation("_main/metropolis/test/e2e/testimages_manifest.prototxt")
- if err != nil {
- t.Fatalf("Resolving registry manifest failed: %v", err)
- }
- df, err := os.ReadFile(rPath)
+ df, err := os.ReadFile(xTestImagesManifestPath)
if err != nil {
t.Fatalf("Reading registry manifest failed: %v", err)
}
diff --git a/metropolis/test/e2e/suites/ha/BUILD.bazel b/metropolis/test/e2e/suites/ha/BUILD.bazel
index 5a2a4dd..3d9c688 100644
--- a/metropolis/test/e2e/suites/ha/BUILD.bazel
+++ b/metropolis/test/e2e/suites/ha/BUILD.bazel
@@ -4,9 +4,7 @@
name = "ha_test",
srcs = ["run_test.go"],
data = [
- "//metropolis/node:image",
"//metropolis/test/e2e:testimages_manifest",
- "//third_party/edk2:firmware",
],
tags = [
"resources:iops:5000",
@@ -14,6 +12,9 @@
# 3x2048 for nodes plus some extra.
"resources:ram:7000",
],
+ x_defs = {
+ "xTestImagesManifestPath": "$(rlocationpath //metropolis/test/e2e:testimages_manifest )",
+ },
deps = [
"//metropolis/test/launch",
"//metropolis/test/localregistry",
diff --git a/metropolis/test/e2e/suites/ha/run_test.go b/metropolis/test/e2e/suites/ha/run_test.go
index cc02df4..f2f7cc2 100644
--- a/metropolis/test/e2e/suites/ha/run_test.go
+++ b/metropolis/test/e2e/suites/ha/run_test.go
@@ -15,6 +15,25 @@
"source.monogon.dev/osbase/test/launch"
)
+var (
+ // These are filled by bazel at linking time with the canonical path of
+ // their corresponding file. Inside the init function we resolve it
+ // with the rules_go runfiles package to the real path.
+ xTestImagesManifestPath string
+)
+
+func init() {
+ var err error
+ for _, path := range []*string{
+ &xTestImagesManifestPath,
+ } {
+ *path, err = runfiles.Rlocation(*path)
+ if err != nil {
+ panic(err)
+ }
+ }
+}
+
const (
// Timeout for the global test context.
//
@@ -35,11 +54,7 @@
ctx, cancel := context.WithTimeout(context.Background(), globalTestTimeout)
defer cancel()
- rPath, err := runfiles.Rlocation("_main/metropolis/test/e2e/testimages_manifest.prototxt")
- if err != nil {
- t.Fatalf("Resolving registry manifest failed: %v", err)
- }
- df, err := os.ReadFile(rPath)
+ df, err := os.ReadFile(xTestImagesManifestPath)
if err != nil {
t.Fatalf("Reading registry manifest failed: %v", err)
}
diff --git a/metropolis/test/e2e/suites/kubernetes/BUILD.bazel b/metropolis/test/e2e/suites/kubernetes/BUILD.bazel
index 6234e94..302f3ac 100644
--- a/metropolis/test/e2e/suites/kubernetes/BUILD.bazel
+++ b/metropolis/test/e2e/suites/kubernetes/BUILD.bazel
@@ -20,9 +20,7 @@
name = "kubernetes_test",
srcs = ["run_test.go"],
data = [
- "//metropolis/node:image",
"//metropolis/test/e2e:testimages_manifest",
- "//third_party/edk2:firmware",
],
embed = [":kubernetes"],
tags = [
@@ -31,6 +29,9 @@
# 2x2048 for nodes plus some extra.
"resources:ram:4500",
],
+ x_defs = {
+ "xTestImagesManifestPath": "$(rlocationpath //metropolis/test/e2e:testimages_manifest )",
+ },
deps = [
"//metropolis/node",
"//metropolis/test/launch",
diff --git a/metropolis/test/e2e/suites/kubernetes/run_test.go b/metropolis/test/e2e/suites/kubernetes/run_test.go
index f15fafd..3608c3c 100644
--- a/metropolis/test/e2e/suites/kubernetes/run_test.go
+++ b/metropolis/test/e2e/suites/kubernetes/run_test.go
@@ -30,6 +30,25 @@
common "source.monogon.dev/metropolis/node"
)
+var (
+ // These are filled by bazel at linking time with the canonical path of
+ // their corresponding file. Inside the init function we resolve it
+ // with the rules_go runfiles package to the real path.
+ xTestImagesManifestPath string
+)
+
+func init() {
+ var err error
+ for _, path := range []*string{
+ &xTestImagesManifestPath,
+ } {
+ *path, err = runfiles.Rlocation(*path)
+ if err != nil {
+ panic(err)
+ }
+ }
+}
+
const (
// Timeout for the global test context.
//
@@ -50,11 +69,7 @@
ctx, cancel := context.WithTimeout(context.Background(), globalTestTimeout)
defer cancel()
- rPath, err := runfiles.Rlocation("_main/metropolis/test/e2e/testimages_manifest.prototxt")
- if err != nil {
- t.Fatalf("Resolving registry manifest failed: %v", err)
- }
- df, err := os.ReadFile(rPath)
+ df, err := os.ReadFile(xTestImagesManifestPath)
if err != nil {
t.Fatalf("Reading registry manifest failed: %v", err)
}
diff --git a/metropolis/test/launch/BUILD.bazel b/metropolis/test/launch/BUILD.bazel
index 1b7ee4d..d494a6b 100644
--- a/metropolis/test/launch/BUILD.bazel
+++ b/metropolis/test/launch/BUILD.bazel
@@ -5,24 +5,39 @@
srcs = [
"cluster.go",
"insecure_key.go",
+ "launch.go",
"metroctl.go",
"prefixed_stdio.go",
"swtpm.go",
],
data = [
+ "//metropolis/cli/metroctl",
"//metropolis/node:image",
"//metropolis/test/nanoswitch:initramfs",
"//metropolis/test/swtpm/certtool",
"//metropolis/test/swtpm/swtpm_cert",
"//osbase/test/ktest:linux-testing",
- "//third_party/edk2:firmware",
- "@com_github_bonzini_qboot//:qboot-bin",
+ "//third_party/edk2:OVMF_CODE.fd",
+ "//third_party/edk2:OVMF_VARS.fd",
"@swtpm",
"@swtpm//:swtpm_localca",
"@swtpm//:swtpm_setup",
],
importpath = "source.monogon.dev/metropolis/test/launch",
visibility = ["//visibility:public"],
+ x_defs = {
+ "xSwtpmPath": "$(rlocationpath @swtpm )",
+ "xSwtpmSetupPath": "$(rlocationpath @swtpm//:swtpm_setup )",
+ "xSwtpmLocalCAPath": "$(rlocationpath @swtpm//:swtpm_localca )",
+ "xSwtpmCertPath": "$(rlocationpath //metropolis/test/swtpm/swtpm_cert )",
+ "xCerttoolPath": "$(rlocationpath //metropolis/test/swtpm/certtool )",
+ "xMetroctlPath": "$(rlocationpath //metropolis/cli/metroctl )",
+ "xOvmfVarsPath": "$(rlocationpath //third_party/edk2:OVMF_VARS.fd )",
+ "xOvmfCodePath": "$(rlocationpath //third_party/edk2:OVMF_CODE.fd )",
+ "xKernelPath": "$(rlocationpath //osbase/test/ktest:linux-testing )",
+ "xInitramfsPath": "$(rlocationpath //metropolis/test/nanoswitch:initramfs )",
+ "xNodeImagePath": "$(rlocationpath //metropolis/node:image )",
+ },
deps = [
"//go/qcow2",
"//metropolis/cli/metroctl/core",
diff --git a/metropolis/test/launch/cli/launch-cluster/BUILD.bazel b/metropolis/test/launch/cli/launch-cluster/BUILD.bazel
index 9e48795..a952abd 100644
--- a/metropolis/test/launch/cli/launch-cluster/BUILD.bazel
+++ b/metropolis/test/launch/cli/launch-cluster/BUILD.bazel
@@ -14,9 +14,6 @@
go_binary(
name = "launch-cluster",
- data = [
- "//metropolis/cli/metroctl",
- ],
embed = [":launch-cluster_lib"],
visibility = ["//visibility:public"],
)
diff --git a/metropolis/test/launch/cli/launch-cluster/main.go b/metropolis/test/launch/cli/launch-cluster/main.go
index 1529396..695fcc7 100644
--- a/metropolis/test/launch/cli/launch-cluster/main.go
+++ b/metropolis/test/launch/cli/launch-cluster/main.go
@@ -20,6 +20,7 @@
"context"
"log"
"os"
+ "os/exec"
"os/signal"
metroctl "source.monogon.dev/metropolis/cli/metroctl/core"
@@ -36,10 +37,6 @@
log.Fatalf("LaunchCluster: %v", err)
}
- mpath, err := mlaunch.MetroctlRunfilePath()
- if err != nil {
- log.Fatalf("MetroctlRunfilePath: %v", err)
- }
wpath, err := cl.MakeMetroctlWrapper()
if err != nil {
log.Fatalf("MakeWrapper: %v", err)
@@ -53,8 +50,19 @@
log.Fatalf("Cluster has no Kubernetes controller nodes")
}
+ // If the user has metroctl in their path, use the metroctl from path as
+ // a credential plugin. Otherwise use the path to the currently-running
+ // metroctl.
+ metroctlPath := "metroctl"
+ if _, err := exec.LookPath("metroctl"); err != nil {
+ metroctlPath, err = os.Executable()
+ if err != nil {
+ log.Fatalf("Failed to create kubectl entry as metroctl is neither in PATH nor can its absolute path be determined: %v", err)
+ }
+ }
+
configName := "launch-cluster"
- if err := metroctl.InstallKubeletConfig(ctx, mpath, cl.ConnectOptions(), configName, apiservers[0]); err != nil {
+ if err := metroctl.InstallKubeletConfig(ctx, metroctlPath, cl.ConnectOptions(), configName, apiservers[0]); err != nil {
log.Fatalf("InstallKubeletConfig: %v", err)
}
diff --git a/metropolis/test/launch/cluster.go b/metropolis/test/launch/cluster.go
index ac8a017..98ab760 100644
--- a/metropolis/test/launch/cluster.go
+++ b/metropolis/test/launch/cluster.go
@@ -26,7 +26,6 @@
"syscall"
"time"
- "github.com/bazelbuild/rules_go/go/runfiles"
"github.com/cenkalti/backoff/v4"
"go.uber.org/multierr"
"golang.org/x/net/proxy"
@@ -140,30 +139,21 @@
}
// Initialize the node's storage with a prebuilt image.
- si, err := runfiles.Rlocation("_main/metropolis/node/image.img")
- if err != nil {
- return nil, fmt.Errorf("while resolving a path: %w", err)
- }
-
di := filepath.Join(stdp, "image.qcow2")
- launch.Log("Cluster: generating node QCOW2 snapshot image: %s -> %s", si, di)
+ launch.Log("Cluster: generating node QCOW2 snapshot image: %s -> %s", xNodeImagePath, di)
df, err := os.Create(di)
if err != nil {
return nil, fmt.Errorf("while opening image for writing: %w", err)
}
defer df.Close()
- if err := qcow2.Generate(df, qcow2.GenerateWithBackingFile(si)); err != nil {
+ if err := qcow2.Generate(df, qcow2.GenerateWithBackingFile(xNodeImagePath)); err != nil {
return nil, fmt.Errorf("while creating copy-on-write node image: %w", err)
}
// Initialize the OVMF firmware variables file.
- sv, err := runfiles.Rlocation("edk2/OVMF_VARS.fd")
- if err != nil {
- return nil, fmt.Errorf("while resolving a path: %w", err)
- }
- dv := filepath.Join(stdp, filepath.Base(sv))
- if err := copyFile(sv, dv); err != nil {
+ dv := filepath.Join(stdp, filepath.Base(xOvmfVarsPath))
+ if err := copyFile(xOvmfVarsPath, dv); err != nil {
return nil, fmt.Errorf("while copying firmware variables: %w", err)
}
@@ -268,18 +258,13 @@
options.Mac = mac
}
- ovmfCodePath, err := runfiles.Rlocation("edk2/OVMF_CODE.fd")
- if err != nil {
- return err
- }
-
tpmSocketPath := filepath.Join(r.sd, "tpm-socket")
fwVarPath := filepath.Join(r.ld, "OVMF_VARS.fd")
storagePath := filepath.Join(r.ld, "image.qcow2")
qemuArgs := []string{
"-machine", "q35", "-accel", "kvm", "-nographic", "-nodefaults", "-m", "2048",
"-cpu", "host", "-smp", "sockets=1,cpus=1,cores=2,threads=2,maxcpus=4",
- "-drive", "if=pflash,format=raw,readonly=on,file=" + ovmfCodePath,
+ "-drive", "if=pflash,format=raw,readonly=on,file=" + xOvmfCodePath,
"-drive", "if=pflash,format=raw,file=" + fwVarPath,
"-drive", "if=virtio,format=qcow2,cache=unsafe,file=" + storagePath,
"-netdev", qemuNetConfig.ToOption(qemuNetType),
@@ -318,7 +303,7 @@
// Manufacture TPM if needed.
tpmd := filepath.Join(r.ld, "tpm")
- err = tpmFactory.Manufacture(ctx, tpmd, &TPMPlatform{
+ err := tpmFactory.Manufacture(ctx, tpmd, &TPMPlatform{
Manufacturer: "Monogon",
Version: "1.0",
Model: "TestCluster",
@@ -328,14 +313,9 @@
}
// Start TPM emulator as a subprocess
- swtpm, err := runfiles.Rlocation("swtpm/swtpm")
- if err != nil {
- return fmt.Errorf("could not find swtpm: %w", err)
- }
-
tpmCtx, tpmCancel := context.WithCancel(options.Runtime.ctxT)
- tpmEmuCmd := exec.CommandContext(tpmCtx, swtpm, "socket", "--tpm2", "--tpmstate", "dir="+tpmd, "--ctrl", "type=unixio,path="+tpmSocketPath)
+ tpmEmuCmd := exec.CommandContext(tpmCtx, xSwtpmPath, "socket", "--tpm2", "--tpmstate", "dir="+tpmd, "--ctrl", "type=unixio,path="+tpmSocketPath)
// Silence warnings from unsafe libtpms build (uses non-constant-time
// cryptographic operations).
tpmEmuCmd.Env = append(tpmEmuCmd.Env, "MONOGON_LIBTPMS_ACKNOWLEDGE_UNSAFE=yes")
@@ -854,18 +834,10 @@
} else {
serialPort = newPrefixedStdio(99)
}
- kernelPath, err := runfiles.Rlocation("_main/osbase/test/ktest/vmlinux")
- if err != nil {
- launch.Fatal("Failed to resolved nanoswitch kernel: %v", err)
- }
- initramfsPath, err := runfiles.Rlocation("_main/metropolis/test/nanoswitch/initramfs.cpio.zst")
- if err != nil {
- launch.Fatal("Failed to resolved nanoswitch initramfs: %v", err)
- }
if err := launch.RunMicroVM(ctxT, &launch.MicroVMOptions{
Name: "nanoswitch",
- KernelPath: kernelPath,
- InitramfsPath: initramfsPath,
+ KernelPath: xKernelPath,
+ InitramfsPath: xInitramfsPath,
ExtraNetworkInterfaces: switchPorts,
PortMap: portMap,
GuestServiceMap: guestSvcMap,
diff --git a/metropolis/test/launch/launch.go b/metropolis/test/launch/launch.go
new file mode 100644
index 0000000..d6c29fe
--- /dev/null
+++ b/metropolis/test/launch/launch.go
@@ -0,0 +1,37 @@
+package launch
+
+import (
+ "github.com/bazelbuild/rules_go/go/runfiles"
+)
+
+var (
+ // These are filled by bazel at linking time with the canonical path of
+ // their corresponding file. Inside the init function we resolve it
+ // with the rules_go runfiles package to the real path.
+ xSwtpmPath string
+ xSwtpmSetupPath string
+ xSwtpmLocalCAPath string
+ xSwtpmCertPath string
+ xCerttoolPath string
+ xMetroctlPath string
+ xOvmfCodePath string
+ xOvmfVarsPath string
+ xKernelPath string
+ xInitramfsPath string
+ xNodeImagePath string
+)
+
+func init() {
+ var err error
+ for _, path := range []*string{
+ &xSwtpmPath, &xSwtpmSetupPath, &xSwtpmLocalCAPath,
+ &xSwtpmCertPath, &xCerttoolPath, &xMetroctlPath,
+ &xOvmfCodePath, &xOvmfVarsPath, &xKernelPath,
+ &xInitramfsPath, &xNodeImagePath,
+ } {
+ *path, err = runfiles.Rlocation(*path)
+ if err != nil {
+ panic(err)
+ }
+ }
+}
diff --git a/metropolis/test/launch/metroctl.go b/metropolis/test/launch/metroctl.go
index e3196a6..711855b 100644
--- a/metropolis/test/launch/metroctl.go
+++ b/metropolis/test/launch/metroctl.go
@@ -9,25 +9,11 @@
"path"
"sort"
- "github.com/bazelbuild/rules_go/go/runfiles"
"github.com/kballard/go-shellquote"
metroctl "source.monogon.dev/metropolis/cli/metroctl/core"
)
-const metroctlRunfile = "_main/metropolis/cli/metroctl/metroctl_/metroctl"
-
-// MetroctlRunfilePath returns the absolute path to the metroctl binary available
-// if the built target depends on //metropolis/cli/metroctl. Otherwise, an error
-// is returned.
-func MetroctlRunfilePath() (string, error) {
- path, err := runfiles.Rlocation(metroctlRunfile)
- if err != nil {
- return "", fmt.Errorf("//metropolis/cli/metroctl not found in runfiles, did you include it as a data dependency? error: %w", err)
- }
- return path, nil
-}
-
type acceptall struct{}
func (a *acceptall) Ask(ctx context.Context, _ *metroctl.ConnectOptions, _ *x509.Certificate) (bool, error) {
@@ -63,10 +49,6 @@
// dependency of the built target) with all the required flags to connect to the
// launched cluster.
func (c *Cluster) MakeMetroctlWrapper() (string, error) {
- mpath, err := MetroctlRunfilePath()
- if err != nil {
- return "", err
- }
wpath := path.Join(c.metroctlDir, "metroctl.sh")
// Don't create wrapper if it already exists.
@@ -74,7 +56,7 @@
return wpath, nil
}
- wrapper := fmt.Sprintf("#!/usr/bin/env bash\nexec %s %s \"$@\"", mpath, c.MetroctlFlags())
+ wrapper := fmt.Sprintf("#!/usr/bin/env bash\nexec %s %s \"$@\"", xMetroctlPath, c.MetroctlFlags())
if err := os.WriteFile(wpath, []byte(wrapper), 0555); err != nil {
return "", fmt.Errorf("could not write wrapper: %w", err)
}
diff --git a/metropolis/test/launch/swtpm.go b/metropolis/test/launch/swtpm.go
index fa5cb78..5691c86 100644
--- a/metropolis/test/launch/swtpm.go
+++ b/metropolis/test/launch/swtpm.go
@@ -10,8 +10,6 @@
"sort"
"strings"
- "github.com/bazelbuild/rules_go/go/runfiles"
-
"source.monogon.dev/osbase/test/launch"
)
@@ -111,29 +109,6 @@
launch.Log("Skipping manufacturing TPM for %s, already exists", path)
return nil
}
-
- // Find all tools.
- swtpm, err := runfiles.Rlocation("swtpm/swtpm")
- if err != nil {
- return fmt.Errorf("could not find swtpm: %w", err)
- }
- swtpmSetup, err := runfiles.Rlocation("swtpm/swtpm_setup")
- if err != nil {
- return fmt.Errorf("could not find swtpm_setup: %w", err)
- }
- swtpmLocalca, err := runfiles.Rlocation("swtpm/swtpm_localca")
- if err != nil {
- return fmt.Errorf("could not find swtpm_localca: %w", err)
- }
- swtpmCert, err := runfiles.Rlocation("_main/metropolis/test/swtpm/swtpm_cert/swtpm_cert_/swtpm_cert")
- if err != nil {
- return fmt.Errorf("could not find swtpm_cert: %w", err)
- }
- certtool, err := runfiles.Rlocation("_main/metropolis/test/swtpm/certtool/certtool_/certtool")
- if err != nil {
- return fmt.Errorf("could not find certtool: %w", err)
- }
-
// Prepare swtpm-localca.options.
options := []string{
"--platform-manufacturer " + platform.Manufacturer,
@@ -141,14 +116,14 @@
"--platform-model " + platform.Model,
"",
}
- err = os.WriteFile(f.localCAOptionsPath(), []byte(strings.Join(options, "\n")), 0600)
+ err := os.WriteFile(f.localCAOptionsPath(), []byte(strings.Join(options, "\n")), 0600)
if err != nil {
return fmt.Errorf("could not write local options: %w", err)
}
// Prepare swptm.conf.
err = writeSWTPMConfig(f.swtpmConfPath(), map[string]string{
- "create_certs_tool": swtpmLocalca,
+ "create_certs_tool": xSwtpmLocalCAPath,
"create_certs_tool_config": f.localCAConfPath(),
"create_certs_tool_options": f.localCAOptionsPath(),
})
@@ -159,8 +134,8 @@
if err := os.MkdirAll(path, 0700); err != nil {
return fmt.Errorf("could not make output path: %w", err)
}
- cmd := exec.CommandContext(ctx, swtpmSetup,
- "--tpm", fmt.Sprintf("%s socket", swtpm),
+ cmd := exec.CommandContext(ctx, xSwtpmSetupPath,
+ "--tpm", fmt.Sprintf("%s socket", xSwtpmPath),
"--tpmstate", path,
"--create-ek-cert",
"--create-platform-cert",
@@ -169,7 +144,7 @@
"--display",
"--pcr-banks", "sha1,sha256,sha384,sha512",
"--config", f.swtpmConfPath())
- cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s:%s", filepath.Dir(swtpmCert), filepath.Dir(certtool)))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s:%s", filepath.Dir(xSwtpmCertPath), filepath.Dir(xCerttoolPath)))
cmd.Env = append(cmd.Env, "MONOGON_LIBTPMS_ACKNOWLEDGE_UNSAFE=yes")
if out, err := cmd.CombinedOutput(); err != nil {
log.Printf("Manufacturing TPM for %s failed: swtm_setup: %s", path, out)