diff options
author | Paul Holzinger <pholzing@redhat.com> | 2021-11-19 18:15:53 +0100 |
---|---|---|
committer | Paul Holzinger <pholzing@redhat.com> | 2021-11-19 18:15:53 +0100 |
commit | 501643c8bde591fcb8e4c42564f1b854128ad2f7 (patch) | |
tree | 741fc6b48d1d5fb5e9eeba2d314c06605a324c11 | |
parent | 671e5ee42d4eb71fc0238e8b0b1e4a68b1def156 (diff) | |
download | podman-501643c8bde591fcb8e4c42564f1b854128ad2f7.tar.gz podman-501643c8bde591fcb8e4c42564f1b854128ad2f7.tar.bz2 podman-501643c8bde591fcb8e4c42564f1b854128ad2f7.zip |
Make sure netavark output is logged to the syslog
Create a custom writer which logs the netavark output to logrus. This
will log to the syslog when it is enabled.
Signed-off-by: Paul Holzinger <pholzing@redhat.com>
-rw-r--r-- | libpod/network/netavark/exec.go | 45 | ||||
-rw-r--r-- | libpod/network/netavark/network.go | 9 | ||||
-rw-r--r-- | libpod/network/netavark/run.go | 4 | ||||
-rw-r--r-- | libpod/options.go | 8 | ||||
-rw-r--r-- | libpod/runtime.go | 6 | ||||
-rw-r--r-- | pkg/domain/infra/runtime_libpod.go | 5 |
6 files changed, 68 insertions, 9 deletions
diff --git a/libpod/network/netavark/exec.go b/libpod/network/netavark/exec.go index d6458eeb4..01dea8489 100644 --- a/libpod/network/netavark/exec.go +++ b/libpod/network/netavark/exec.go @@ -3,6 +3,7 @@ package netavark import ( "encoding/json" "errors" + "io" "os" "os/exec" "strconv" @@ -45,6 +46,15 @@ func newNetavarkError(msg string, err error) error { } } +// Type to implement io.Writer interface +// This will write the logrus at info level +type logrusNetavarkWriter struct{} + +func (l *logrusNetavarkWriter) Write(b []byte) (int, error) { + logrus.Info("netavark: ", string(b)) + return len(b), nil +} + // getRustLogEnv returns the RUST_LOG env var based on the current logrus level func getRustLogEnv() string { level := logrus.GetLevel().String() @@ -63,26 +73,43 @@ func getRustLogEnv() string { // used to marshal the netavark output into it. This can be nil. // All errors return by this function should be of the type netavarkError // to provide a helpful error message. -func execNetavark(binary string, args []string, stdin, result interface{}) error { +func (n *netavarkNetwork) execNetavark(args []string, stdin, result interface{}) error { stdinR, stdinW, err := os.Pipe() if err != nil { return newNetavarkError("failed to create stdin pipe", err) } - defer stdinR.Close() + stdinWClosed := false + defer func() { + stdinR.Close() + if !stdinWClosed { + stdinW.Close() + } + }() stdoutR, stdoutW, err := os.Pipe() if err != nil { return newNetavarkError("failed to create stdout pipe", err) } - defer stdoutR.Close() - defer stdoutW.Close() + stdoutWClosed := false + defer func() { + stdoutR.Close() + if !stdoutWClosed { + stdoutW.Close() + } + }() - cmd := exec.Command(binary, args...) + // connect stderr to the podman stderr for logging + var logWriter io.Writer = os.Stderr + if n.syslog { + // connect logrus to stderr as well so that the logs will be written to the syslog as well + logWriter = io.MultiWriter(logWriter, &logrusNetavarkWriter{}) + } + + cmd := exec.Command(n.netavarkBinary, args...) // connect the pipes to stdin and stdout cmd.Stdin = stdinR cmd.Stdout = stdoutW - // connect stderr to the podman stderr for logging - cmd.Stderr = os.Stderr + cmd.Stderr = logWriter // set the netavark log level to the same as the podman cmd.Env = append(os.Environ(), getRustLogEnv()) // if we run with debug log level lets also set RUST_BACKTRACE=1 so we can get the full stack trace in case of panics @@ -95,7 +122,9 @@ func execNetavark(binary string, args []string, stdin, result interface{}) error return newNetavarkError("failed to start process", err) } err = json.NewEncoder(stdinW).Encode(stdin) + // we have to close stdinW so netavark gets the EOF and does not hang forever stdinW.Close() + stdinWClosed = true if err != nil { return newNetavarkError("failed to encode stdin data", err) } @@ -103,7 +132,9 @@ func execNetavark(binary string, args []string, stdin, result interface{}) error dec := json.NewDecoder(stdoutR) err = cmd.Wait() + // we have to close stdoutW so we can decode the json without hanging forever stdoutW.Close() + stdoutWClosed = true if err != nil { exitError := &exec.ExitError{} if errors.As(err, &exitError) { diff --git a/libpod/network/netavark/network.go b/libpod/network/netavark/network.go index cc6fb423c..540d8d6e5 100644 --- a/libpod/network/netavark/network.go +++ b/libpod/network/netavark/network.go @@ -37,6 +37,10 @@ type netavarkNetwork struct { // isMachine describes whenever podman runs in a podman machine environment. isMachine bool + // syslog describes whenever the netavark debbug output should be log to the syslog as well. + // This will use logrus to do so, make sure logrus is set up to log to the syslog. + syslog bool + // lock is a internal lock for critical operations lock lockfile.Locker @@ -68,6 +72,10 @@ type InitConfig struct { // LockFile is the path to lock file. LockFile string + + // Syslog describes whenever the netavark debbug output should be log to the syslog as well. + // This will use logrus to do so, make sure logrus is set up to log to the syslog. + Syslog bool } // NewNetworkInterface creates the ContainerNetwork interface for the netavark backend. @@ -122,6 +130,7 @@ func NewNetworkInterface(conf InitConfig) (types.ContainerNetwork, error) { defaultSubnet: defaultNet, isMachine: conf.IsMachine, lock: lock, + syslog: conf.Syslog, } return n, nil diff --git a/libpod/network/netavark/run.go b/libpod/network/netavark/run.go index 2f839151e..54917a981 100644 --- a/libpod/network/netavark/run.go +++ b/libpod/network/netavark/run.go @@ -54,7 +54,7 @@ func (n *netavarkNetwork) Setup(namespacePath string, options types.SetupOptions } result := map[string]types.StatusBlock{} - err = execNetavark(n.netavarkBinary, []string{"setup", namespacePath}, netavarkOpts, &result) + err = n.execNetavark([]string{"setup", namespacePath}, netavarkOpts, &result) if len(result) != len(options.Networks) { logrus.Errorf("unexpected netavark result: %v", result) @@ -86,7 +86,7 @@ func (n *netavarkNetwork) Teardown(namespacePath string, options types.TeardownO return errors.Wrap(err, "failed to convert net opts") } - retErr := execNetavark(n.netavarkBinary, []string{"teardown", namespacePath}, netavarkOpts, nil) + retErr := n.execNetavark([]string{"teardown", namespacePath}, netavarkOpts, nil) // when netavark returned an error we still free the used ips // otherwise we could end up in a state where block the ips forever diff --git a/libpod/options.go b/libpod/options.go index 3f0f9fbe0..8f2d5cb15 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -578,6 +578,14 @@ func WithEnableSDNotify() RuntimeOption { } } +// WithSyslog sets a runtime option so we know that we have to log to the syslog as well +func WithSyslog() RuntimeOption { + return func(rt *Runtime) error { + rt.syslog = true + return nil + } +} + // WithRuntimeFlags adds the global runtime flags to the container config func WithRuntimeFlags(runtimeFlags []string) RuntimeOption { return func(rt *Runtime) error { diff --git a/libpod/runtime.go b/libpod/runtime.go index c751df79b..1a22cd09a 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -88,6 +88,11 @@ type Runtime struct { libimageEventsShutdown chan bool lockManager lock.Manager + // syslog describes whenever logrus should log to the syslog as well. + // Note that the syslog hook will be enabled early in cmd/podman/syslog_linux.go + // This bool is just needed so that we can set it for netavark interface. + syslog bool + // doRenumber indicates that the runtime should perform a lock renumber // during initialization. // Once the runtime has been initialized and returned, this variable is @@ -517,6 +522,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { DefaultSubnet: runtime.config.Network.DefaultSubnet, IsMachine: runtime.config.Engine.MachineEnabled, LockFile: filepath.Join(runtime.config.Network.NetworkConfigDir, "netavark.lock"), + Syslog: runtime.syslog, }) if err != nil { return errors.Wrapf(err, "could not create network interface") diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go index cfb674b6d..90eb6abeb 100644 --- a/pkg/domain/infra/runtime_libpod.go +++ b/pkg/domain/infra/runtime_libpod.go @@ -236,6 +236,11 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo options = append(options, libpod.WithRegistriesConf(cfg.RegistriesConf)) } + // no need to handle the error, it will return false anyway + if syslog, _ := fs.GetBool("syslog"); syslog { + options = append(options, libpod.WithSyslog()) + } + // TODO flag to set CNI plugins dir? if !opts.withFDS { |