mirror of https://github.com/containers/podman.git
Merge pull request #12372 from Luap99/syslog-netavark
Make sure netavark output is logged to the syslog
This commit is contained in:
commit
bfc929efc4
|
@ -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
|
||||
|
|
|
@ -89,6 +89,10 @@ var _ = Describe("run netavark", func() {
|
|||
if err != nil {
|
||||
Fail("Failed to create netns")
|
||||
}
|
||||
|
||||
// Force iptables driver, firewalld is broken inside the extra
|
||||
// namespace because it still connects to firewalld on the host.
|
||||
_ = os.Setenv("NETAVARK_FW", "iptables")
|
||||
})
|
||||
|
||||
JustBeforeEach(func() {
|
||||
|
@ -109,6 +113,8 @@ var _ = Describe("run netavark", func() {
|
|||
|
||||
netns.UnmountNS(netNSContainer)
|
||||
netNSContainer.Close()
|
||||
|
||||
_ = os.Unsetenv("NETAVARK_FW")
|
||||
})
|
||||
|
||||
It("test basic setup", func() {
|
||||
|
|
|
@ -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