cri-o/cmd/crio/main.go
Dan Walsh 4493b6f176 Rename ocid to crio.
The ocid project was renamed to CRI-O, months ago, it is time that we moved
all of the code to the new name.  We want to elminate the name ocid from use.
Move fully to crio.

Also cric is being renamed to crioctl for the time being.

Signed-off-by: Dan Walsh <dwalsh@redhat.com>
2017-05-12 09:56:06 -04:00

331 lines
7.8 KiB
Go

package main
import (
"fmt"
"net"
"os"
"os/signal"
"sort"
"strings"
"syscall"
"runtime/pprof"
"github.com/Sirupsen/logrus"
"github.com/containers/storage/pkg/reexec"
"github.com/kubernetes-incubator/cri-o/server"
"github.com/opencontainers/selinux/go-selinux"
"github.com/urfave/cli"
"google.golang.org/grpc"
"k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)
const ociConfigPath = "/etc/crio/crio.conf"
func mergeConfig(config *server.Config, ctx *cli.Context) error {
// Don't parse the config if the user explicitly set it to "".
if path := ctx.GlobalString("config"); path != "" {
if err := config.FromFile(path); err != nil {
if ctx.GlobalIsSet("config") || !os.IsNotExist(err) {
return err
}
// We don't error out if --config wasn't explicitly set and the
// default doesn't exist. But we will log a warning about it, so
// the user doesn't miss it.
logrus.Warnf("default configuration file does not exist: %s", ociConfigPath)
}
}
// Override options set with the CLI.
if ctx.GlobalIsSet("conmon") {
config.Conmon = ctx.GlobalString("conmon")
}
if ctx.GlobalIsSet("pause-command") {
config.PauseCommand = ctx.GlobalString("pause-command")
}
if ctx.GlobalIsSet("pause-image") {
config.PauseImage = ctx.GlobalString("pause-image")
}
if ctx.GlobalIsSet("signature-policy") {
config.SignaturePolicyPath = ctx.GlobalString("signature-policy")
}
if ctx.GlobalIsSet("root") {
config.Root = ctx.GlobalString("root")
}
if ctx.GlobalIsSet("runroot") {
config.RunRoot = ctx.GlobalString("runroot")
}
if ctx.GlobalIsSet("storage-driver") {
config.Storage = ctx.GlobalString("storage-driver")
}
if ctx.GlobalIsSet("storage-opt") {
config.StorageOptions = ctx.GlobalStringSlice("storage-opt")
}
if ctx.GlobalIsSet("default-transport") {
config.DefaultTransport = ctx.GlobalString("default-transport")
}
if ctx.GlobalIsSet("listen") {
config.Listen = ctx.GlobalString("listen")
}
if ctx.GlobalIsSet("runtime") {
config.Runtime = ctx.GlobalString("runtime")
}
if ctx.GlobalIsSet("selinux") {
config.SELinux = ctx.GlobalBool("selinux")
}
if ctx.GlobalIsSet("seccomp-profile") {
config.SeccompProfile = ctx.GlobalString("seccomp-profile")
}
if ctx.GlobalIsSet("apparmor-profile") {
config.ApparmorProfile = ctx.GlobalString("apparmor-profile")
}
if ctx.GlobalIsSet("cgroup-manager") {
config.CgroupManager = ctx.GlobalString("cgroup-manager")
}
if ctx.GlobalIsSet("cni-config-dir") {
config.NetworkDir = ctx.GlobalString("cni-config-dir")
}
if ctx.GlobalIsSet("cni-plugin-dir") {
config.PluginDir = ctx.GlobalString("cni-plugin-dir")
}
return nil
}
func catchShutdown(gserver *grpc.Server, sserver *server.Server, signalled *bool) {
sig := make(chan os.Signal, 10)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
go func() {
for s := range sig {
switch s {
case syscall.SIGINT:
logrus.Debugf("Caught SIGINT")
case syscall.SIGTERM:
logrus.Debugf("Caught SIGTERM")
default:
continue
}
*signalled = true
gserver.GracefulStop()
return
}
}()
}
func main() {
if reexec.Init() {
return
}
app := cli.NewApp()
app.Name = "crio"
app.Usage = "crio server"
app.Version = "0.3"
app.Metadata = map[string]interface{}{
"config": server.DefaultConfig(),
}
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "config",
Value: ociConfigPath,
Usage: "path to configuration file",
},
cli.StringFlag{
Name: "conmon",
Usage: "path to the conmon executable",
},
cli.BoolFlag{
Name: "debug",
Usage: "enable debug output for logging",
},
cli.StringFlag{
Name: "listen",
Usage: "path to crio socket",
},
cli.StringFlag{
Name: "log",
Value: "",
Usage: "set the log file path where internal debug information is written",
},
cli.StringFlag{
Name: "log-format",
Value: "text",
Usage: "set the format used by logs ('text' (default), or 'json')",
},
cli.StringFlag{
Name: "pause-command",
Usage: "name of the pause command in the pause image",
},
cli.StringFlag{
Name: "pause-image",
Usage: "name of the pause image",
},
cli.StringFlag{
Name: "signature-policy",
Usage: "path to signature policy file",
},
cli.StringFlag{
Name: "root",
Usage: "crio root dir",
},
cli.StringFlag{
Name: "runroot",
Usage: "crio state dir",
},
cli.StringFlag{
Name: "storage-driver",
Usage: "storage driver",
},
cli.StringSliceFlag{
Name: "storage-opt",
Usage: "storage driver option",
},
cli.StringFlag{
Name: "default-transport",
Usage: "default transport",
},
cli.StringFlag{
Name: "runtime",
Usage: "OCI runtime path",
},
cli.StringFlag{
Name: "seccomp-profile",
Usage: "default seccomp profile path",
},
cli.StringFlag{
Name: "apparmor-profile",
Usage: "default apparmor profile name (default: \"crio-default\")",
},
cli.BoolFlag{
Name: "selinux",
Usage: "enable selinux support",
},
cli.StringFlag{
Name: "cgroup-manager",
Usage: "cgroup manager (cgroupfs or systemd)",
},
cli.StringFlag{
Name: "cni-config-dir",
Usage: "CNI configuration files directory",
},
cli.StringFlag{
Name: "cni-plugin-dir",
Usage: "CNI plugin binaries directory",
},
cli.StringFlag{
Name: "cpu-profile",
Usage: "set the CPU profile file path",
},
}
sort.Sort(cli.FlagsByName(app.Flags))
sort.Sort(cli.FlagsByName(configCommand.Flags))
app.Commands = []cli.Command{
configCommand,
}
app.Before = func(c *cli.Context) error {
// Load the configuration file.
config := c.App.Metadata["config"].(*server.Config)
if err := mergeConfig(config, c); err != nil {
return err
}
cf := &logrus.TextFormatter{
TimestampFormat: "2006-01-02 15:04:05.000000000Z07:00",
FullTimestamp: true,
}
logrus.SetFormatter(cf)
if c.GlobalBool("debug") {
logrus.SetLevel(logrus.DebugLevel)
}
if path := c.GlobalString("log"); path != "" {
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0666)
if err != nil {
return err
}
logrus.SetOutput(f)
}
switch c.GlobalString("log-format") {
case "text":
// retain logrus's default.
case "json":
logrus.SetFormatter(new(logrus.JSONFormatter))
default:
return fmt.Errorf("unknown log-format %q", c.GlobalString("log-format"))
}
return nil
}
app.Action = func(c *cli.Context) error {
if cp := c.GlobalString("cpu-profile"); cp != "" {
f, err := os.Create(cp)
if err != nil {
return fmt.Errorf("invalid --cpu-profile value %q", err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
config := c.App.Metadata["config"].(*server.Config)
if !config.SELinux {
selinux.SetDisabled()
}
if _, err := os.Stat(config.Runtime); os.IsNotExist(err) {
// path to runtime does not exist
return fmt.Errorf("invalid --runtime value %q", err)
}
// Remove the socket if it already exists
if _, err := os.Stat(config.Listen); err == nil {
if err := os.Remove(config.Listen); err != nil {
logrus.Fatal(err)
}
}
lis, err := net.Listen("unix", config.Listen)
if err != nil {
logrus.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
service, err := server.New(config)
if err != nil {
logrus.Fatal(err)
}
graceful := false
catchShutdown(s, service, &graceful)
runtime.RegisterRuntimeServiceServer(s, service)
runtime.RegisterImageServiceServer(s, service)
// after the daemon is done setting up we can notify systemd api
notifySystem()
err = s.Serve(lis)
if graceful && strings.Contains(strings.ToLower(err.Error()), "use of closed network connection") {
err = nil
}
if err2 := service.Shutdown(); err2 != nil {
logrus.Infof("error shutting down layer storage: %v", err2)
}
if err != nil {
logrus.Fatal(err)
}
return nil
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
}
}