diff options
Diffstat (limited to 'libpod')
-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 | 12 | ||||
-rw-r--r-- | libpod/network/netavark/run_test.go | 6 | ||||
-rw-r--r-- | libpod/options.go | 8 | ||||
-rw-r--r-- | libpod/runtime.go | 6 |
6 files changed, 77 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..0ac20daee 100644 --- a/libpod/network/netavark/run.go +++ b/libpod/network/netavark/run.go @@ -54,8 +54,16 @@ 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 err != nil { + // lets dealloc ips to prevent leaking + if err := n.deallocIPs(&options.NetworkOptions); err != nil { + logrus.Error(err) + } + return nil, err + } + // make sure that the result makes sense if len(result) != len(options.Networks) { logrus.Errorf("unexpected netavark result: %v", result) return nil, fmt.Errorf("unexpected netavark result length, want (%d), got (%d) networks", len(options.Networks), len(result)) @@ -86,7 +94,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/network/netavark/run_test.go b/libpod/network/netavark/run_test.go index 67dc51c10..f79e6d812 100644 --- a/libpod/network/netavark/run_test.go +++ b/libpod/network/netavark/run_test.go @@ -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() { 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") |