summaryrefslogtreecommitdiff
path: root/libpod/network/netavark/exec.go
diff options
context:
space:
mode:
authorPaul Holzinger <pholzing@redhat.com>2021-10-14 10:33:18 +0200
committerPaul Holzinger <pholzing@redhat.com>2021-11-11 15:54:02 +0100
commiteaae29462880aa0fb17e8d448cc79519e070e64f (patch)
tree7da8ee0d642bb34f0f7c97a64e95f93661966050 /libpod/network/netavark/exec.go
parent12c62b92ff2f63cb34dcb9c0555b96983e6aad94 (diff)
downloadpodman-eaae29462880aa0fb17e8d448cc79519e070e64f.tar.gz
podman-eaae29462880aa0fb17e8d448cc79519e070e64f.tar.bz2
podman-eaae29462880aa0fb17e8d448cc79519e070e64f.zip
netavark network interface
Implement a new network interface for netavark. For now only bridge networking is supported. The interface can create/list/inspect/remove networks. For setup and teardown netavark will be invoked. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Diffstat (limited to 'libpod/network/netavark/exec.go')
-rw-r--r--libpod/network/netavark/exec.go116
1 files changed, 116 insertions, 0 deletions
diff --git a/libpod/network/netavark/exec.go b/libpod/network/netavark/exec.go
new file mode 100644
index 000000000..700df9a69
--- /dev/null
+++ b/libpod/network/netavark/exec.go
@@ -0,0 +1,116 @@
+package netavark
+
+import (
+ "encoding/json"
+ "errors"
+ "os"
+ "os/exec"
+ "strconv"
+
+ "github.com/sirupsen/logrus"
+)
+
+type netavarkError struct {
+ exitCode int
+ // Set the json key to "error" so we can directly unmarshal into this struct
+ Msg string `json:"error"`
+ err error
+}
+
+func (e *netavarkError) Error() string {
+ ec := ""
+ // only add the exit code the the error message if we have at least info log level
+ // the normal user does not need to care about the number
+ if e.exitCode > 0 && logrus.IsLevelEnabled(logrus.InfoLevel) {
+ ec = " (exit code " + strconv.Itoa(e.exitCode) + ")"
+ }
+ msg := "netavark" + ec
+ if len(msg) > 0 {
+ msg += ": " + e.Msg
+ }
+ if e.err != nil {
+ msg += ": " + e.err.Error()
+ }
+ return msg
+}
+
+func (e *netavarkError) Unwrap() error {
+ return e.err
+}
+
+func newNetavarkError(msg string, err error) error {
+ return &netavarkError{
+ Msg: msg,
+ err: err,
+ }
+}
+
+// execNetavark will execute netavark with the following arguments
+// It takes the path to the binary, the list of args and an interface which is
+// marshaled to json and send via stdin to netavark. The result interface is
+// 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 {
+ stdinR, stdinW, err := os.Pipe()
+ if err != nil {
+ return newNetavarkError("failed to create stdin pipe", err)
+ }
+ defer stdinR.Close()
+
+ stdoutR, stdoutW, err := os.Pipe()
+ if err != nil {
+ return newNetavarkError("failed to create stdout pipe", err)
+ }
+ defer stdoutR.Close()
+ defer stdoutW.Close()
+
+ cmd := exec.Command(binary, 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
+ // set the netavark log level to the same as the podman
+ cmd.Env = append(os.Environ(), "RUST_LOG="+logrus.GetLevel().String())
+ // 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
+ if logrus.IsLevelEnabled(logrus.DebugLevel) {
+ cmd.Env = append(cmd.Env, "RUST_BACKTRACE=1")
+ }
+
+ err = cmd.Start()
+ if err != nil {
+ return newNetavarkError("failed to start process", err)
+ }
+ err = json.NewEncoder(stdinW).Encode(stdin)
+ stdinW.Close()
+ if err != nil {
+ return newNetavarkError("failed to encode stdin data", err)
+ }
+
+ dec := json.NewDecoder(stdoutR)
+
+ err = cmd.Wait()
+ stdoutW.Close()
+ if err != nil {
+ exitError := &exec.ExitError{}
+ if errors.As(err, &exitError) {
+ ne := &netavarkError{}
+ // lets disallow unknown fields to make sure we do not get some unexpected stuff
+ dec.DisallowUnknownFields()
+ // this will unmarshal the error message into the error struct
+ ne.err = dec.Decode(ne)
+ ne.exitCode = exitError.ExitCode()
+ return ne
+ }
+ return newNetavarkError("unexpected failure during execution", err)
+ }
+
+ if result != nil {
+ err = dec.Decode(result)
+ if err != nil {
+ return newNetavarkError("failed to decode result", err)
+ }
+ }
+ return nil
+}