...

Source file src/github.com/Microsoft/hcsshim/cmd/runhcs/main.go

Documentation: github.com/Microsoft/hcsshim/cmd/runhcs

     1  //go:build windows
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"strings"
    10  
    11  	"github.com/Microsoft/go-winio"
    12  	"github.com/Microsoft/go-winio/pkg/etwlogrus"
    13  	"github.com/Microsoft/hcsshim/internal/regstate"
    14  	"github.com/Microsoft/hcsshim/internal/runhcs"
    15  	"github.com/opencontainers/runtime-spec/specs-go"
    16  	"github.com/sirupsen/logrus"
    17  	"github.com/urfave/cli"
    18  )
    19  
    20  // Add a manifest to get proper Windows version detection.
    21  //go:generate go run github.com/josephspurrier/goversioninfo/cmd/goversioninfo -platform-specific
    22  
    23  // version will be populated by the Makefile, read from
    24  // VERSION file of the source code.
    25  var version = ""
    26  
    27  // gitCommit will be the hash that the binary was built from
    28  // and will be populated by the Makefile
    29  var gitCommit = ""
    30  
    31  var stateKey *regstate.Key
    32  
    33  var logFormat string
    34  
    35  const (
    36  	specConfig = "config.json"
    37  	usage      = `Open Container Initiative runtime for Windows
    38  
    39  runhcs is a fork of runc, modified to run containers on Windows with or without Hyper-V isolation.  Like runc, it is a command line client for running applications packaged according to the Open Container Initiative (OCI) format.
    40  
    41  runhcs integrates with existing process supervisors to provide a production container runtime environment for applications. It can be used with your existing process monitoring tools and the container will be spawned as a direct child of the process supervisor.
    42  
    43  Containers are configured using bundles. A bundle for a container is a directory that includes a specification file named "` + specConfig + `".  Bundle contents will depend on the container type.
    44  
    45  To start a new instance of a container:
    46  
    47      # runhcs run [ -b bundle ] <container-id>
    48  
    49  Where "<container-id>" is your name for the instance of the container that you are starting. The name you provide for the container instance must be unique on your host. Providing the bundle directory using "-b" is optional. The default value for "bundle" is the current directory.`
    50  )
    51  
    52  func main() {
    53  	// Provider ID: 0b52781f-b24d-5685-ddf6-69830ed40ec3
    54  	// Hook isn't closed explicitly, as it will exist until process exit.
    55  	if hook, err := etwlogrus.NewHook("Microsoft.Virtualization.RunHCS"); err == nil {
    56  		logrus.AddHook(hook)
    57  	} else {
    58  		logrus.Error(err)
    59  	}
    60  
    61  	app := cli.NewApp()
    62  	app.Name = "runhcs"
    63  	app.Usage = usage
    64  
    65  	var v []string
    66  	if version != "" {
    67  		v = append(v, version)
    68  	}
    69  	if gitCommit != "" {
    70  		v = append(v, fmt.Sprintf("commit: %s", gitCommit))
    71  	}
    72  	v = append(v, fmt.Sprintf("spec: %s", specs.Version))
    73  	app.Version = strings.Join(v, "\n")
    74  
    75  	app.Flags = []cli.Flag{
    76  		cli.BoolFlag{
    77  			Name:  "debug",
    78  			Usage: "enable debug output for logging",
    79  		},
    80  		cli.StringFlag{
    81  			Name:  "log",
    82  			Value: "nul",
    83  			Usage: `set the log file path or named pipe (e.g. \\.\pipe\ProtectedPrefix\Administrators\runhcs-log) where internal debug information is written`,
    84  		},
    85  		cli.StringFlag{
    86  			Name:  "log-format",
    87  			Value: "text",
    88  			Usage: "set the format used by logs ('text' (default), or 'json')",
    89  		},
    90  		cli.StringFlag{
    91  			Name:  "owner",
    92  			Value: "runhcs",
    93  			Usage: "compute system owner",
    94  		},
    95  		cli.StringFlag{
    96  			Name:  "root",
    97  			Value: "default",
    98  			Usage: "registry key for storage of container state",
    99  		},
   100  	}
   101  	app.Commands = []cli.Command{
   102  		createCommand,
   103  		createScratchCommand,
   104  		deleteCommand,
   105  		// eventsCommand,
   106  		execCommand,
   107  		killCommand,
   108  		listCommand,
   109  		pauseCommand,
   110  		prepareDiskCommand,
   111  		psCommand,
   112  		resizeTtyCommand,
   113  		resumeCommand,
   114  		runCommand,
   115  		shimCommand,
   116  		startCommand,
   117  		stateCommand,
   118  		// updateCommand,
   119  		vmshimCommand,
   120  	}
   121  	app.Before = func(context *cli.Context) error {
   122  		if context.GlobalBool("debug") {
   123  			logrus.SetLevel(logrus.DebugLevel)
   124  		}
   125  		if path := context.GlobalString("log"); path != "" {
   126  			var f io.Writer
   127  			var err error
   128  			if strings.HasPrefix(path, runhcs.SafePipePrefix) {
   129  				f, err = winio.DialPipe(path, nil)
   130  			} else {
   131  				f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0666)
   132  			}
   133  			if err != nil {
   134  				return err
   135  			}
   136  			logrus.SetOutput(f)
   137  		}
   138  		switch logFormat = context.GlobalString("log-format"); logFormat {
   139  		case "text":
   140  			// retain logrus's default.
   141  		case "json":
   142  			logrus.SetFormatter(new(logrus.JSONFormatter))
   143  		default:
   144  			return fmt.Errorf("unknown log-format %q", logFormat)
   145  		}
   146  
   147  		var err error
   148  		stateKey, err = regstate.Open(context.GlobalString("root"), false)
   149  		if err != nil {
   150  			return err
   151  		}
   152  		return nil
   153  	}
   154  	// If the command returns an error, cli takes upon itself to print
   155  	// the error on cli.ErrWriter and exit.
   156  	// Use our own writer here to ensure the log gets sent to the right location.
   157  	fatalWriter.Writer = cli.ErrWriter
   158  	cli.ErrWriter = &fatalWriter
   159  	if err := app.Run(os.Args); err != nil {
   160  		fmt.Fprintln(cli.ErrWriter, err)
   161  		os.Exit(1)
   162  	}
   163  }
   164  
   165  type logErrorWriter struct {
   166  	Writer io.Writer
   167  }
   168  
   169  var fatalWriter logErrorWriter
   170  
   171  func (f *logErrorWriter) Write(p []byte) (n int, err error) {
   172  	logrus.Error(string(p))
   173  	return f.Writer.Write(p)
   174  }
   175  

View as plain text