Files
podman/vendor/github.com/containers/common/libnetwork/netavark/run.go
Urvashi Mohnani 7c8c945496 Vendor in latest c/common
Pull in updates made to the filters code for
images. Filters now perform an AND operation
except for th reference filter which does an
OR operation for positive case but an AND operation
for negative cases.

Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
2024-01-25 11:10:41 -05:00

190 lines
5.3 KiB
Go

//go:build linux || freebsd
package netavark
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"github.com/containers/common/libnetwork/internal/util"
"github.com/containers/common/libnetwork/types"
"github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
)
type netavarkOptions struct {
types.NetworkOptions
Networks map[string]*types.Network `json:"network_info"`
}
func (n *netavarkNetwork) execUpdate(networkName string, networkDNSServers []string) error {
retErr := n.execNetavark([]string{"update", networkName, "--network-dns-servers", strings.Join(networkDNSServers, ",")}, false, nil, nil)
return retErr
}
// Setup will setup the container network namespace. It returns
// a map of StatusBlocks, the key is the network name.
func (n *netavarkNetwork) Setup(namespacePath string, options types.SetupOptions) (map[string]types.StatusBlock, error) {
n.lock.Lock()
defer n.lock.Unlock()
err := n.loadNetworks()
if err != nil {
return nil, err
}
err = util.ValidateSetupOptions(n, namespacePath, options)
if err != nil {
return nil, err
}
// allocate IPs in the IPAM db
err = n.allocIPs(&options.NetworkOptions)
if err != nil {
return nil, err
}
netavarkOpts, needPlugin, err := n.convertNetOpts(options.NetworkOptions)
if err != nil {
return nil, fmt.Errorf("failed to convert net opts: %w", err)
}
// Warn users if one or more networks have dns enabled
// but aardvark-dns binary is not configured
for _, network := range netavarkOpts.Networks {
if network != nil && network.DNSEnabled && n.aardvarkBinary == "" {
// this is not a fatal error we can still use container without dns
logrus.Warnf("aardvark-dns binary not found, container dns will not be enabled")
break
}
}
// trace output to get the json
if logrus.IsLevelEnabled(logrus.TraceLevel) {
b, err := json.Marshal(&netavarkOpts)
if err != nil {
return nil, err
}
// show the full netavark command so we can easily reproduce errors from the cli
logrus.Tracef("netavark command: printf '%s' | %s setup %s", string(b), n.netavarkBinary, namespacePath)
}
result := map[string]types.StatusBlock{}
setup := func() error {
err := n.execNetavark([]string{"setup", namespacePath}, needPlugin, netavarkOpts, &result)
if err != nil {
// lets dealloc ips to prevent leaking
if err := n.deallocIPs(&options.NetworkOptions); err != nil {
logrus.Error(err)
}
return err
}
return nil
}
if n.rootlessNetns != nil {
err = n.rootlessNetns.Setup(len(options.Networks), setup)
} else {
err = setup()
}
if err != nil {
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))
}
return result, err
}
// Teardown will teardown the container network namespace.
func (n *netavarkNetwork) Teardown(namespacePath string, options types.TeardownOptions) error {
n.lock.Lock()
defer n.lock.Unlock()
err := n.loadNetworks()
if err != nil {
return err
}
// get IPs from the IPAM db
err = n.getAssignedIPs(&options.NetworkOptions)
if err != nil {
// when there is an error getting the ips we should still continue
// to call teardown for netavark to prevent leaking network interfaces
logrus.Error(err)
}
netavarkOpts, needPlugin, err := n.convertNetOpts(options.NetworkOptions)
if err != nil {
return fmt.Errorf("failed to convert net opts: %w", err)
}
var retErr error
teardown := func() error {
return n.execNetavark([]string{"teardown", namespacePath}, needPlugin, netavarkOpts, nil)
}
if n.rootlessNetns != nil {
retErr = n.rootlessNetns.Teardown(len(options.Networks), teardown)
} else {
retErr = teardown()
}
// when netavark returned an error we still free the used ips
// otherwise we could end up in a state where block the ips forever
err = n.deallocIPs(&netavarkOpts.NetworkOptions)
if err != nil {
if retErr != nil {
logrus.Error(err)
} else {
retErr = err
}
}
return retErr
}
func (n *netavarkNetwork) getCommonNetavarkOptions(needPlugin bool) []string {
opts := []string{"--config", n.networkRunDir, "--rootless=" + strconv.FormatBool(n.networkRootless), "--aardvark-binary=" + n.aardvarkBinary}
// to allow better backwards compat we only add the new netavark option when really needed
if needPlugin {
// Note this will require a netavark with https://github.com/containers/netavark/pull/509
for _, dir := range n.pluginDirs {
opts = append(opts, "--plugin-directory", dir)
}
}
return opts
}
func (n *netavarkNetwork) convertNetOpts(opts types.NetworkOptions) (*netavarkOptions, bool, error) {
netavarkOptions := netavarkOptions{
NetworkOptions: opts,
Networks: make(map[string]*types.Network, len(opts.Networks)),
}
needsPlugin := false
for network := range opts.Networks {
net, err := n.getNetwork(network)
if err != nil {
return nil, false, err
}
netavarkOptions.Networks[network] = net
if !slices.Contains(builtinDrivers, net.Driver) {
needsPlugin = true
}
}
return &netavarkOptions, needsPlugin, nil
}
func (n *netavarkNetwork) RunInRootlessNetns(toRun func() error) error {
if n.rootlessNetns == nil {
return types.ErrNotRootlessNetns
}
return n.rootlessNetns.Run(n.lock, toRun)
}