github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/runsc/cmd/create.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package cmd
    16  
    17  import (
    18  	"context"
    19  
    20  	"github.com/google/subcommands"
    21  	"github.com/metacubex/gvisor/runsc/cmd/util"
    22  	"github.com/metacubex/gvisor/runsc/config"
    23  	"github.com/metacubex/gvisor/runsc/container"
    24  	"github.com/metacubex/gvisor/runsc/flag"
    25  	"github.com/metacubex/gvisor/runsc/specutils"
    26  )
    27  
    28  // Create implements subcommands.Command for the "create" command.
    29  type Create struct {
    30  	// bundleDir is the path to the bundle directory (defaults to the
    31  	// current working directory).
    32  	bundleDir string
    33  
    34  	// pidFile is the filename that the sandbox pid will be written to.
    35  	// This file should only be created once the container process inside
    36  	// the sandbox is ready to use.
    37  	pidFile string
    38  
    39  	// consoleSocket is the path to an AF_UNIX socket which will receive a
    40  	// file descriptor referencing the master end of the console's
    41  	// pseudoterminal.  This is ignored unless spec.Process.Terminal is
    42  	// true.
    43  	consoleSocket string
    44  
    45  	// userLog is the path to send user-visible logs to. This log is different
    46  	// from debug logs. The former is meant to be consumed by the users and should
    47  	// contain only information that is relevant to the person running the
    48  	// container, e.g. unsupported syscalls, while the later is more verbose and
    49  	// consumed by developers.
    50  	userLog string
    51  }
    52  
    53  // Name implements subcommands.Command.Name.
    54  func (*Create) Name() string {
    55  	return "create"
    56  }
    57  
    58  // Synopsis implements subcommands.Command.Synopsis.
    59  func (*Create) Synopsis() string {
    60  	return "create a secure container"
    61  }
    62  
    63  // Usage implements subcommands.Command.Usage.
    64  func (*Create) Usage() string {
    65  	return `create [flags] <container id> - create a secure container
    66  `
    67  }
    68  
    69  // SetFlags implements subcommands.Command.SetFlags.
    70  func (c *Create) SetFlags(f *flag.FlagSet) {
    71  	f.StringVar(&c.bundleDir, "bundle", "", "path to the root of the bundle directory, defaults to the current directory")
    72  	f.StringVar(&c.consoleSocket, "console-socket", "", "path to an AF_UNIX socket which will receive a file descriptor referencing the master end of the console's pseudoterminal")
    73  	f.StringVar(&c.pidFile, "pid-file", "", "filename that the container pid will be written to")
    74  	f.StringVar(&c.userLog, "user-log", "", "filename to send user-visible logs to. Empty means no logging.")
    75  }
    76  
    77  // Execute implements subcommands.Command.Execute.
    78  func (c *Create) Execute(_ context.Context, f *flag.FlagSet, args ...any) subcommands.ExitStatus {
    79  	if f.NArg() != 1 {
    80  		f.Usage()
    81  		return subcommands.ExitUsageError
    82  	}
    83  
    84  	id := f.Arg(0)
    85  	conf := args[0].(*config.Config)
    86  
    87  	if conf.Rootless {
    88  		return util.Errorf("Rootless mode not supported with %q", c.Name())
    89  	}
    90  
    91  	bundleDir := c.bundleDir
    92  	if bundleDir == "" {
    93  		bundleDir = getwdOrDie()
    94  	}
    95  	spec, err := specutils.ReadSpec(bundleDir, conf)
    96  	if err != nil {
    97  		return util.Errorf("reading spec: %v", err)
    98  	}
    99  	specutils.LogSpecDebug(spec, conf.OCISeccomp)
   100  
   101  	// Create the container. A new sandbox will be created for the
   102  	// container unless the metadata specifies that it should be run in an
   103  	// existing container.
   104  	contArgs := container.Args{
   105  		ID:            id,
   106  		Spec:          spec,
   107  		BundleDir:     bundleDir,
   108  		ConsoleSocket: c.consoleSocket,
   109  		PIDFile:       c.pidFile,
   110  		UserLog:       c.userLog,
   111  	}
   112  	if _, err := container.New(conf, contArgs); err != nil {
   113  		return util.Errorf("creating container: %v", err)
   114  	}
   115  	return subcommands.ExitSuccess
   116  }