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>
This commit is contained in:
		
							parent
							
								
									671e5ee42d
								
							
						
					
					
						commit
						501643c8bd
					
				| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue