runsc: Support `%ID%` substitution in more path flags than just `--debug-log`.

This allows things like CPU profiles to be written out to sandbox-specific
file paths.

PiperOrigin-RevId: 447867091
This commit is contained in:
Etienne Perot 2022-05-10 17:27:53 -07:00 committed by gVisor bot
parent f62143f31f
commit 6af4eedc21
3 changed files with 45 additions and 8 deletions

View File

@ -36,20 +36,52 @@ func putBuf(b *bytes.Buffer) {
bytesBufferPool.Put(b) bytesBufferPool.Put(b)
} }
// FormatRunscLogPath parses runsc config, and fill in %ID% in the log path. // pathLikeFlags are runsc flags which refer to paths to files.
func FormatRunscLogPath(id string, config map[string]string) { var pathLikeFlags = []string{
if path, ok := config["debug-log"]; ok { "log",
config["debug-log"] = strings.Replace(path, "%ID%", id, -1) "panic-log",
"debug-log",
"coverage-report",
"profile-block",
"profile-cpu",
"profile-heap",
"profile-mutex",
"trace",
}
// replaceID replaces %ID% in `path` with the given sandbox ID.
func replaceID(id string, path string) string {
return strings.Replace(path, "%ID%", id, -1)
}
// EmittedPaths returns a list of file paths that the sandbox may need to
// create using the given configuration. Useful to create parent directories.
func EmittedPaths(id string, config map[string]string) []string {
var paths []string
for _, cfgFlag := range pathLikeFlags {
if path, ok := config[cfgFlag]; ok {
paths = append(paths, replaceID(id, path))
}
}
return paths
}
// FormatRunscPaths fills in %ID% in path-like flags.
func FormatRunscPaths(id string, config map[string]string) {
for _, cfgFlag := range pathLikeFlags {
if path, ok := config[cfgFlag]; ok {
config[cfgFlag] = replaceID(id, path)
}
} }
} }
// FormatShimLogPath creates the file path to the log file. It replaces %ID% // FormatShimLogPath creates the file path to the log file. It replaces %ID%
// in the path with the provided "id". It also uses a default log name if the // in the path with the provided "id". It also uses a default log name if the
// path end with '/'. // path ends with '/'.
func FormatShimLogPath(path string, id string) string { func FormatShimLogPath(path string, id string) string {
if strings.HasSuffix(path, "/") { if strings.HasSuffix(path, "/") {
// Default format: <path>/runsc-shim-<ID>.log // Default format: <path>/runsc-shim-<ID>.log
path += "runsc-shim-%ID%.log" path += "runsc-shim-%ID%.log"
} }
return strings.Replace(path, "%ID%", id, -1) return replaceID(id, path)
} }

View File

@ -401,6 +401,11 @@ func (s *service) create(ctx context.Context, r *taskAPI.CreateTaskRequest) (*ta
} }
logrus.SetLevel(lvl) logrus.SetLevel(lvl)
} }
for _, emittedPath := range runsc.EmittedPaths(s.id, s.opts.RunscConfig) {
if err := os.MkdirAll(filepath.Dir(emittedPath), 0777); err != nil {
return nil, fmt.Errorf("failed to create parent directories for file %v: %w", emittedPath, err)
}
}
if len(s.opts.LogPath) != 0 { if len(s.opts.LogPath) != 0 {
logPath := runsc.FormatShimLogPath(s.opts.LogPath, s.id) logPath := runsc.FormatShimLogPath(s.opts.LogPath, s.id)
if err := os.MkdirAll(filepath.Dir(logPath), 0777); err != nil { if err := os.MkdirAll(filepath.Dir(logPath), 0777); err != nil {
@ -1076,7 +1081,7 @@ func newInit(path, workDir, namespace string, platform stdio.Platform, r *proc.C
} }
} }
runsc.FormatRunscLogPath(r.ID, options.RunscConfig) runsc.FormatRunscPaths(r.ID, options.RunscConfig)
runtime := proc.NewRunsc(options.Root, path, namespace, options.BinaryName, options.RunscConfig) runtime := proc.NewRunsc(options.Root, path, namespace, options.BinaryName, options.RunscConfig)
p := proc.New(r.ID, runtime, stdio.Stdio{ p := proc.New(r.ID, runtime, stdio.Stdio{
Stdin: r.Stdin, Stdin: r.Stdin,

View File

@ -178,7 +178,7 @@ type Config struct {
// Controls defines the controls that may be enabled. // Controls defines the controls that may be enabled.
Controls controlConfig `flag:"controls"` Controls controlConfig `flag:"controls"`
// RestoreFile is the path to the saved container image // RestoreFile is the path to the saved container image.
RestoreFile string RestoreFile string
// NumNetworkChannels controls the number of AF_PACKET sockets that map // NumNetworkChannels controls the number of AF_PACKET sockets that map