summaryrefslogtreecommitdiff
path: root/libpod/network
diff options
context:
space:
mode:
authorPaul Holzinger <pholzing@redhat.com>2021-12-17 14:46:15 +0100
committerPaul Holzinger <pholzing@redhat.com>2022-01-12 17:07:30 +0100
commit495884b3195de482dc610a2a002db7e053188a32 (patch)
tree2a6f23db066cd52aa366991b0b34d7b919368ddc /libpod/network
parent2cdab5d53923784e72020d70ee9375518f19f9b6 (diff)
downloadpodman-495884b3195de482dc610a2a002db7e053188a32.tar.gz
podman-495884b3195de482dc610a2a002db7e053188a32.tar.bz2
podman-495884b3195de482dc610a2a002db7e053188a32.zip
use libnetwork from c/common
The libpod/network packages were moved to c/common so that buildah can use it as well. To prevent duplication use it in podman as well and remove it from here. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
Diffstat (limited to 'libpod/network')
-rw-r--r--libpod/network/cni/README.md10
-rw-r--r--libpod/network/cni/cni_conversion.go378
-rw-r--r--libpod/network/cni/cni_exec.go110
-rw-r--r--libpod/network/cni/cni_suite_test.go53
-rw-r--r--libpod/network/cni/cni_types.go281
-rw-r--r--libpod/network/cni/config.go208
-rw-r--r--libpod/network/cni/config_test.go1378
-rw-r--r--libpod/network/cni/network.go273
-rw-r--r--libpod/network/cni/run.go273
-rw-r--r--libpod/network/cni/run_test.go1329
-rw-r--r--libpod/network/cni/testfiles/invalid/broken.conflist25
-rw-r--r--libpod/network/cni/testfiles/invalid/invalid_gateway.conflist51
-rw-r--r--libpod/network/cni/testfiles/invalid/invalidname.conflist49
-rw-r--r--libpod/network/cni/testfiles/invalid/noname.conflist48
-rw-r--r--libpod/network/cni/testfiles/invalid/noplugin.conflist5
-rw-r--r--libpod/network/cni/testfiles/invalid/samename1.conflist49
-rw-r--r--libpod/network/cni/testfiles/invalid/samename2.conflist49
-rw-r--r--libpod/network/cni/testfiles/valid/87-podman.conflist37
-rw-r--r--libpod/network/cni/testfiles/valid/bridge.conflist51
-rw-r--r--libpod/network/cni/testfiles/valid/dualstack.conflist58
-rw-r--r--libpod/network/cni/testfiles/valid/internal.conflist40
-rw-r--r--libpod/network/cni/testfiles/valid/label.conflist54
-rw-r--r--libpod/network/cni/testfiles/valid/macvlan.conflist13
-rw-r--r--libpod/network/cni/testfiles/valid/macvlan_mtu.conflist14
-rw-r--r--libpod/network/cni/testfiles/valid/mtu.conflist49
-rw-r--r--libpod/network/cni/testfiles/valid/vlan.conflist50
-rw-r--r--libpod/network/internal/util/bridge.go69
-rw-r--r--libpod/network/internal/util/create.go42
-rw-r--r--libpod/network/internal/util/interface.go19
-rw-r--r--libpod/network/internal/util/interfaces.go34
-rw-r--r--libpod/network/internal/util/ip.go70
-rw-r--r--libpod/network/internal/util/ip_test.go63
-rw-r--r--libpod/network/internal/util/parse.go37
-rw-r--r--libpod/network/internal/util/util.go123
-rw-r--r--libpod/network/internal/util/validate.go121
-rw-r--r--libpod/network/netavark/config.go210
-rw-r--r--libpod/network/netavark/config_test.go1123
-rw-r--r--libpod/network/netavark/const.go5
-rw-r--r--libpod/network/netavark/exec.go159
-rw-r--r--libpod/network/netavark/ipam.go368
-rw-r--r--libpod/network/netavark/ipam_test.go433
-rw-r--r--libpod/network/netavark/netavark_suite_test.go75
-rw-r--r--libpod/network/netavark/network.go314
-rw-r--r--libpod/network/netavark/run.go127
-rw-r--r--libpod/network/netavark/run_test.go699
-rw-r--r--libpod/network/netavark/testfiles/invalid/broken.json16
-rw-r--r--libpod/network/netavark/testfiles/invalid/invalid name.json19
-rw-r--r--libpod/network/netavark/testfiles/invalid/invalid_gateway.json19
-rw-r--r--libpod/network/netavark/testfiles/invalid/name_missmatch.json19
-rw-r--r--libpod/network/netavark/testfiles/invalid/wrongID.json19
-rw-r--r--libpod/network/netavark/testfiles/valid/bridge.json23
-rw-r--r--libpod/network/netavark/testfiles/valid/dualstack.json23
-rw-r--r--libpod/network/netavark/testfiles/valid/internal.json18
-rw-r--r--libpod/network/netavark/testfiles/valid/label.json22
-rw-r--r--libpod/network/netavark/testfiles/valid/mtu.json22
-rw-r--r--libpod/network/netavark/testfiles/valid/podman.json19
-rw-r--r--libpod/network/netavark/testfiles/valid/vlan.json22
-rw-r--r--libpod/network/types/const.go23
-rw-r--r--libpod/network/types/network.go278
-rw-r--r--libpod/network/types/network_test.go82
-rw-r--r--libpod/network/util/filters.go79
-rw-r--r--libpod/network/util/ip.go56
-rw-r--r--libpod/network/util/ip_calc.go53
-rw-r--r--libpod/network/util/ip_test.go73
64 files changed, 0 insertions, 9911 deletions
diff --git a/libpod/network/cni/README.md b/libpod/network/cni/README.md
deleted file mode 100644
index 6f57feff5..000000000
--- a/libpod/network/cni/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-This package abstracts CNI from libpod.
-It implements the `ContainerNetwork` interface defined in [libpod/network/types/network.go](../types/network.go) for the CNI backend.
-
-
-## Testing
-Run the tests with:
-```
-go test -v -mod=vendor -cover ./libpod/network/cni/
-```
-Run the tests as root to also test setup/teardown. This will execute CNI and therefore the cni plugins have to be installed.
diff --git a/libpod/network/cni/cni_conversion.go b/libpod/network/cni/cni_conversion.go
deleted file mode 100644
index 788165b5e..000000000
--- a/libpod/network/cni/cni_conversion.go
+++ /dev/null
@@ -1,378 +0,0 @@
-// +build linux
-
-package cni
-
-import (
- "encoding/json"
- "io/ioutil"
- "net"
- "os"
- "path/filepath"
- "strconv"
- "strings"
- "syscall"
- "time"
-
- "github.com/containernetworking/cni/libcni"
- internalutil "github.com/containers/podman/v3/libpod/network/internal/util"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
- pkgutil "github.com/containers/podman/v3/pkg/util"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-func createNetworkFromCNIConfigList(conf *libcni.NetworkConfigList, confPath string) (*types.Network, error) {
- network := types.Network{
- Name: conf.Name,
- ID: getNetworkIDFromName(conf.Name),
- Labels: map[string]string{},
- Options: map[string]string{},
- IPAMOptions: map[string]string{},
- }
-
- cniJSON := make(map[string]interface{})
- err := json.Unmarshal(conf.Bytes, &cniJSON)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to unmarshal network config %s", conf.Name)
- }
- if args, ok := cniJSON["args"]; ok {
- if key, ok := args.(map[string]interface{}); ok {
- // read network labels and options from the conf file
- network.Labels = getNetworkArgsFromConfList(key, podmanLabelKey)
- network.Options = getNetworkArgsFromConfList(key, podmanOptionsKey)
- }
- }
-
- f, err := os.Stat(confPath)
- if err != nil {
- return nil, err
- }
- stat := f.Sys().(*syscall.Stat_t)
- network.Created = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec))
-
- firstPlugin := conf.Plugins[0]
- network.Driver = firstPlugin.Network.Type
-
- switch firstPlugin.Network.Type {
- case types.BridgeNetworkDriver:
- var bridge hostLocalBridge
- err := json.Unmarshal(firstPlugin.Bytes, &bridge)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to unmarshal the bridge plugin config in %s", confPath)
- }
- network.NetworkInterface = bridge.BrName
-
- // if isGateway is false we have an internal network
- if !bridge.IsGW {
- network.Internal = true
- }
-
- // set network options
- if bridge.MTU != 0 {
- network.Options["mtu"] = strconv.Itoa(bridge.MTU)
- }
- if bridge.Vlan != 0 {
- network.Options["vlan"] = strconv.Itoa(bridge.Vlan)
- }
-
- err = convertIPAMConfToNetwork(&network, bridge.IPAM, confPath)
- if err != nil {
- return nil, err
- }
-
- case types.MacVLANNetworkDriver, types.IPVLANNetworkDriver:
- var vlan VLANConfig
- err := json.Unmarshal(firstPlugin.Bytes, &vlan)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to unmarshal the macvlan plugin config in %s", confPath)
- }
- network.NetworkInterface = vlan.Master
-
- // set network options
- if vlan.MTU != 0 {
- network.Options["mtu"] = strconv.Itoa(vlan.MTU)
- }
-
- if vlan.Mode != "" {
- network.Options["mode"] = vlan.Mode
- }
-
- err = convertIPAMConfToNetwork(&network, vlan.IPAM, confPath)
- if err != nil {
- return nil, err
- }
-
- default:
- // A warning would be good but users would get this warning every time so keep this at info level.
- logrus.Infof("Unsupported CNI config type %s in %s, this network can still be used but inspect or list cannot show all information",
- firstPlugin.Network.Type, confPath)
- }
-
- // check if the dnsname plugin is configured
- network.DNSEnabled = findPluginByName(conf.Plugins, "dnsname")
-
- return &network, nil
-}
-
-func findPluginByName(plugins []*libcni.NetworkConfig, name string) bool {
- for _, plugin := range plugins {
- if plugin.Network.Type == name {
- return true
- }
- }
- return false
-}
-
-// convertIPAMConfToNetwork converts A cni IPAMConfig to libpod network subnets.
-// It returns an array of subnets and an extra bool if dhcp is configured.
-func convertIPAMConfToNetwork(network *types.Network, ipam ipamConfig, confPath string) error {
- if ipam.PluginType == types.DHCPIPAMDriver {
- network.IPAMOptions["driver"] = types.DHCPIPAMDriver
- return nil
- }
-
- if ipam.PluginType != types.HostLocalIPAMDriver {
- return errors.Errorf("unsupported ipam plugin %s in %s", ipam.PluginType, confPath)
- }
-
- network.IPAMOptions["driver"] = types.HostLocalIPAMDriver
- for _, r := range ipam.Ranges {
- for _, ipam := range r {
- s := types.Subnet{}
-
- // Do not use types.ParseCIDR() because we want the ip to be
- // the network address and not a random ip in the sub.
- _, sub, err := net.ParseCIDR(ipam.Subnet)
- if err != nil {
- return err
- }
- s.Subnet = types.IPNet{IPNet: *sub}
-
- // gateway
- var gateway net.IP
- if ipam.Gateway != "" {
- gateway = net.ParseIP(ipam.Gateway)
- if gateway == nil {
- return errors.Errorf("failed to parse gateway ip %s", ipam.Gateway)
- }
- // convert to 4 byte if ipv4
- util.NormalizeIP(&gateway)
- } else if !network.Internal {
- // only add a gateway address if the network is not internal
- gateway, err = util.FirstIPInSubnet(sub)
- if err != nil {
- return errors.Errorf("failed to get first ip in subnet %s", sub.String())
- }
- }
- s.Gateway = gateway
-
- var rangeStart net.IP
- var rangeEnd net.IP
- if ipam.RangeStart != "" {
- rangeStart = net.ParseIP(ipam.RangeStart)
- if rangeStart == nil {
- return errors.Errorf("failed to parse range start ip %s", ipam.RangeStart)
- }
- }
- if ipam.RangeEnd != "" {
- rangeEnd = net.ParseIP(ipam.RangeEnd)
- if rangeEnd == nil {
- return errors.Errorf("failed to parse range end ip %s", ipam.RangeEnd)
- }
- }
- if rangeStart != nil || rangeEnd != nil {
- s.LeaseRange = &types.LeaseRange{}
- s.LeaseRange.StartIP = rangeStart
- s.LeaseRange.EndIP = rangeEnd
- }
- if util.IsIPv6(s.Subnet.IP) {
- network.IPv6Enabled = true
- }
- network.Subnets = append(network.Subnets, s)
- }
- }
- return nil
-}
-
-// getNetworkArgsFromConfList returns the map of args in a conflist, argType should be labels or options
-func getNetworkArgsFromConfList(args map[string]interface{}, argType string) map[string]string {
- if args, ok := args[argType]; ok {
- if labels, ok := args.(map[string]interface{}); ok {
- result := make(map[string]string, len(labels))
- for k, v := range labels {
- if v, ok := v.(string); ok {
- result[k] = v
- }
- }
- return result
- }
- }
- return map[string]string{}
-}
-
-// createCNIConfigListFromNetwork will create a cni config file from the given network.
-// It returns the cni config and the path to the file where the config was written.
-// Set writeToDisk to false to only add this network into memory.
-func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writeToDisk bool) (*libcni.NetworkConfigList, string, error) {
- var (
- routes []ipamRoute
- ipamRanges [][]ipamLocalHostRangeConf
- ipamConf ipamConfig
- err error
- )
- if len(network.Subnets) > 0 {
- for _, subnet := range network.Subnets {
- route, err := newIPAMDefaultRoute(util.IsIPv6(subnet.Subnet.IP))
- if err != nil {
- return nil, "", err
- }
- routes = append(routes, route)
- ipam := newIPAMLocalHostRange(subnet.Subnet, subnet.LeaseRange, subnet.Gateway)
- ipamRanges = append(ipamRanges, []ipamLocalHostRangeConf{*ipam})
- }
- ipamConf = newIPAMHostLocalConf(routes, ipamRanges)
- } else {
- ipamConf = ipamConfig{PluginType: "dhcp"}
- }
-
- vlan := 0
- mtu := 0
- vlanPluginMode := ""
- for k, v := range network.Options {
- switch k {
- case "mtu":
- mtu, err = internalutil.ParseMTU(v)
- if err != nil {
- return nil, "", err
- }
-
- case "vlan":
- vlan, err = internalutil.ParseVlan(v)
- if err != nil {
- return nil, "", err
- }
-
- case "mode":
- switch network.Driver {
- case types.MacVLANNetworkDriver:
- if !pkgutil.StringInSlice(v, []string{"", "bridge", "private", "vepa", "passthru"}) {
- return nil, "", errors.Errorf("unknown macvlan mode %q", v)
- }
- case types.IPVLANNetworkDriver:
- if !pkgutil.StringInSlice(v, []string{"", "l2", "l3", "l3s"}) {
- return nil, "", errors.Errorf("unknown ipvlan mode %q", v)
- }
- default:
- return nil, "", errors.Errorf("cannot set option \"mode\" with driver %q", network.Driver)
- }
- vlanPluginMode = v
-
- default:
- return nil, "", errors.Errorf("unsupported network option %s", k)
- }
- }
-
- isGateway := true
- ipMasq := true
- if network.Internal {
- isGateway = false
- ipMasq = false
- }
- // create CNI plugin configuration
- // explicitly use CNI version 0.4.0 here, to use v1.0.0 at least containernetwork-plugins-1.0.1 has to be installed
- // the dnsname plugin also needs to be updated for 1.0.0
- // TODO change to 1.0.0 when most distros support it
- ncList := newNcList(network.Name, "0.4.0", network.Labels, network.Options)
- var plugins []interface{}
-
- switch network.Driver {
- case types.BridgeNetworkDriver:
- bridge := newHostLocalBridge(network.NetworkInterface, isGateway, ipMasq, mtu, vlan, ipamConf)
- plugins = append(plugins, bridge, newPortMapPlugin(), newFirewallPlugin(), newTuningPlugin())
- // if we find the dnsname plugin we add configuration for it
- if hasDNSNamePlugin(n.cniPluginDirs) && network.DNSEnabled {
- // Note: in the future we might like to allow for dynamic domain names
- plugins = append(plugins, newDNSNamePlugin(defaultPodmanDomainName))
- }
-
- case types.MacVLANNetworkDriver:
- plugins = append(plugins, newVLANPlugin(types.MacVLANNetworkDriver, network.NetworkInterface, vlanPluginMode, mtu, ipamConf))
-
- case types.IPVLANNetworkDriver:
- plugins = append(plugins, newVLANPlugin(types.IPVLANNetworkDriver, network.NetworkInterface, vlanPluginMode, mtu, ipamConf))
-
- default:
- return nil, "", errors.Errorf("driver %q is not supported by cni", network.Driver)
- }
- ncList["plugins"] = plugins
- b, err := json.MarshalIndent(ncList, "", " ")
- if err != nil {
- return nil, "", err
- }
- cniPathName := ""
- if writeToDisk {
- cniPathName = filepath.Join(n.cniConfigDir, network.Name+".conflist")
- err = ioutil.WriteFile(cniPathName, b, 0644)
- if err != nil {
- return nil, "", err
- }
- f, err := os.Stat(cniPathName)
- if err != nil {
- return nil, "", err
- }
- stat := f.Sys().(*syscall.Stat_t)
- network.Created = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec))
- } else {
- network.Created = time.Now()
- }
- config, err := libcni.ConfListFromBytes(b)
- if err != nil {
- return nil, "", err
- }
- return config, cniPathName, nil
-}
-
-func convertSpecgenPortsToCNIPorts(ports []types.PortMapping) ([]cniPortMapEntry, error) {
- cniPorts := make([]cniPortMapEntry, 0, len(ports))
- for _, port := range ports {
- if port.Protocol == "" {
- return nil, errors.New("port protocol should not be empty")
- }
- protocols := strings.Split(port.Protocol, ",")
-
- for _, protocol := range protocols {
- if !pkgutil.StringInSlice(protocol, []string{"tcp", "udp", "sctp"}) {
- return nil, errors.Errorf("unknown port protocol %s", protocol)
- }
- cniPort := cniPortMapEntry{
- HostPort: int(port.HostPort),
- ContainerPort: int(port.ContainerPort),
- HostIP: port.HostIP,
- Protocol: protocol,
- }
- cniPorts = append(cniPorts, cniPort)
- for i := 1; i < int(port.Range); i++ {
- cniPort := cniPortMapEntry{
- HostPort: int(port.HostPort) + i,
- ContainerPort: int(port.ContainerPort) + i,
- HostIP: port.HostIP,
- Protocol: protocol,
- }
- cniPorts = append(cniPorts, cniPort)
- }
- }
- }
- return cniPorts, nil
-}
-
-func removeMachinePlugin(conf *libcni.NetworkConfigList) *libcni.NetworkConfigList {
- plugins := make([]*libcni.NetworkConfig, 0, len(conf.Plugins))
- for _, net := range conf.Plugins {
- if net.Network.Type != "podman-machine" {
- plugins = append(plugins, net)
- }
- }
- conf.Plugins = plugins
- return conf
-}
diff --git a/libpod/network/cni/cni_exec.go b/libpod/network/cni/cni_exec.go
deleted file mode 100644
index ae857bcfb..000000000
--- a/libpod/network/cni/cni_exec.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2016 CNI authors
-// Copyright 2021 Podman authors
-//
-// This code has been originally copied from github.com/containernetworking/cni
-// but has been changed to better fit the Podman use case.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// +build linux
-
-package cni
-
-import (
- "bytes"
- "context"
- "encoding/json"
- "fmt"
- "os/exec"
- "path/filepath"
-
- "github.com/containernetworking/cni/pkg/invoke"
- "github.com/containernetworking/cni/pkg/version"
- "github.com/containers/podman/v3/pkg/rootless"
-)
-
-type cniExec struct {
- version.PluginDecoder
-}
-
-type cniPluginError struct {
- plugin string
- Code uint `json:"code"`
- Msg string `json:"msg"`
- Details string `json:"details,omitempty"`
-}
-
-// Error returns a nicely formatted error message for the cni plugin errors.
-func (e *cniPluginError) Error() string {
- err := fmt.Sprintf("cni plugin %s failed", e.plugin)
- if e.Msg != "" {
- err = fmt.Sprintf("%s: %s", err, e.Msg)
- } else if e.Code > 0 {
- err = fmt.Sprintf("%s with error code %d", err, e.Code)
- }
- if e.Details != "" {
- err = fmt.Sprintf("%s: %s", err, e.Details)
- }
- return err
-}
-
-// ExecPlugin execute the cni plugin. Returns the stdout of the plugin or an error.
-func (e *cniExec) ExecPlugin(ctx context.Context, pluginPath string, stdinData []byte, environ []string) ([]byte, error) {
- stdout := &bytes.Buffer{}
- stderr := &bytes.Buffer{}
- c := exec.CommandContext(ctx, pluginPath)
- c.Env = environ
- c.Stdin = bytes.NewBuffer(stdinData)
- c.Stdout = stdout
- c.Stderr = stderr
-
- // The dnsname plugin tries to use XDG_RUNTIME_DIR to store files.
- // podman run will have XDG_RUNTIME_DIR set and thus the cni plugin can use
- // it. The problem is that XDG_RUNTIME_DIR is unset for the conmon process
- // for rootful users. This causes issues since the cleanup process is spawned
- // by conmon and thus not have XDG_RUNTIME_DIR set to same value as podman run.
- // Because of it dnsname will not find the config files and cannot correctly cleanup.
- // To fix this we should also unset XDG_RUNTIME_DIR for the cni plugins as rootful.
- if !rootless.IsRootless() {
- c.Env = append(c.Env, "XDG_RUNTIME_DIR=")
- }
-
- err := c.Run()
- if err != nil {
- return nil, annotatePluginError(err, pluginPath, stdout.Bytes(), stderr.Bytes())
- }
- return stdout.Bytes(), nil
-}
-
-// annotatePluginError parses the common cni plugin error json.
-func annotatePluginError(err error, plugin string, stdout []byte, stderr []byte) error {
- pluginName := filepath.Base(plugin)
- emsg := cniPluginError{
- plugin: pluginName,
- }
- if len(stdout) == 0 {
- if len(stderr) == 0 {
- emsg.Msg = err.Error()
- } else {
- emsg.Msg = string(stderr)
- }
- } else if perr := json.Unmarshal(stdout, &emsg); perr != nil {
- emsg.Msg = fmt.Sprintf("failed to unmarshal error message %q: %v", string(stdout), perr)
- }
- return &emsg
-}
-
-// FindInPath finds the plugin in the given paths.
-func (e *cniExec) FindInPath(plugin string, paths []string) (string, error) {
- return invoke.FindInPath(plugin, paths)
-}
diff --git a/libpod/network/cni/cni_suite_test.go b/libpod/network/cni/cni_suite_test.go
deleted file mode 100644
index f98869c96..000000000
--- a/libpod/network/cni/cni_suite_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// +build linux
-
-package cni_test
-
-import (
- "os"
- "path/filepath"
- "testing"
-
- "github.com/containers/podman/v3/libpod/network/cni"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/test/utils"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
-)
-
-var cniPluginDirs = []string{
- "/usr/libexec/cni",
- "/usr/lib/cni",
- "/usr/local/lib/cni",
- "/opt/cni/bin",
-}
-
-func TestCni(t *testing.T) {
- RegisterFailHandler(Fail)
- RunSpecs(t, "CNI Suite")
-}
-
-func getNetworkInterface(cniConfDir string, machine bool) (types.ContainerNetwork, error) {
- return cni.NewCNINetworkInterface(cni.InitConfig{
- CNIConfigDir: cniConfDir,
- CNIPluginDirs: cniPluginDirs,
- IsMachine: machine,
- LockFile: filepath.Join(cniConfDir, "cni.lock"),
- })
-}
-
-func SkipIfNoDnsname() {
- for _, path := range cniPluginDirs {
- f, err := os.Stat(filepath.Join(path, "dnsname"))
- if err == nil && f.Mode().IsRegular() {
- return
- }
- }
- Skip("dnsname cni plugin needs to be installed for this test")
-}
-
-func SkipIfNotFedora(msg string) {
- info := utils.GetHostDistributionInfo()
- if info.Distribution != "fedora" {
- Skip("Test can only run on Fedora: " + msg)
- }
-}
diff --git a/libpod/network/cni/cni_types.go b/libpod/network/cni/cni_types.go
deleted file mode 100644
index e5eb777de..000000000
--- a/libpod/network/cni/cni_types.go
+++ /dev/null
@@ -1,281 +0,0 @@
-// +build linux
-
-package cni
-
-import (
- "net"
- "os"
- "path/filepath"
-
- "github.com/containers/podman/v3/libpod/network/types"
-)
-
-const (
- defaultIPv4Route = "0.0.0.0/0"
- defaultIPv6Route = "::/0"
- // defaultPodmanDomainName is used for the dnsname plugin to define
- // a localized domain name for a created network
- defaultPodmanDomainName = "dns.podman"
-
- // cniDeviceName is the default name for a new bridge, it should be suffixed with an integer
- cniDeviceName = "cni-podman"
-
- // podmanLabelKey key used to store the podman network label in a cni config
- podmanLabelKey = "podman_labels"
-
- // podmanOptionsKey key used to store the podman network options in a cni config
- podmanOptionsKey = "podman_options"
-)
-
-// cniPortMapEntry struct is used by the portmap plugin
-// https://github.com/containernetworking/plugins/blob/649e0181fe7b3a61e708f3e4249a798f57f25cc5/plugins/meta/portmap/main.go#L43-L50
-type cniPortMapEntry struct {
- HostPort int `json:"hostPort"`
- ContainerPort int `json:"containerPort"`
- Protocol string `json:"protocol"`
- HostIP string `json:"hostIP,omitempty"`
-}
-
-// hostLocalBridge describes a configuration for a bridge plugin
-// https://github.com/containernetworking/plugins/tree/master/plugins/main/bridge#network-configuration-reference
-type hostLocalBridge struct {
- PluginType string `json:"type"`
- BrName string `json:"bridge,omitempty"`
- IsGW bool `json:"isGateway"`
- IsDefaultGW bool `json:"isDefaultGateway,omitempty"`
- ForceAddress bool `json:"forceAddress,omitempty"`
- IPMasq bool `json:"ipMasq,omitempty"`
- MTU int `json:"mtu,omitempty"`
- HairpinMode bool `json:"hairpinMode,omitempty"`
- PromiscMode bool `json:"promiscMode,omitempty"`
- Vlan int `json:"vlan,omitempty"`
- IPAM ipamConfig `json:"ipam"`
- Capabilities map[string]bool `json:"capabilities,omitempty"`
-}
-
-// ipamConfig describes an IPAM configuration
-// https://github.com/containernetworking/plugins/tree/master/plugins/ipam/host-local#network-configuration-reference
-type ipamConfig struct {
- PluginType string `json:"type"`
- Routes []ipamRoute `json:"routes,omitempty"`
- ResolveConf string `json:"resolveConf,omitempty"`
- DataDir string `json:"dataDir,omitempty"`
- Ranges [][]ipamLocalHostRangeConf `json:"ranges,omitempty"`
-}
-
-// ipamLocalHostRangeConf describes the new style IPAM ranges
-type ipamLocalHostRangeConf struct {
- Subnet string `json:"subnet"`
- RangeStart string `json:"rangeStart,omitempty"`
- RangeEnd string `json:"rangeEnd,omitempty"`
- Gateway string `json:"gateway,omitempty"`
-}
-
-// ipamRoute describes a route in an ipam config
-type ipamRoute struct {
- Dest string `json:"dst"`
-}
-
-// portMapConfig describes the default portmapping config
-type portMapConfig struct {
- PluginType string `json:"type"`
- Capabilities map[string]bool `json:"capabilities"`
-}
-
-// VLANConfig describes the macvlan config
-type VLANConfig struct {
- PluginType string `json:"type"`
- Master string `json:"master"`
- IPAM ipamConfig `json:"ipam"`
- MTU int `json:"mtu,omitempty"`
- Mode string `json:"mode,omitempty"`
- Capabilities map[string]bool `json:"capabilities,omitempty"`
-}
-
-// firewallConfig describes the firewall plugin
-type firewallConfig struct {
- PluginType string `json:"type"`
- Backend string `json:"backend"`
-}
-
-// tuningConfig describes the tuning plugin
-type tuningConfig struct {
- PluginType string `json:"type"`
-}
-
-// dnsNameConfig describes the dns container name resolution plugin config
-type dnsNameConfig struct {
- PluginType string `json:"type"`
- DomainName string `json:"domainName"`
- Capabilities map[string]bool `json:"capabilities"`
-}
-
-// ncList describes a generic map
-type ncList map[string]interface{}
-
-// newNcList creates a generic map of values with string
-// keys and adds in version and network name
-func newNcList(name, version string, labels, options map[string]string) ncList {
- n := ncList{}
- n["cniVersion"] = version
- n["name"] = name
- args := map[string]map[string]string{}
- if len(labels) > 0 {
- args[podmanLabelKey] = labels
- }
- if len(options) > 0 {
- args[podmanOptionsKey] = options
- }
- if len(args) > 0 {
- n["args"] = args
- }
- return n
-}
-
-// newHostLocalBridge creates a new LocalBridge for host-local
-func newHostLocalBridge(name string, isGateWay, ipMasq bool, mtu int, vlan int, ipamConf ipamConfig) *hostLocalBridge {
- caps := make(map[string]bool)
- caps["ips"] = true
- bridge := hostLocalBridge{
- PluginType: "bridge",
- BrName: name,
- IsGW: isGateWay,
- IPMasq: ipMasq,
- MTU: mtu,
- HairpinMode: true,
- Vlan: vlan,
- IPAM: ipamConf,
- }
- // if we use host-local set the ips cap to ensure we can set static ips via runtime config
- if ipamConf.PluginType == types.HostLocalIPAMDriver {
- bridge.Capabilities = caps
- }
- return &bridge
-}
-
-// newIPAMHostLocalConf creates a new IPAMHostLocal configuration
-func newIPAMHostLocalConf(routes []ipamRoute, ipamRanges [][]ipamLocalHostRangeConf) ipamConfig {
- ipamConf := ipamConfig{
- PluginType: "host-local",
- Routes: routes,
- }
-
- ipamConf.Ranges = ipamRanges
- return ipamConf
-}
-
-// newIPAMLocalHostRange create a new IPAM range
-func newIPAMLocalHostRange(subnet types.IPNet, leaseRange *types.LeaseRange, gw net.IP) *ipamLocalHostRangeConf {
- hostRange := &ipamLocalHostRangeConf{
- Subnet: subnet.String(),
- }
-
- // a user provided a range, we add it here
- if leaseRange != nil {
- if leaseRange.StartIP != nil {
- hostRange.RangeStart = leaseRange.StartIP.String()
- }
- if leaseRange.EndIP != nil {
- hostRange.RangeEnd = leaseRange.EndIP.String()
- }
- }
-
- if gw != nil {
- hostRange.Gateway = gw.String()
- }
- return hostRange
-}
-
-// newIPAMRoute creates a new IPAM route configuration
-// nolint:interfacer
-func newIPAMRoute(r *net.IPNet) ipamRoute {
- return ipamRoute{Dest: r.String()}
-}
-
-// newIPAMDefaultRoute creates a new IPAMDefault route of
-// 0.0.0.0/0 for IPv4 or ::/0 for IPv6
-func newIPAMDefaultRoute(isIPv6 bool) (ipamRoute, error) {
- route := defaultIPv4Route
- if isIPv6 {
- route = defaultIPv6Route
- }
- _, n, err := net.ParseCIDR(route)
- if err != nil {
- return ipamRoute{}, err
- }
- return newIPAMRoute(n), nil
-}
-
-// newPortMapPlugin creates a predefined, default portmapping
-// configuration
-func newPortMapPlugin() portMapConfig {
- caps := make(map[string]bool)
- caps["portMappings"] = true
- p := portMapConfig{
- PluginType: "portmap",
- Capabilities: caps,
- }
- return p
-}
-
-// newFirewallPlugin creates a generic firewall plugin
-func newFirewallPlugin() firewallConfig {
- return firewallConfig{
- PluginType: "firewall",
- }
-}
-
-// newTuningPlugin creates a generic tuning section
-func newTuningPlugin() tuningConfig {
- return tuningConfig{
- PluginType: "tuning",
- }
-}
-
-// newDNSNamePlugin creates the dnsname config with a given
-// domainname
-func newDNSNamePlugin(domainName string) dnsNameConfig {
- caps := make(map[string]bool, 1)
- caps["aliases"] = true
- return dnsNameConfig{
- PluginType: "dnsname",
- DomainName: domainName,
- Capabilities: caps,
- }
-}
-
-// hasDNSNamePlugin looks to see if the dnsname cni plugin is present
-func hasDNSNamePlugin(paths []string) bool {
- for _, p := range paths {
- if _, err := os.Stat(filepath.Join(p, "dnsname")); err == nil {
- return true
- }
- }
- return false
-}
-
-// newVLANPlugin creates a macvlanconfig with a given device name
-func newVLANPlugin(pluginType, device, mode string, mtu int, ipam ipamConfig) VLANConfig {
- m := VLANConfig{
- PluginType: pluginType,
- IPAM: ipam,
- }
- if mtu > 0 {
- m.MTU = mtu
- }
- if len(mode) > 0 {
- m.Mode = mode
- }
- // CNI is supposed to use the default route if a
- // parent device is not provided
- if len(device) > 0 {
- m.Master = device
- }
- caps := make(map[string]bool)
- caps["ips"] = true
- // if we use host-local set the ips cap to ensure we can set static ips via runtime config
- if ipam.PluginType == types.HostLocalIPAMDriver {
- m.Capabilities = caps
- }
- return m
-}
diff --git a/libpod/network/cni/config.go b/libpod/network/cni/config.go
deleted file mode 100644
index 5d587da23..000000000
--- a/libpod/network/cni/config.go
+++ /dev/null
@@ -1,208 +0,0 @@
-// +build linux
-
-package cni
-
-import (
- "net"
- "os"
-
- "github.com/containers/podman/v3/libpod/define"
- internalutil "github.com/containers/podman/v3/libpod/network/internal/util"
- "github.com/containers/podman/v3/libpod/network/types"
- pkgutil "github.com/containers/podman/v3/pkg/util"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- "github.com/vishvananda/netlink"
-)
-
-// NetworkCreate will take a partial filled Network and fill the
-// missing fields. It creates the Network and returns the full Network.
-func (n *cniNetwork) NetworkCreate(net types.Network) (types.Network, error) {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return types.Network{}, err
- }
- network, err := n.networkCreate(net, false)
- if err != nil {
- return types.Network{}, err
- }
- // add the new network to the map
- n.networks[network.libpodNet.Name] = network
- return *network.libpodNet, nil
-}
-
-// networkCreate will fill out the given network struct and return the new network entry.
-// If defaultNet is true it will not validate against used subnets and it will not write the cni config to disk.
-func (n *cniNetwork) networkCreate(newNetwork types.Network, defaultNet bool) (*network, error) {
- // if no driver is set use the default one
- if newNetwork.Driver == "" {
- newNetwork.Driver = types.DefaultNetworkDriver
- }
-
- // FIXME: Should we use a different type for network create without the ID field?
- // the caller is not allowed to set a specific ID
- if newNetwork.ID != "" {
- return nil, errors.Wrap(define.ErrInvalidArg, "ID can not be set for network create")
- }
-
- err := internalutil.CommonNetworkCreate(n, &newNetwork)
- if err != nil {
- return nil, err
- }
-
- // Only get the used networks for validation if we do not create the default network.
- // The default network should not be validated against used subnets, we have to ensure
- // that this network can always be created even when a subnet is already used on the host.
- // This could happen if you run a container on this net, then the cni interface will be
- // created on the host and "block" this subnet from being used again.
- // Therefore the next podman command tries to create the default net again and it would
- // fail because it thinks the network is used on the host.
- var usedNetworks []*net.IPNet
- if !defaultNet {
- usedNetworks, err = internalutil.GetUsedSubnets(n)
- if err != nil {
- return nil, err
- }
- }
-
- switch newNetwork.Driver {
- case types.BridgeNetworkDriver:
- err = internalutil.CreateBridge(n, &newNetwork, usedNetworks)
- if err != nil {
- return nil, err
- }
- case types.MacVLANNetworkDriver, types.IPVLANNetworkDriver:
- err = createIPMACVLAN(&newNetwork)
- if err != nil {
- return nil, err
- }
- default:
- return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported driver %s", newNetwork.Driver)
- }
-
- err = internalutil.ValidateSubnets(&newNetwork, usedNetworks)
- if err != nil {
- return nil, err
- }
-
- // generate the network ID
- newNetwork.ID = getNetworkIDFromName(newNetwork.Name)
-
- // FIXME: Should this be a hard error?
- if newNetwork.DNSEnabled && newNetwork.Internal && hasDNSNamePlugin(n.cniPluginDirs) {
- logrus.Warnf("dnsname and internal networks are incompatible. dnsname plugin not configured for network %s", newNetwork.Name)
- newNetwork.DNSEnabled = false
- }
-
- cniConf, path, err := n.createCNIConfigListFromNetwork(&newNetwork, !defaultNet)
- if err != nil {
- return nil, err
- }
- return &network{cniNet: cniConf, libpodNet: &newNetwork, filename: path}, nil
-}
-
-// NetworkRemove will remove the Network with the given name or ID.
-// It does not ensure that the network is unused.
-func (n *cniNetwork) NetworkRemove(nameOrID string) error {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return err
- }
-
- network, err := n.getNetwork(nameOrID)
- if err != nil {
- return err
- }
-
- // Removing the default network is not allowed.
- if network.libpodNet.Name == n.defaultNetwork {
- return errors.Errorf("default network %s cannot be removed", n.defaultNetwork)
- }
-
- // Remove the bridge network interface on the host.
- if network.libpodNet.Driver == types.BridgeNetworkDriver {
- link, err := netlink.LinkByName(network.libpodNet.NetworkInterface)
- if err == nil {
- err = netlink.LinkDel(link)
- // only log the error, it is not fatal
- if err != nil {
- logrus.Infof("Failed to remove network interface %s: %v", network.libpodNet.NetworkInterface, err)
- }
- }
- }
-
- file := network.filename
- delete(n.networks, network.libpodNet.Name)
-
- // make sure to not error for ErrNotExist
- if err := os.Remove(file); err != nil && !errors.Is(err, os.ErrNotExist) {
- return err
- }
- return nil
-}
-
-// NetworkList will return all known Networks. Optionally you can
-// supply a list of filter functions. Only if a network matches all
-// functions it is returned.
-func (n *cniNetwork) NetworkList(filters ...types.FilterFunc) ([]types.Network, error) {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return nil, err
- }
-
- networks := make([]types.Network, 0, len(n.networks))
-outer:
- for _, net := range n.networks {
- for _, filter := range filters {
- // All filters have to match, if one does not match we can skip to the next network.
- if !filter(*net.libpodNet) {
- continue outer
- }
- }
- networks = append(networks, *net.libpodNet)
- }
- return networks, nil
-}
-
-// NetworkInspect will return the Network with the given name or ID.
-func (n *cniNetwork) NetworkInspect(nameOrID string) (types.Network, error) {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return types.Network{}, err
- }
-
- network, err := n.getNetwork(nameOrID)
- if err != nil {
- return types.Network{}, err
- }
- return *network.libpodNet, nil
-}
-
-func createIPMACVLAN(network *types.Network) error {
- if network.Internal {
- return errors.New("internal is not supported with macvlan")
- }
- if network.NetworkInterface != "" {
- interfaceNames, err := internalutil.GetLiveNetworkNames()
- if err != nil {
- return err
- }
- if !pkgutil.StringInSlice(network.NetworkInterface, interfaceNames) {
- return errors.Errorf("parent interface %s does not exists", network.NetworkInterface)
- }
- }
- if len(network.Subnets) == 0 {
- network.IPAMOptions["driver"] = types.DHCPIPAMDriver
- } else {
- network.IPAMOptions["driver"] = types.HostLocalIPAMDriver
- }
- return nil
-}
diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go
deleted file mode 100644
index c2e5fc985..000000000
--- a/libpod/network/cni/config_test.go
+++ /dev/null
@@ -1,1378 +0,0 @@
-// +build linux
-
-package cni_test
-
-import (
- "bytes"
- "io/ioutil"
- "net"
- "os"
- "path/filepath"
- "time"
-
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- gomegaTypes "github.com/onsi/gomega/types"
- "github.com/sirupsen/logrus"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
-)
-
-var _ = Describe("Config", func() {
- var (
- libpodNet types.ContainerNetwork
- cniConfDir string
- logBuffer bytes.Buffer
- )
-
- BeforeEach(func() {
- var err error
- cniConfDir, err = ioutil.TempDir("", "podman_cni_test")
- if err != nil {
- Fail("Failed to create tmpdir")
-
- }
- logBuffer = bytes.Buffer{}
- logrus.SetOutput(&logBuffer)
- })
-
- JustBeforeEach(func() {
- var err error
- libpodNet, err = getNetworkInterface(cniConfDir, false)
- if err != nil {
- Fail("Failed to create NewCNINetworkInterface")
- }
- })
-
- AfterEach(func() {
- os.RemoveAll(cniConfDir)
- })
-
- Context("basic network config tests", func() {
-
- It("check default network config exists", func() {
- networks, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks[0].Name).To(Equal("podman"))
- Expect(networks[0].Driver).To(Equal("bridge"))
- Expect(networks[0].NetworkInterface).To(Equal("cni-podman0"))
- Expect(networks[0].Created.Before(time.Now())).To(BeTrue())
- Expect(networks[0].Subnets).To(HaveLen(1))
- Expect(networks[0].Subnets[0].Subnet.String()).To(Equal("10.88.0.0/16"))
- Expect(networks[0].Subnets[0].Gateway.String()).To(Equal("10.88.0.1"))
- Expect(networks[0].Subnets[0].LeaseRange).To(BeNil())
- Expect(networks[0].IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- Expect(networks[0].Options).To(BeEmpty())
- Expect(networks[0].Labels).To(BeEmpty())
- Expect(networks[0].DNSEnabled).To(BeFalse())
- Expect(networks[0].Internal).To(BeFalse())
- })
-
- It("basic network create, inspect and remove", func() {
- // Because we get the time from the file create timestamp there is small precision
- // loss so lets remove 500 milliseconds to make sure this test does not flake.
- now := time.Now().Add(-500 * time.Millisecond)
- network := types.Network{}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.IPAMOptions).ToNot(BeEmpty())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- Expect(network1.Created.After(now)).To(BeTrue())
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal("10.89.0.0/24"))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.89.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
-
- // inspect by name
- network2, err := libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- Expect(network2).To(Equal(network1))
-
- // inspect by ID
- network2, err = libpodNet.NetworkInspect(network1.ID)
- Expect(err).To(BeNil())
- Expect(network2).To(Equal(network1))
-
- // inspect by partial ID
- network2, err = libpodNet.NetworkInspect(network1.ID[:10])
- Expect(err).To(BeNil())
- Expect(network2).To(Equal(network1))
-
- // create a new interface to force a config load from disk
- libpodNet, err = getNetworkInterface(cniConfDir, false)
- Expect(err).To(BeNil())
-
- network2, err = libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- Expect(network2).To(Equal(network1))
-
- err = libpodNet.NetworkRemove(network1.Name)
- Expect(err).To(BeNil())
- Expect(path).ToNot(BeARegularFile())
-
- _, err = libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("network not found"))
- })
-
- It("create two networks", func() {
- network := types.Network{}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.Subnets).To(HaveLen(1))
-
- network = types.Network{}
- network2, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network2.Name).ToNot(Equal(network1.Name))
- Expect(network2.ID).ToNot(Equal(network1.ID))
- Expect(network2.NetworkInterface).ToNot(Equal(network1.NetworkInterface))
- Expect(network2.Subnets).To(HaveLen(1))
- Expect(network2.Subnets[0].Subnet.Contains(network1.Subnets[0].Subnet.IP)).To(BeFalse())
- })
-
- It("create bridge config", func() {
- network := types.Network{Driver: "bridge"}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(filepath.Join(cniConfDir, network1.Name+".conflist")).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.IPAMOptions).ToNot(BeEmpty())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal("10.89.0.0/24"))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.89.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
- })
-
- It("create bridge with same name should fail", func() {
- network := types.Network{
- Driver: "bridge",
- NetworkInterface: "cni-podman2",
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).To(Equal("cni-podman2"))
- Expect(network1.Driver).To(Equal("bridge"))
-
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("bridge name cni-podman2 already in use"))
- })
-
- It("create macvlan config", func() {
- network := types.Network{Driver: "macvlan"}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(filepath.Join(cniConfDir, network1.Name+".conflist")).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("macvlan"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.IPAMOptions).ToNot(BeEmpty())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp"))
- Expect(network1.Subnets).To(HaveLen(0))
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
- })
-
- It("create macvlan config with device", func() {
- network := types.Network{
- Driver: "macvlan",
- NetworkInterface: "lo",
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("macvlan"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.Subnets).To(HaveLen(0))
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp"))
- grepInFile(path, `"type": "macvlan"`)
- grepInFile(path, `"master": "lo"`)
- grepInFile(path, `"type": "dhcp"`)
- })
-
- It("create macvlan config with subnet", func() {
- subnet := "10.1.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- network := types.Network{
- Driver: "macvlan",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("macvlan"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.1.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- grepInFile(path, `"type": "host-local"`)
- })
-
- It("create ipvlan config with subnet", func() {
- subnet := "10.1.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- network := types.Network{
- Driver: "ipvlan",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("ipvlan"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.1.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- grepInFile(path, `"type": "host-local"`)
- })
-
- It("create macvlan config with mode", func() {
- for _, mode := range []string{"bridge", "private", "vepa", "passthru"} {
- network := types.Network{
- Driver: "macvlan",
- Options: map[string]string{
- "mode": mode,
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- Expect(network1.Driver).To(Equal("macvlan"))
- Expect(network1.Options).To(HaveKeyWithValue("mode", mode))
- Expect(network1.IPAMOptions).ToNot(BeEmpty())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp"))
- grepInFile(path, `"mode": "`+mode+`"`)
- }
- })
-
- It("create macvlan config with invalid mode", func() {
- network := types.Network{
- Driver: "macvlan",
- Options: map[string]string{
- "mode": "test",
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`unknown macvlan mode "test"`))
- })
-
- It("create macvlan config with invalid device", func() {
- network := types.Network{
- Driver: "macvlan",
- NetworkInterface: "idonotexists",
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("parent interface idonotexists does not exists"))
- })
-
- It("create macvlan config with internal should fail", func() {
- network := types.Network{
- Driver: "macvlan",
- Internal: true,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("internal is not supported with macvlan"))
- })
-
- It("create ipvlan config with mode", func() {
- for _, mode := range []string{"l2", "l3", "l3s"} {
- network := types.Network{
- Driver: "ipvlan",
- Options: map[string]string{
- "mode": mode,
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- Expect(network1.Driver).To(Equal("ipvlan"))
- Expect(network1.Options).To(HaveKeyWithValue("mode", mode))
- Expect(network1.IPAMOptions).ToNot(BeEmpty())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp"))
- grepInFile(path, `"mode": "`+mode+`"`)
-
- // reload configs from disk
- libpodNet, err = getNetworkInterface(cniConfDir, false)
- Expect(err).To(BeNil())
-
- network2, err := libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- Expect(network2).To(Equal(network1))
- }
- })
-
- It("create ipvlan config with invalid mode", func() {
- network := types.Network{
- Driver: "ipvlan",
- Options: map[string]string{
- "mode": "test",
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`unknown ipvlan mode "test"`))
- })
-
- It("create bridge with subnet", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 subnet", func() {
- subnet := "fdcc::/64"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.IPv6Enabled).To(BeTrue())
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("fdcc::1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
-
- // reload configs from disk
- libpodNet, err = getNetworkInterface(cniConfDir, false)
- Expect(err).To(BeNil())
- // check the the networks are identical
- network2, err := libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- Expect(network1).To(Equal(network2))
- })
-
- It("create bridge with ipv6 enabled", func() {
- network := types.Network{
- Driver: "bridge",
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(ContainSubstring(".0/24"))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(ContainSubstring("::/64"))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and ipv4 subnet", func() {
- subnet := "10.100.0.0/24"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(ContainSubstring("::/64"))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and ipv6 subnet", func() {
- subnet := "fd66::/64"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(ContainSubstring(".0/24"))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and ipv4+ipv6 subnet", func() {
- subnet1 := "10.100.0.0/24"
- n1, _ := types.ParseCIDR(subnet1)
- subnet2 := "fd66::/64"
- n2, _ := types.ParseCIDR(subnet2)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n1}, {Subnet: n2},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet1))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(Equal(subnet2))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and two ipv4 subnets", func() {
- subnet1 := "10.100.0.0/24"
- n1, _ := types.ParseCIDR(subnet1)
- subnet2 := "10.200.0.0/24"
- n2, _ := types.ParseCIDR(subnet2)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n1}, {Subnet: n2},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(3))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet1))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(Equal(subnet2))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- Expect(network1.Subnets[2].Subnet.String()).To(ContainSubstring("::/64"))
- Expect(network1.Subnets[2].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[2].LeaseRange).To(BeNil())
- })
-
- It("create bridge with subnet and gateway", func() {
- subnet := "10.0.0.5/24"
- n, _ := types.ParseCIDR(subnet)
- gateway := "10.0.0.50"
- g := net.ParseIP(gateway)
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, Gateway: g},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal("10.0.0.0/24"))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal(gateway))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- })
-
- It("create bridge with subnet and gateway not in the same subnet", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- gateway := "10.10.0.50"
- g := net.ParseIP(gateway)
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, Gateway: g},
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("not in subnet"))
- })
-
- It("create bridge with subnet and lease range", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- startIP := "10.0.0.10"
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- StartIP: net.ParseIP(startIP),
- }},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange.StartIP.String()).To(Equal(startIP))
-
- err = libpodNet.NetworkRemove(network1.Name)
- Expect(err).To(BeNil())
-
- endIP := "10.0.0.30"
- network = types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- EndIP: net.ParseIP(endIP),
- }},
- },
- }
- network1, err = libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(filepath.Join(cniConfDir, network1.Name+".conflist")).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange.EndIP.String()).To(Equal(endIP))
-
- err = libpodNet.NetworkRemove(network1.Name)
- Expect(err).To(BeNil())
-
- network = types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- StartIP: net.ParseIP(startIP),
- EndIP: net.ParseIP(endIP),
- }},
- },
- }
- network1, err = libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange.StartIP.String()).To(Equal(startIP))
- Expect(network1.Subnets[0].LeaseRange.EndIP.String()).To(Equal(endIP))
-
- // create a new interface to force a config load from disk
- libpodNet, err = getNetworkInterface(cniConfDir, false)
- Expect(err).To(BeNil())
-
- network1, err = libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange.StartIP.String()).To(Equal(startIP))
- Expect(network1.Subnets[0].LeaseRange.EndIP.String()).To(Equal(endIP))
- })
-
- It("create bridge with subnet and invalid lease range", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- startIP := "10.0.1.2"
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- StartIP: net.ParseIP(startIP),
- }},
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("not in subnet"))
-
- endIP := "10.1.1.1"
- network = types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- EndIP: net.ParseIP(endIP),
- }},
- },
- }
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("not in subnet"))
- })
-
- It("create bridge with broken subnet", func() {
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: types.IPNet{}},
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("subnet ip is nil"))
- })
-
- It("create network with name", func() {
- name := "myname"
- network := types.Network{
- Name: name,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).To(Equal(name))
- Expect(network1.NetworkInterface).ToNot(Equal(name))
- Expect(network1.Driver).To(Equal("bridge"))
- })
-
- It("create network with invalid name", func() {
- name := "myname@some"
- network := types.Network{
- Name: name,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- })
-
- It("create network with name", func() {
- name := "myname"
- network := types.Network{
- Name: name,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).To(Equal(name))
- Expect(network1.NetworkInterface).ToNot(Equal(name))
- Expect(network1.Driver).To(Equal("bridge"))
- })
-
- It("create network with invalid name", func() {
- name := "myname@some"
- network := types.Network{
- Name: name,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- })
-
- It("create network with interface name", func() {
- name := "myname"
- network := types.Network{
- NetworkInterface: name,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(Equal(name))
- Expect(network1.NetworkInterface).To(Equal(name))
- Expect(network1.Driver).To(Equal("bridge"))
- })
-
- It("create network with invalid interface name", func() {
- name := "myname@some"
- network := types.Network{
- NetworkInterface: name,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- })
-
- It("create network with ID should fail", func() {
- id := "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"
- network := types.Network{
- ID: id,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("ID can not be set for network create"))
- })
-
- It("create bridge with dns", func() {
- network := types.Network{
- Driver: "bridge",
- DNSEnabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.DNSEnabled).To(BeTrue())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- grepInFile(path, `"type": "dnsname"`)
- })
-
- It("create bridge with internal", func() {
- network := types.Network{
- Driver: "bridge",
- Internal: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).ToNot(BeEmpty())
- Expect(network1.Subnets[0].Gateway).To(BeNil())
- Expect(network1.Internal).To(BeTrue())
- })
-
- It("create network with labels", func() {
- network := types.Network{
- Labels: map[string]string{
- "key": "value",
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Labels).ToNot(BeNil())
- Expect(network1.Labels).To(ContainElement("value"))
- })
-
- It("create network with mtu option", func() {
- network := types.Network{
- Options: map[string]string{
- "mtu": "1500",
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Options).ToNot(BeNil())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- grepInFile(path, `"mtu": 1500,`)
- Expect(network1.Options).To(HaveKeyWithValue("mtu", "1500"))
- })
-
- It("create network with invalid mtu option", func() {
- network := types.Network{
- Options: map[string]string{
- "mtu": "abc",
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`parsing "abc": invalid syntax`))
-
- network = types.Network{
- Options: map[string]string{
- "mtu": "-1",
- },
- }
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`mtu -1 is less than zero`))
- })
-
- It("create macvlan network with mtu option", func() {
- network := types.Network{
- Driver: "macvlan",
- Options: map[string]string{
- "mtu": "1500",
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("macvlan"))
- Expect(network1.Options).ToNot(BeNil())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- grepInFile(path, `"mtu": 1500`)
- Expect(network1.Options).To(HaveKeyWithValue("mtu", "1500"))
- })
-
- It("create network with vlan option", func() {
- network := types.Network{
- Options: map[string]string{
- "vlan": "5",
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Options).ToNot(BeNil())
- path := filepath.Join(cniConfDir, network1.Name+".conflist")
- Expect(path).To(BeARegularFile())
- grepInFile(path, `"vlan": 5,`)
- Expect(network1.Options).To(HaveKeyWithValue("vlan", "5"))
- })
-
- It("create network with invalid vlan option", func() {
- network := types.Network{
- Options: map[string]string{
- "vlan": "abc",
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`parsing "abc": invalid syntax`))
-
- network = types.Network{
- Options: map[string]string{
- "vlan": "-1",
- },
- }
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`vlan ID -1 must be between 0 and 4094`))
- })
-
- It("network create unsupported option", func() {
- network := types.Network{Options: map[string]string{
- "someopt": "",
- }}
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("unsupported network option someopt"))
- })
-
- It("network create unsupported driver", func() {
- network := types.Network{
- Driver: "someDriver",
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("unsupported driver someDriver"))
- })
-
- It("network create internal and dns", func() {
- network := types.Network{
- Driver: "bridge",
- Internal: true,
- DNSEnabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).ToNot(BeEmpty())
- Expect(network1.Subnets[0].Gateway).To(BeNil())
- Expect(network1.Internal).To(BeTrue())
- // internal and dns does not work, dns should be disabled
- Expect(network1.DNSEnabled).To(BeFalse())
- logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("dnsname and internal networks are incompatible"))
- })
-
- It("network inspect partial ID", func() {
- network := types.Network{Name: "net4"}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.ID).To(Equal("b44b7426c006839e7fe6f15d1faf64db58079d5233cba09b43be2257c1652cf5"))
- network = types.Network{Name: "net5"}
- network1, err = libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.ID).To(Equal("b67e86fb039828ad686aa13667975b9e51f192eb617044faf06cded9d31602af"))
-
- // Note ID is the sha256 from the name
- // both net4 and net5 have an ID starting with b...
- _, err = libpodNet.NetworkInspect("b")
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("more than one result for network ID"))
- })
-
- It("network create two with same name", func() {
- network := types.Network{Name: "net"}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).To(Equal("net"))
- network = types.Network{Name: "net"}
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("network name net already used"))
- })
-
- It("remove default network config should fail", func() {
- err := libpodNet.NetworkRemove("podman")
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("default network podman cannot be removed"))
-
- network, err := libpodNet.NetworkInspect("podman")
- Expect(err).To(BeNil())
- err = libpodNet.NetworkRemove(network.ID)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("default network podman cannot be removed"))
- })
-
- It("network create with same subnet", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- subnet2 := "10.10.0.0/24"
- n2, _ := types.ParseCIDR(subnet2)
- network := types.Network{Subnets: []types.Subnet{{Subnet: n}, {Subnet: n2}}}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Subnets).To(HaveLen(2))
- network = types.Network{Subnets: []types.Subnet{{Subnet: n}}}
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("subnet 10.0.0.0/24 is already used on the host or by another config"))
- network = types.Network{Subnets: []types.Subnet{{Subnet: n2}}}
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("subnet 10.10.0.0/24 is already used on the host or by another config"))
- })
- })
-
- Context("network load valid existing ones", func() {
-
- BeforeEach(func() {
- dir := "testfiles/valid"
- files, err := ioutil.ReadDir(dir)
- if err != nil {
- Fail("Failed to read test directory")
- }
- for _, file := range files {
- filename := file.Name()
- data, err := ioutil.ReadFile(filepath.Join(dir, filename))
- if err != nil {
- Fail("Failed to copy test files")
- }
- err = ioutil.WriteFile(filepath.Join(cniConfDir, filename), data, 0700)
- if err != nil {
- Fail("Failed to copy test files")
- }
- }
- })
-
- It("load networks from disk", func() {
- nets, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(9))
- // test the we do not show logrus warnings/errors
- logString := logBuffer.String()
- Expect(logString).To(BeEmpty())
- })
-
- It("change network struct fields should not affect network struct in the backend", func() {
- nets, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(9))
-
- nets[0].Name = "myname"
- nets, err = libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(9))
- Expect(nets).ToNot(ContainElement(HaveNetworkName("myname")))
-
- network, err := libpodNet.NetworkInspect("bridge")
- Expect(err).To(BeNil())
- network.NetworkInterface = "abc"
-
- network, err = libpodNet.NetworkInspect("bridge")
- Expect(err).To(BeNil())
- Expect(network.NetworkInterface).ToNot(Equal("abc"))
- })
-
- It("bridge network", func() {
- network, err := libpodNet.NetworkInspect("bridge")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("bridge"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("cni-podman9"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Subnets[0].Subnet.String()).To(Equal("10.89.8.0/24"))
- Expect(network.Subnets[0].Gateway.String()).To(Equal("10.89.8.1"))
- Expect(network.Subnets[0].LeaseRange).ToNot(BeNil())
- Expect(network.Subnets[0].LeaseRange.StartIP.String()).To(Equal("10.89.8.20"))
- Expect(network.Subnets[0].LeaseRange.EndIP.String()).To(Equal("10.89.8.50"))
- Expect(network.Internal).To(BeFalse())
- })
-
- It("macvlan network", func() {
- network, err := libpodNet.NetworkInspect("macvlan")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("macvlan"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("lo"))
- Expect(network.Driver).To(Equal("macvlan"))
- Expect(network.Subnets).To(HaveLen(0))
- // DHCP
- })
-
- It("internal network", func() {
- network, err := libpodNet.NetworkInspect("internal")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("internal"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("cni-podman8"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Subnets[0].Subnet.String()).To(Equal("10.89.7.0/24"))
- Expect(network.Subnets[0].Gateway).To(BeNil())
- Expect(network.Internal).To(BeTrue())
- })
-
- It("bridge network with mtu", func() {
- network, err := libpodNet.NetworkInspect("mtu")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("mtu"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("cni-podman13"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Subnets[0].Subnet.String()).To(Equal("10.89.11.0/24"))
- Expect(network.Subnets[0].Gateway.String()).To(Equal("10.89.11.1"))
- Expect(network.Internal).To(BeFalse())
- Expect(network.Options).To(HaveLen(1))
- Expect(network.Options).To(HaveKeyWithValue("mtu", "1500"))
- })
-
- It("macvlan network with mtu", func() {
- network, err := libpodNet.NetworkInspect("macvlan_mtu")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("macvlan_mtu"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("lo"))
- Expect(network.Driver).To(Equal("macvlan"))
- Expect(network.Subnets).To(HaveLen(0))
- Expect(network.Internal).To(BeFalse())
- Expect(network.Options).To(HaveLen(1))
- Expect(network.Options).To(HaveKeyWithValue("mtu", "1300"))
- Expect(network.IPAMOptions).To(HaveLen(1))
- Expect(network.IPAMOptions).To(HaveKeyWithValue("driver", "dhcp"))
- })
-
- It("bridge network with vlan", func() {
- network, err := libpodNet.NetworkInspect("vlan")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("vlan"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("cni-podman14"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Options).To(HaveLen(1))
- Expect(network.Options).To(HaveKeyWithValue("vlan", "5"))
- })
-
- It("bridge network with labels", func() {
- network, err := libpodNet.NetworkInspect("label")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("label"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("cni-podman15"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Labels).To(HaveLen(1))
- Expect(network.Labels).To(HaveKeyWithValue("mykey", "value"))
- })
-
- It("dual stack network", func() {
- network, err := libpodNet.NetworkInspect("dualstack")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("dualstack"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("cni-podman21"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(2))
-
- sub1, _ := types.ParseCIDR("fd10:88:a::/64")
- sub2, _ := types.ParseCIDR("10.89.19.0/24")
- Expect(network.Subnets).To(ContainElements(
- types.Subnet{Subnet: sub1, Gateway: net.ParseIP("fd10:88:a::1")},
- types.Subnet{Subnet: sub2, Gateway: net.ParseIP("10.89.19.10").To4()},
- ))
- })
-
- It("network list with filters (name)", func() {
- filters := map[string][]string{
- "name": {"internal", "bridge"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (partial name)", func() {
- filters := map[string][]string{
- "name": {"inte", "bri"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (id)", func() {
- filters := map[string][]string{
- "id": {"3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f", "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (id)", func() {
- filters := map[string][]string{
- "id": {"3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f", "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (partial id)", func() {
- filters := map[string][]string{
- "id": {"3bed2cb3a3acf7b6a8ef408420", "17f29b073143d8cd97b5bbe492bde"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (driver)", func() {
- filters := map[string][]string{
- "driver": {"bridge", "macvlan"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(9))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge"),
- HaveNetworkName("mtu"), HaveNetworkName("vlan"), HaveNetworkName("podman"),
- HaveNetworkName("label"), HaveNetworkName("macvlan"), HaveNetworkName("macvlan_mtu"), HaveNetworkName("dualstack")))
- })
-
- It("network list with filters (label)", func() {
- filters := map[string][]string{
- "label": {"mykey"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks).To(ConsistOf(HaveNetworkName("label")))
-
- filters = map[string][]string{
- "label": {"mykey=value"},
- }
- filterFuncs, err = util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err = libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks).To(ConsistOf(HaveNetworkName("label")))
- })
-
- It("network list with filters", func() {
- filters := map[string][]string{
- "driver": {"bridge"},
- "label": {"mykey"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
- Expect(filterFuncs).To(HaveLen(2))
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks).To(ConsistOf(HaveNetworkName("label")))
-
- filters = map[string][]string{
- "driver": {"macvlan"},
- "label": {"mykey"},
- }
- filterFuncs, err = util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err = libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(0))
- })
-
- It("create bridge network with used interface name", func() {
- network := types.Network{
- NetworkInterface: "cni-podman9",
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("bridge name cni-podman9 already in use"))
- })
- })
-
- Context("network load invalid existing ones", func() {
-
- BeforeEach(func() {
- dir := "testfiles/invalid"
- files, err := ioutil.ReadDir(dir)
- if err != nil {
- Fail("Failed to read test directory")
- }
- for _, file := range files {
- filename := file.Name()
- data, err := ioutil.ReadFile(filepath.Join(dir, filename))
- if err != nil {
- Fail("Failed to copy test files")
- }
- err = ioutil.WriteFile(filepath.Join(cniConfDir, filename), data, 0700)
- if err != nil {
- Fail("Failed to copy test files")
- }
- }
- })
-
- It("load invalid networks from disk", func() {
- nets, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(2))
- logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("noname.conflist: error parsing configuration list: no name"))
- Expect(logString).To(ContainSubstring("noplugin.conflist: error parsing configuration list: no plugins in list"))
- Expect(logString).To(ContainSubstring("invalidname.conflist has invalid name, skipping: names must match"))
- Expect(logString).To(ContainSubstring("has the same network name as"))
- Expect(logString).To(ContainSubstring("broken.conflist: error parsing configuration list"))
- Expect(logString).To(ContainSubstring("invalid_gateway.conflist could not be converted to a libpod config, skipping: failed to parse gateway ip 10.89.8"))
- })
-
- })
-
-})
-
-func grepInFile(path string, match string) {
- data, err := ioutil.ReadFile(path)
- ExpectWithOffset(1, err).To(BeNil())
- ExpectWithOffset(1, string(data)).To(ContainSubstring(match))
-}
-
-// HaveNetworkName is a custom GomegaMatcher to match a network name
-func HaveNetworkName(name string) gomegaTypes.GomegaMatcher {
- return WithTransform(func(e types.Network) string {
- return e.Name
- }, Equal(name))
-}
diff --git a/libpod/network/cni/network.go b/libpod/network/cni/network.go
deleted file mode 100644
index 41e3e414e..000000000
--- a/libpod/network/cni/network.go
+++ /dev/null
@@ -1,273 +0,0 @@
-// +build linux
-
-package cni
-
-import (
- "context"
- "crypto/sha256"
- "encoding/hex"
- "os"
- "strings"
- "time"
-
- "github.com/containernetworking/cni/libcni"
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/storage/pkg/lockfile"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-type cniNetwork struct {
- // cniConfigDir is directory where the cni config files are stored.
- cniConfigDir string
- // cniPluginDirs is a list of directories where cni should look for the plugins.
- cniPluginDirs []string
-
- cniConf *libcni.CNIConfig
-
- // defaultNetwork is the name for the default network.
- defaultNetwork string
- // defaultSubnet is the default subnet for the default network.
- defaultSubnet types.IPNet
-
- // isMachine describes whenever podman runs in a podman machine environment.
- isMachine bool
-
- // lock is a internal lock for critical operations
- lock lockfile.Locker
-
- // modTime is the timestamp when the config dir was modified
- modTime time.Time
-
- // networks is a map with loaded networks, the key is the network name
- networks map[string]*network
-}
-
-type network struct {
- // filename is the full path to the cni config file on disk
- filename string
- libpodNet *types.Network
- cniNet *libcni.NetworkConfigList
-}
-
-type InitConfig struct {
- // CNIConfigDir is directory where the cni config files are stored.
- CNIConfigDir string
- // CNIPluginDirs is a list of directories where cni should look for the plugins.
- CNIPluginDirs []string
-
- // DefaultNetwork is the name for the default network.
- DefaultNetwork string
- // DefaultSubnet is the default subnet for the default network.
- DefaultSubnet string
-
- // IsMachine describes whenever podman runs in a podman machine environment.
- IsMachine bool
-
- // LockFile is the path to lock file.
- LockFile string
-}
-
-// NewCNINetworkInterface creates the ContainerNetwork interface for the CNI backend.
-// Note: The networks are not loaded from disk until a method is called.
-func NewCNINetworkInterface(conf InitConfig) (types.ContainerNetwork, error) {
- // TODO: consider using a shared memory lock
- lock, err := lockfile.GetLockfile(conf.LockFile)
- if err != nil {
- return nil, err
- }
-
- defaultNetworkName := conf.DefaultNetwork
- if defaultNetworkName == "" {
- defaultNetworkName = types.DefaultNetworkName
- }
-
- defaultSubnet := conf.DefaultSubnet
- if defaultSubnet == "" {
- defaultSubnet = types.DefaultSubnet
- }
- defaultNet, err := types.ParseCIDR(defaultSubnet)
- if err != nil {
- return nil, errors.Wrap(err, "failed to parse default subnet")
- }
-
- cni := libcni.NewCNIConfig(conf.CNIPluginDirs, &cniExec{})
- n := &cniNetwork{
- cniConfigDir: conf.CNIConfigDir,
- cniPluginDirs: conf.CNIPluginDirs,
- cniConf: cni,
- defaultNetwork: defaultNetworkName,
- defaultSubnet: defaultNet,
- isMachine: conf.IsMachine,
- lock: lock,
- }
-
- return n, nil
-}
-
-// Drivers will return the list of supported network drivers
-// for this interface.
-func (n *cniNetwork) Drivers() []string {
- return []string{types.BridgeNetworkDriver, types.MacVLANNetworkDriver, types.IPVLANNetworkDriver}
-}
-
-func (n *cniNetwork) loadNetworks() error {
- // check the mod time of the config dir
- f, err := os.Stat(n.cniConfigDir)
- if err != nil {
- return err
- }
- modTime := f.ModTime()
-
- // skip loading networks if they are already loaded and
- // if the config dir was not modified since the last call
- if n.networks != nil && modTime.Equal(n.modTime) {
- return nil
- }
- // make sure the remove all networks before we reload them
- n.networks = nil
- n.modTime = modTime
-
- // FIXME: do we have to support other file types as well, e.g. .conf?
- files, err := libcni.ConfFiles(n.cniConfigDir, []string{".conflist"})
- if err != nil {
- return err
- }
- networks := make(map[string]*network, len(files))
- for _, file := range files {
- conf, err := libcni.ConfListFromFile(file)
- if err != nil {
- // do not log ENOENT errors
- if !errors.Is(err, os.ErrNotExist) {
- logrus.Warnf("Error loading CNI config file %s: %v", file, err)
- }
- continue
- }
-
- if !define.NameRegex.MatchString(conf.Name) {
- logrus.Warnf("CNI config list %s has invalid name, skipping: %v", file, define.RegexError)
- continue
- }
-
- // podman < v4.0 used the podman-machine cni plugin for podman machine port forwarding
- // since this is now build into podman we no longer use the plugin
- // old configs may still contain it so we just remove it here
- if n.isMachine {
- conf = removeMachinePlugin(conf)
- }
-
- if _, err := n.cniConf.ValidateNetworkList(context.Background(), conf); err != nil {
- logrus.Warnf("Error validating CNI config file %s: %v", file, err)
- continue
- }
-
- if val, ok := networks[conf.Name]; ok {
- logrus.Warnf("CNI config list %s has the same network name as %s, skipping", file, val.filename)
- continue
- }
-
- net, err := createNetworkFromCNIConfigList(conf, file)
- if err != nil {
- logrus.Errorf("CNI config list %s could not be converted to a libpod config, skipping: %v", file, err)
- continue
- }
- logrus.Debugf("Successfully loaded network %s: %v", net.Name, net)
- networkInfo := network{
- filename: file,
- cniNet: conf,
- libpodNet: net,
- }
- networks[net.Name] = &networkInfo
- }
-
- // create the default network in memory if it did not exists on disk
- if networks[n.defaultNetwork] == nil {
- networkInfo, err := n.createDefaultNetwork()
- if err != nil {
- return errors.Wrapf(err, "failed to create default network %s", n.defaultNetwork)
- }
- networks[n.defaultNetwork] = networkInfo
- }
-
- logrus.Debugf("Successfully loaded %d networks", len(networks))
- n.networks = networks
- return nil
-}
-
-func (n *cniNetwork) createDefaultNetwork() (*network, error) {
- net := types.Network{
- Name: n.defaultNetwork,
- NetworkInterface: "cni-podman0",
- Driver: types.BridgeNetworkDriver,
- Subnets: []types.Subnet{
- {Subnet: n.defaultSubnet},
- },
- }
- return n.networkCreate(net, true)
-}
-
-// getNetwork will lookup a network by name or ID. It returns an
-// error when no network was found or when more than one network
-// with the given (partial) ID exists.
-// getNetwork will read from the networks map, therefore the caller
-// must ensure that n.lock is locked before using it.
-func (n *cniNetwork) getNetwork(nameOrID string) (*network, error) {
- // fast path check the map key, this will only work for names
- if val, ok := n.networks[nameOrID]; ok {
- return val, nil
- }
- // If there was no match we might got a full or partial ID.
- var net *network
- for _, val := range n.networks {
- // This should not happen because we already looked up the map by name but check anyway.
- if val.libpodNet.Name == nameOrID {
- return val, nil
- }
-
- if strings.HasPrefix(val.libpodNet.ID, nameOrID) {
- if net != nil {
- return nil, errors.Errorf("more than one result for network ID %s", nameOrID)
- }
- net = val
- }
- }
- if net != nil {
- return net, nil
- }
- return nil, errors.Wrapf(define.ErrNoSuchNetwork, "unable to find network with name or ID %s", nameOrID)
-}
-
-// getNetworkIDFromName creates a network ID from the name. It is just the
-// sha256 hash so it is not safe but it should be safe enough for our use case.
-func getNetworkIDFromName(name string) string {
- hash := sha256.Sum256([]byte(name))
- return hex.EncodeToString(hash[:])
-}
-
-// Implement the NetUtil interface for easy code sharing with other network interfaces.
-
-// ForEach call the given function for each network
-func (n *cniNetwork) ForEach(run func(types.Network)) {
- for _, val := range n.networks {
- run(*val.libpodNet)
- }
-}
-
-// Len return the number of networks
-func (n *cniNetwork) Len() int {
- return len(n.networks)
-}
-
-// DefaultInterfaceName return the default cni bridge name, must be suffixed with a number.
-func (n *cniNetwork) DefaultInterfaceName() string {
- return cniDeviceName
-}
-
-func (n *cniNetwork) Network(nameOrID string) (*types.Network, error) {
- network, err := n.getNetwork(nameOrID)
- if err != nil {
- return nil, err
- }
- return network.libpodNet, err
-}
diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go
deleted file mode 100644
index d0ff49b73..000000000
--- a/libpod/network/cni/run.go
+++ /dev/null
@@ -1,273 +0,0 @@
-// +build linux
-
-package cni
-
-import (
- "context"
- "net"
- "os"
- "strings"
-
- "github.com/containernetworking/cni/libcni"
- cnitypes "github.com/containernetworking/cni/pkg/types"
- types040 "github.com/containernetworking/cni/pkg/types/040"
- "github.com/containernetworking/plugins/pkg/ns"
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/libpod/network/internal/util"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/hashicorp/go-multierror"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- "github.com/vishvananda/netlink"
-)
-
-// Setup will setup the container network namespace. It returns
-// a map of StatusBlocks, the key is the network name.
-func (n *cniNetwork) 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
- }
-
- // set the loopback adapter up in the container netns
- err = ns.WithNetNSPath(namespacePath, func(_ ns.NetNS) error {
- link, err := netlink.LinkByName("lo")
- if err == nil {
- err = netlink.LinkSetUp(link)
- }
- return err
- })
- if err != nil {
- return nil, errors.Wrapf(err, "failed to set the loopback adapter up")
- }
-
- var retErr error
- teardownOpts := options
- teardownOpts.Networks = map[string]types.PerNetworkOptions{}
- // make sure to teardown the already connected networks on error
- defer func() {
- if retErr != nil {
- if len(teardownOpts.Networks) > 0 {
- err := n.teardown(namespacePath, types.TeardownOptions(teardownOpts))
- if err != nil {
- logrus.Warn(err)
- }
- }
- }
- }()
-
- ports, err := convertSpecgenPortsToCNIPorts(options.PortMappings)
- if err != nil {
- return nil, err
- }
-
- results := make(map[string]types.StatusBlock, len(options.Networks))
- for name, netOpts := range options.Networks {
- network := n.networks[name]
- rt := getRuntimeConfig(namespacePath, options.ContainerName, options.ContainerID, name, ports, netOpts)
-
- // If we have more than one static ip we need parse the ips via runtime config,
- // make sure to add the ips capability to the first plugin otherwise it doesn't get the ips
- if len(netOpts.StaticIPs) > 0 && !network.cniNet.Plugins[0].Network.Capabilities["ips"] {
- caps := make(map[string]interface{})
- caps["capabilities"] = map[string]bool{"ips": true}
- network.cniNet.Plugins[0], retErr = libcni.InjectConf(network.cniNet.Plugins[0], caps)
- if retErr != nil {
- return nil, retErr
- }
- }
-
- var res cnitypes.Result
- res, retErr = n.cniConf.AddNetworkList(context.Background(), network.cniNet, rt)
- // Add this network to teardown opts since it is now connected.
- // Also add this if an errors was returned since we want to call teardown on this regardless.
- teardownOpts.Networks[name] = netOpts
- if retErr != nil {
- return nil, retErr
- }
-
- logrus.Debugf("cni result for container %s network %s: %v", options.ContainerID, name, res)
- var status types.StatusBlock
- status, retErr = CNIResultToStatus(res)
- if retErr != nil {
- return nil, retErr
- }
- results[name] = status
- }
- return results, nil
-}
-
-// CNIResultToStatus convert the cni result to status block
-// nolint:golint
-func CNIResultToStatus(res cnitypes.Result) (types.StatusBlock, error) {
- result := types.StatusBlock{}
- cniResult, err := types040.GetResult(res)
- if err != nil {
- return result, err
- }
- nameservers := make([]net.IP, 0, len(cniResult.DNS.Nameservers))
- for _, nameserver := range cniResult.DNS.Nameservers {
- ip := net.ParseIP(nameserver)
- if ip == nil {
- return result, errors.Errorf("failed to parse cni nameserver ip %s", nameserver)
- }
- nameservers = append(nameservers, ip)
- }
- result.DNSServerIPs = nameservers
- result.DNSSearchDomains = cniResult.DNS.Search
-
- interfaces := make(map[string]types.NetInterface)
- for _, ip := range cniResult.IPs {
- if ip.Interface == nil {
- // we do no expect ips without an interface
- continue
- }
- if len(cniResult.Interfaces) <= *ip.Interface {
- return result, errors.Errorf("invalid cni result, interface index %d out of range", *ip.Interface)
- }
- cniInt := cniResult.Interfaces[*ip.Interface]
- netInt, ok := interfaces[cniInt.Name]
- if ok {
- netInt.Subnets = append(netInt.Subnets, types.NetAddress{
- IPNet: types.IPNet{IPNet: ip.Address},
- Gateway: ip.Gateway,
- })
- interfaces[cniInt.Name] = netInt
- } else {
- mac, err := net.ParseMAC(cniInt.Mac)
- if err != nil {
- return result, err
- }
- interfaces[cniInt.Name] = types.NetInterface{
- MacAddress: types.HardwareAddr(mac),
- Subnets: []types.NetAddress{{
- IPNet: types.IPNet{IPNet: ip.Address},
- Gateway: ip.Gateway,
- }},
- }
- }
- }
- result.Interfaces = interfaces
- return result, nil
-}
-
-func getRuntimeConfig(netns, conName, conID, networkName string, ports []cniPortMapEntry, opts types.PerNetworkOptions) *libcni.RuntimeConf {
- rt := &libcni.RuntimeConf{
- ContainerID: conID,
- NetNS: netns,
- IfName: opts.InterfaceName,
- Args: [][2]string{
- {"IgnoreUnknown", "1"},
- // Do not set the K8S env vars, see https://github.com/containers/podman/issues/12083.
- // Only K8S_POD_NAME is used by dnsname to get the container name.
- {"K8S_POD_NAME", conName},
- },
- CapabilityArgs: map[string]interface{}{},
- }
-
- // Propagate environment CNI_ARGS
- for _, kvpairs := range strings.Split(os.Getenv("CNI_ARGS"), ";") {
- if keyval := strings.SplitN(kvpairs, "=", 2); len(keyval) == 2 {
- rt.Args = append(rt.Args, [2]string{keyval[0], keyval[1]})
- }
- }
-
- // Add mac address to cni args
- if len(opts.StaticMAC) > 0 {
- rt.Args = append(rt.Args, [2]string{"MAC", opts.StaticMAC.String()})
- }
-
- if len(opts.StaticIPs) == 1 {
- // Add a single IP to the args field. CNI plugins < 1.0.0
- // do not support multiple ips via capability args.
- rt.Args = append(rt.Args, [2]string{"IP", opts.StaticIPs[0].String()})
- } else if len(opts.StaticIPs) > 1 {
- // Set the static ips in the capability args
- // to support more than one static ip per network.
- rt.CapabilityArgs["ips"] = opts.StaticIPs
- }
-
- // Set network aliases for the dnsname plugin.
- if len(opts.Aliases) > 0 {
- rt.CapabilityArgs["aliases"] = map[string][]string{
- networkName: opts.Aliases,
- }
- }
-
- // Set PortMappings in Capabilities
- if len(ports) > 0 {
- rt.CapabilityArgs["portMappings"] = ports
- }
-
- return rt
-}
-
-// Teardown will teardown the container network namespace.
-func (n *cniNetwork) Teardown(namespacePath string, options types.TeardownOptions) error {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return err
- }
- return n.teardown(namespacePath, options)
-}
-
-func (n *cniNetwork) teardown(namespacePath string, options types.TeardownOptions) error {
- // Note: An empty namespacePath is allowed because some plugins
- // still need teardown, for example ipam should remove used ip allocations.
-
- ports, err := convertSpecgenPortsToCNIPorts(options.PortMappings)
- if err != nil {
- return err
- }
-
- var multiErr *multierror.Error
- for name, netOpts := range options.Networks {
- rt := getRuntimeConfig(namespacePath, options.ContainerName, options.ContainerID, name, ports, netOpts)
-
- cniConfList, newRt, err := getCachedNetworkConfig(n.cniConf, name, rt)
- if err == nil {
- rt = newRt
- } else {
- logrus.Warnf("Failed to load cached network config: %v, falling back to loading network %s from disk", err, name)
- network := n.networks[name]
- if network == nil {
- multiErr = multierror.Append(multiErr, errors.Wrapf(define.ErrNoSuchNetwork, "network %s", name))
- continue
- }
- cniConfList = network.cniNet
- }
-
- err = n.cniConf.DelNetworkList(context.Background(), cniConfList, rt)
- if err != nil {
- multiErr = multierror.Append(multiErr, err)
- }
- }
- return multiErr.ErrorOrNil()
-}
-
-func getCachedNetworkConfig(cniConf *libcni.CNIConfig, name string, rt *libcni.RuntimeConf) (*libcni.NetworkConfigList, *libcni.RuntimeConf, error) {
- cniConfList := &libcni.NetworkConfigList{
- Name: name,
- }
- confBytes, rt, err := cniConf.GetNetworkListCachedConfig(cniConfList, rt)
- if err != nil {
- return nil, nil, err
- } else if confBytes == nil {
- return nil, nil, errors.Errorf("network %s not found in CNI cache", name)
- }
-
- cniConfList, err = libcni.ConfListFromBytes(confBytes)
- if err != nil {
- return nil, nil, err
- }
- return cniConfList, rt, nil
-}
diff --git a/libpod/network/cni/run_test.go b/libpod/network/cni/run_test.go
deleted file mode 100644
index f6cc2d412..000000000
--- a/libpod/network/cni/run_test.go
+++ /dev/null
@@ -1,1329 +0,0 @@
-// +build linux
-
-package cni_test
-
-// The tests have to be run as root.
-// For each test there will be two network namespaces created,
-// netNSTest and netNSContainer. Each test must be run inside
-// netNSTest to prevent leakage in the host netns, therefore
-// it should use the following structure:
-// It("test name", func() {
-// runTest(func() {
-// // add test logic here
-// })
-// })
-
-import (
- "bytes"
- "io/ioutil"
- "net"
- "os"
- "path/filepath"
- "strconv"
- "sync"
- "time"
-
- "github.com/containernetworking/plugins/pkg/ns"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- "github.com/sirupsen/logrus"
- "github.com/vishvananda/netlink"
- "golang.org/x/sys/unix"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/pkg/netns"
- "github.com/containers/podman/v3/pkg/rootless"
- "github.com/containers/storage/pkg/stringid"
-)
-
-var _ = Describe("run CNI", func() {
- var (
- libpodNet types.ContainerNetwork
- cniConfDir string
- logBuffer bytes.Buffer
- netNSTest ns.NetNS
- netNSContainer ns.NetNS
- )
- const cniVarDir = "/var/lib/cni"
-
- // runTest is a helper function to run a test. It ensures that each test
- // is run in its own netns. It also creates a mountns to mount a tmpfs to /var/lib/cni.
- runTest := func(run func()) {
- netNSTest.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- err := os.MkdirAll(cniVarDir, 0755)
- Expect(err).To(BeNil(), "Failed to create cniVarDir")
- err = unix.Unshare(unix.CLONE_NEWNS)
- Expect(err).To(BeNil(), "Failed to create new mountns")
- err = unix.Mount("tmpfs", cniVarDir, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV, "")
- Expect(err).To(BeNil(), "Failed to mount tmpfs for cniVarDir")
- defer unix.Unmount(cniVarDir, 0)
-
- // we have to setup the loopback adapter in this netns to use port forwarding
- link, err := netlink.LinkByName("lo")
- Expect(err).To(BeNil(), "Failed to get loopback adapter")
- err = netlink.LinkSetUp(link)
- Expect(err).To(BeNil(), "Failed to set loopback adapter up")
- run()
- return nil
- })
- }
-
- BeforeEach(func() {
- // The tests need root privileges.
- // Technically we could work around that by using user namespaces and
- // the rootless cni code but this is to much work to get it right for a unit test.
- if rootless.IsRootless() {
- Skip("this test needs to be run as root")
- }
-
- var err error
- cniConfDir, err = ioutil.TempDir("", "podman_cni_test")
- if err != nil {
- Fail("Failed to create tmpdir")
- }
- logBuffer = bytes.Buffer{}
- logrus.SetOutput(&logBuffer)
-
- netNSTest, err = netns.NewNS()
- if err != nil {
- Fail("Failed to create netns")
- }
-
- netNSContainer, err = netns.NewNS()
- if err != nil {
- Fail("Failed to create netns")
- }
- })
-
- JustBeforeEach(func() {
- var err error
- libpodNet, err = getNetworkInterface(cniConfDir, false)
- if err != nil {
- Fail("Failed to create NewCNINetworkInterface")
- }
- })
-
- AfterEach(func() {
- os.RemoveAll(cniConfDir)
-
- netns.UnmountNS(netNSTest)
- netNSTest.Close()
-
- netns.UnmountNS(netNSContainer)
- netNSContainer.Close()
- })
-
- Context("network setup test", func() {
-
- It("run with default config", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- Expect(res[defNet].Interfaces[intName].Subnets[0].IPNet.IP.String()).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
- // default network has no dns
- Expect(res[defNet].DNSServerIPs).To(BeEmpty())
- Expect(res[defNet].DNSSearchDomains).To(BeEmpty())
-
- // reload the interface so the networks are reload from disk
- libpodNet, err := getNetworkInterface(cniConfDir, false)
- Expect(err).To(BeNil())
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- })
- })
-
- It("run with default config and static ip", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- ip := net.ParseIP("10.88.5.5")
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- StaticIPs: []net.IP{ip},
- },
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- Expect(res[defNet].Interfaces[intName].Subnets[0].IPNet.IP).To(Equal(ip))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
- // default network has no dns
- Expect(res[defNet].DNSServerIPs).To(BeEmpty())
- Expect(res[defNet].DNSSearchDomains).To(BeEmpty())
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- })
- })
-
- for _, proto := range []string{"tcp", "udp"} {
- // copy proto to extra var to keep correct references in the goroutines
- protocol := proto
- It("run with exposed ports protocol "+protocol, func() {
- runTest(func() {
- testdata := stringid.GenerateNonCryptoID()
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- PortMappings: []types.PortMapping{{
- Protocol: protocol,
- HostIP: "127.0.0.1",
- HostPort: 5000,
- ContainerPort: 5000,
- }},
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- Expect(res[defNet].Interfaces[intName].Subnets[0].IPNet.IP.String()).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
- // default network has no dns
- Expect(res[defNet].DNSServerIPs).To(BeEmpty())
- Expect(res[defNet].DNSSearchDomains).To(BeEmpty())
- var wg sync.WaitGroup
- wg.Add(1)
- // start a listener in the container ns
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- runNetListener(&wg, protocol, "0.0.0.0", 5000, testdata)
- return nil
- })
- Expect(err).To(BeNil())
-
- conn, err := net.Dial(protocol, "127.0.0.1:5000")
- Expect(err).To(BeNil())
- _, err = conn.Write([]byte(testdata))
- Expect(err).To(BeNil())
- conn.Close()
-
- // wait for the listener to finish
- wg.Wait()
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- })
- })
-
- It("run with range ports protocol "+protocol, func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- PortMappings: []types.PortMapping{{
- Protocol: protocol,
- HostIP: "127.0.0.1",
- HostPort: 5001,
- ContainerPort: 5000,
- Range: 3,
- }},
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- containerIP := res[defNet].Interfaces[intName].Subnets[0].IPNet.IP.String()
- Expect(containerIP).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
- // default network has no dns
- Expect(res[defNet].DNSServerIPs).To(BeEmpty())
- Expect(res[defNet].DNSSearchDomains).To(BeEmpty())
-
- // loop over all ports
- for p := 5001; p < 5004; p++ {
- port := p
- var wg sync.WaitGroup
- wg.Add(1)
- testdata := stringid.GenerateNonCryptoID()
- // start a listener in the container ns
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- runNetListener(&wg, protocol, containerIP, port-1, testdata)
- return nil
- })
- Expect(err).To(BeNil())
-
- conn, err := net.Dial(protocol, net.JoinHostPort("127.0.0.1", strconv.Itoa(port)))
- Expect(err).To(BeNil())
- _, err = conn.Write([]byte(testdata))
- Expect(err).To(BeNil())
- conn.Close()
-
- // wait for the listener to finish
- wg.Wait()
- }
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- })
- })
- }
-
- It("run with comma separated port protocol", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- PortMappings: []types.PortMapping{{
- Protocol: "tcp,udp",
- HostIP: "127.0.0.1",
- HostPort: 5000,
- ContainerPort: 5000,
- }},
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- Expect(res[defNet].Interfaces[intName].Subnets[0].IPNet.IP.String()).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
-
- for _, proto := range []string{"tcp", "udp"} {
- // copy proto to extra var to keep correct references in the goroutines
- protocol := proto
-
- testdata := stringid.GenerateNonCryptoID()
- var wg sync.WaitGroup
- wg.Add(1)
- // start tcp listener in the container ns
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- runNetListener(&wg, protocol, "0.0.0.0", 5000, testdata)
- return nil
- })
- Expect(err).To(BeNil())
-
- conn, err := net.Dial(protocol, "127.0.0.1:5000")
- Expect(err).To(BeNil())
- _, err = conn.Write([]byte(testdata))
- Expect(err).To(BeNil())
- conn.Close()
-
- // wait for the listener to finish
- wg.Wait()
- }
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- })
- })
-
- It("call setup twice", func() {
- runTest(func() {
- network := types.Network{}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- intName1 := "eth0"
- netName1 := network1.Name
-
- containerID := stringid.GenerateNonCryptoID()
-
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: containerID,
- Networks: map[string]types.PerNetworkOptions{
- netName1: {
- InterfaceName: intName1,
- },
- },
- },
- }
-
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
-
- Expect(res).To(HaveKey(netName1))
- Expect(res[netName1].Interfaces).To(HaveKey(intName1))
- Expect(res[netName1].Interfaces[intName1].Subnets).To(HaveLen(1))
- ipInt1 := res[netName1].Interfaces[intName1].Subnets[0].IPNet.IP
- Expect(ipInt1).ToNot(BeEmpty())
- macInt1 := res[netName1].Interfaces[intName1].MacAddress
- Expect(macInt1).To(HaveLen(6))
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(intName1)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(intName1))
- Expect(i.HardwareAddr).To(Equal((net.HardwareAddr)(macInt1)))
- addrs, err := i.Addrs()
- Expect(err).To(BeNil())
- subnet := &net.IPNet{
- IP: ipInt1,
- Mask: net.CIDRMask(24, 32),
- }
- Expect(addrs).To(ContainElements(subnet))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).To(BeNil())
-
- network = types.Network{}
- network2, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- intName2 := "eth1"
- netName2 := network2.Name
-
- setupOpts.Networks = map[string]types.PerNetworkOptions{
- netName2: {
- InterfaceName: intName2,
- },
- }
-
- res, err = libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
-
- Expect(res).To(HaveKey(netName2))
- Expect(res[netName2].Interfaces).To(HaveKey(intName2))
- Expect(res[netName2].Interfaces[intName2].Subnets).To(HaveLen(1))
- ipInt2 := res[netName2].Interfaces[intName2].Subnets[0].IPNet.IP
- Expect(ipInt2).ToNot(BeEmpty())
- macInt2 := res[netName2].Interfaces[intName2].MacAddress
- Expect(macInt2).To(HaveLen(6))
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(intName1)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(intName1))
- Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt1)))
- addrs, err := i.Addrs()
- Expect(err).To(BeNil())
- subnet := &net.IPNet{
- IP: ipInt1,
- Mask: net.CIDRMask(24, 32),
- }
- Expect(addrs).To(ContainElements(subnet))
-
- i, err = net.InterfaceByName(intName2)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(intName2))
- Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt2)))
- addrs, err = i.Addrs()
- Expect(err).To(BeNil())
- subnet = &net.IPNet{
- IP: ipInt2,
- Mask: net.CIDRMask(24, 32),
- }
- Expect(addrs).To(ContainElements(subnet))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).To(BeNil())
-
- teatdownOpts := types.TeardownOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: containerID,
- Networks: map[string]types.PerNetworkOptions{
- netName1: {
- InterfaceName: intName1,
- },
- netName2: {
- InterfaceName: intName2,
- },
- },
- },
- }
-
- err = libpodNet.Teardown(netNSContainer.Path(), teatdownOpts)
- Expect(err).To(BeNil())
- logString := logBuffer.String()
- Expect(logString).To(BeEmpty())
-
- // check in the container namespace that the interface is removed
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- _, err := net.InterfaceByName(intName1)
- Expect(err).To(HaveOccurred())
- _, err = net.InterfaceByName(intName2)
- Expect(err).To(HaveOccurred())
-
- // check that only the loopback adapter is left
- ints, err := net.Interfaces()
- Expect(err).To(BeNil())
- Expect(ints).To(HaveLen(1))
- Expect(ints[0].Name).To(Equal("lo"))
- Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
-
- return nil
- })
- Expect(err).To(BeNil())
-
- err = libpodNet.NetworkRemove(netName1)
- Expect(err).To(BeNil())
- err = libpodNet.NetworkRemove(netName2)
- Expect(err).To(BeNil())
-
- // check that the interfaces are removed in the host ns
- _, err = net.InterfaceByName(network1.NetworkInterface)
- Expect(err).To(HaveOccurred())
- _, err = net.InterfaceByName(network2.NetworkInterface)
- Expect(err).To(HaveOccurred())
- })
- })
-
- It("setup two networks with one setup call", func() {
- runTest(func() {
- subnet1, _ := types.ParseCIDR("192.168.0.0/24")
- subnet2, _ := types.ParseCIDR("192.168.1.0/24")
- network := types.Network{
- Subnets: []types.Subnet{
- {Subnet: subnet1},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- network = types.Network{
- Subnets: []types.Subnet{
- {Subnet: subnet2},
- },
- }
- network2, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- intName1 := "eth0"
- intName2 := "eth1"
- netName1 := network1.Name
- netName2 := network2.Name
-
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName1: {
- InterfaceName: intName1,
- },
- netName2: {
- InterfaceName: intName2,
- },
- },
- },
- }
-
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(2))
-
- Expect(res).To(HaveKey(netName1))
- Expect(res[netName1].Interfaces).To(HaveKey(intName1))
- Expect(res[netName1].Interfaces[intName1].Subnets).To(HaveLen(1))
- ipInt1 := res[netName1].Interfaces[intName1].Subnets[0].IPNet.IP
- Expect(ipInt1.String()).To(ContainSubstring("192.168.0."))
- macInt1 := res[netName1].Interfaces[intName1].MacAddress
- Expect(macInt1).To(HaveLen(6))
-
- Expect(res).To(HaveKey(netName2))
- Expect(res[netName2].Interfaces).To(HaveKey(intName2))
- Expect(res[netName2].Interfaces[intName2].Subnets).To(HaveLen(1))
- ipInt2 := res[netName2].Interfaces[intName2].Subnets[0].IPNet.IP
- Expect(ipInt2.String()).To(ContainSubstring("192.168.1."))
- macInt2 := res[netName2].Interfaces[intName2].MacAddress
- Expect(macInt2).To(HaveLen(6))
-
- // default network has no dns
- Expect(res[netName1].DNSServerIPs).To(BeEmpty())
- Expect(res[netName1].DNSSearchDomains).To(BeEmpty())
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(intName1)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(intName1))
- Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt1)))
- addrs, err := i.Addrs()
- Expect(err).To(BeNil())
- subnet := &net.IPNet{
- IP: ipInt1,
- Mask: net.CIDRMask(24, 32),
- }
- Expect(addrs).To(ContainElements(subnet))
-
- i, err = net.InterfaceByName(intName2)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(intName2))
- Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macInt2)))
- addrs, err = i.Addrs()
- Expect(err).To(BeNil())
- subnet = &net.IPNet{
- IP: ipInt2,
- Mask: net.CIDRMask(24, 32),
- }
- Expect(addrs).To(ContainElements(subnet))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).To(BeNil())
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- logString := logBuffer.String()
- Expect(logString).To(BeEmpty())
-
- // check in the container namespace that the interface is removed
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- _, err := net.InterfaceByName(intName1)
- Expect(err).To(HaveOccurred())
- _, err = net.InterfaceByName(intName2)
- Expect(err).To(HaveOccurred())
-
- // check that only the loopback adapter is left
- ints, err := net.Interfaces()
- Expect(err).To(BeNil())
- Expect(ints).To(HaveLen(1))
- Expect(ints[0].Name).To(Equal("lo"))
- Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
-
- return nil
- })
- Expect(err).To(BeNil())
- })
-
- })
-
- It("dual stack network with static ips", func() {
- // Version checks for cni plugins are not possible, the plugins do not output
- // version information and using the package manager does not work across distros.
- // Fedora has the right version so we use this for now.
- SkipIfNotFedora("requires cni plugins 1.0.0 or newer for multiple static ips")
- runTest(func() {
- subnet1, _ := types.ParseCIDR("192.168.0.0/24")
- subnet2, _ := types.ParseCIDR("fd41:0a75:2ca0:48a9::/64")
- network := types.Network{
- Subnets: []types.Subnet{
- {Subnet: subnet1}, {Subnet: subnet2},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- mac, _ := net.ParseMAC("40:15:2f:d8:42:36")
- interfaceName := "eth0"
-
- ip1 := net.ParseIP("192.168.0.5")
- ip2 := net.ParseIP("fd41:0a75:2ca0:48a9::5")
-
- netName := network1.Name
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerName: "mycon",
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName: {
- InterfaceName: interfaceName,
- StaticIPs: []net.IP{ip1, ip2},
- StaticMAC: types.HardwareAddr(mac),
- },
- },
- },
- }
-
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(netName))
- Expect(res[netName].Interfaces).To(HaveKey(interfaceName))
- Expect(res[netName].Interfaces[interfaceName].Subnets).To(HaveLen(2))
- Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.IP.String()).To(Equal(ip1.String()))
- Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.Mask).To(Equal(subnet1.Mask))
- Expect(res[netName].Interfaces[interfaceName].Subnets[0].Gateway).To(Equal(net.ParseIP("192.168.0.1")))
- Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.IP.String()).To(Equal(ip2.String()))
- Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.Mask).To(Equal(subnet2.Mask))
- Expect(res[netName].Interfaces[interfaceName].Subnets[1].Gateway).To(Equal(net.ParseIP("fd41:0a75:2ca0:48a9::1")))
- Expect(res[netName].Interfaces[interfaceName].MacAddress).To(Equal(types.HardwareAddr(mac)))
- // default network has no dns
- Expect(res[netName].DNSServerIPs).To(BeEmpty())
- Expect(res[netName].DNSSearchDomains).To(BeEmpty())
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(interfaceName)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(interfaceName))
- Expect(i.HardwareAddr).To(Equal(mac))
- addrs, err := i.Addrs()
- Expect(err).To(BeNil())
- subnet1 := &net.IPNet{
- IP: ip1,
- Mask: net.CIDRMask(24, 32),
- }
- subnet2 := &net.IPNet{
- IP: ip2,
- Mask: net.CIDRMask(64, 128),
- }
- Expect(addrs).To(ContainElements(subnet1, subnet2))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).To(BeNil())
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- logString := logBuffer.String()
- Expect(logString).To(BeEmpty())
-
- // check in the container namespace that the interface is removed
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- _, err := net.InterfaceByName(interfaceName)
- Expect(err).To(HaveOccurred())
-
- // check that only the loopback adapter is left
- ints, err := net.Interfaces()
- Expect(err).To(BeNil())
- Expect(ints).To(HaveLen(1))
- Expect(ints[0].Name).To(Equal("lo"))
- Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
-
- return nil
- })
- Expect(err).To(BeNil())
- })
- })
-
- It("CNI_ARGS from environment variable", func() {
- runTest(func() {
- subnet1, _ := types.ParseCIDR("172.16.1.0/24")
- ip := "172.16.1.5"
- network := types.Network{
- Subnets: []types.Subnet{
- {Subnet: subnet1},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- netName := network1.Name
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName: {
- InterfaceName: intName,
- },
- },
- },
- }
-
- os.Setenv("CNI_ARGS", "IP="+ip)
- defer os.Unsetenv("CNI_ARGS")
-
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(netName))
- Expect(res[netName].Interfaces).To(HaveKey(intName))
- Expect(res[netName].Interfaces[intName].Subnets).To(HaveLen(1))
- Expect(res[netName].Interfaces[intName].Subnets[0].IPNet.IP.String()).To(Equal(ip))
- Expect(res[netName].Interfaces[intName].Subnets[0].IPNet.Mask).To(Equal(net.CIDRMask(24, 32)))
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(intName)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(intName))
- addrs, err := i.Addrs()
- Expect(err).To(BeNil())
- subnet := &net.IPNet{
- IP: net.ParseIP(ip),
- Mask: net.CIDRMask(24, 32),
- }
- Expect(addrs).To(ContainElements(subnet))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).To(BeNil())
- })
- })
- })
-
- Context("network setup test with networks from disk", func() {
-
- BeforeEach(func() {
- dir := "testfiles/valid"
- files, err := ioutil.ReadDir(dir)
- if err != nil {
- Fail("Failed to read test directory")
- }
- for _, file := range files {
- filename := file.Name()
- data, err := ioutil.ReadFile(filepath.Join(dir, filename))
- if err != nil {
- Fail("Failed to copy test files")
- }
- err = ioutil.WriteFile(filepath.Join(cniConfDir, filename), data, 0700)
- if err != nil {
- Fail("Failed to copy test files")
- }
- }
- })
-
- It("dualstack setup with static ip and dns", func() {
- SkipIfNoDnsname()
- // Version checks for cni plugins are not possible, the plugins do not output
- // version information and using the package manager does not work across distros.
- // Fedora has the right version so we use this for now.
- SkipIfNotFedora("requires cni plugins 1.0.0 or newer for multiple static ips")
- runTest(func() {
- interfaceName := "eth0"
-
- ip1 := net.ParseIP("fd10:88:a::11")
- ip2 := net.ParseIP("10.89.19.15")
-
- containerName := "myname"
- aliases := []string{"aliasname"}
-
- netName := "dualstack"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- ContainerName: containerName,
- Networks: map[string]types.PerNetworkOptions{
- netName: {
- InterfaceName: interfaceName,
- StaticIPs: []net.IP{ip1, ip2},
- Aliases: aliases,
- },
- },
- },
- }
-
- network, err := libpodNet.NetworkInspect(netName)
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal(netName))
- Expect(network.DNSEnabled).To(BeTrue())
- Expect(network.Subnets).To(HaveLen(2))
- gw1 := network.Subnets[0].Gateway
- Expect(gw1).To(HaveLen(16))
- mask1 := network.Subnets[0].Subnet.Mask
- Expect(mask1).To(HaveLen(16))
- gw2 := network.Subnets[1].Gateway
- Expect(gw2).To(HaveLen(4))
- mask2 := network.Subnets[1].Subnet.Mask
- Expect(mask2).To(HaveLen(4))
-
- // because this net has dns we should always teardown otherwise we leak a dnsmasq process
- defer libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(netName))
- Expect(res[netName].Interfaces).To(HaveKey(interfaceName))
- Expect(res[netName].Interfaces[interfaceName].Subnets).To(HaveLen(2))
- Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.IP.String()).To(Equal(ip1.String()))
- Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.Mask).To(Equal(mask1))
- Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.IP.String()).To(Equal(ip2.String()))
- Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.Mask).To(Equal(mask2))
- // dualstack network dns
- Expect(res[netName].DNSServerIPs).To(HaveLen(2))
- Expect(res[netName].DNSSearchDomains).To(HaveLen(1))
- Expect(res[netName].DNSSearchDomains).To(ConsistOf("dns.podman"))
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(interfaceName)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(interfaceName))
- addrs, err := i.Addrs()
- Expect(err).To(BeNil())
- subnet1 := &net.IPNet{
- IP: ip1,
- Mask: net.CIDRMask(64, 128),
- }
- subnet2 := &net.IPNet{
- IP: ip2,
- Mask: net.CIDRMask(24, 32),
- }
- Expect(addrs).To(ContainElements(subnet1, subnet2))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
-
- return nil
- })
- Expect(err).To(BeNil())
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- logString := logBuffer.String()
- Expect(logString).To(BeEmpty())
-
- // check in the container namespace that the interface is removed
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- _, err := net.InterfaceByName(interfaceName)
- Expect(err).To(HaveOccurred())
-
- // check that only the loopback adapter is left
- ints, err := net.Interfaces()
- Expect(err).To(BeNil())
- Expect(ints).To(HaveLen(1))
- Expect(ints[0].Name).To(Equal("lo"))
- Expect(ints[0].Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(ints[0].Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
-
- return nil
- })
- Expect(err).To(BeNil())
- })
- })
-
- It("setup with aliases but dns disabled should work", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- Aliases: []string{"somealias"},
- },
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).ToNot(HaveOccurred())
- })
- })
-
- })
-
- Context("invalid network setup test", func() {
-
- It("static ip not in subnet", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- ip := "1.1.1.1"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- StaticIPs: []net.IP{net.ParseIP(ip)},
- },
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("requested static ip %s not in any subnet on network %s", ip, defNet))
- })
- })
-
- It("setup without namespace path", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- },
- },
- },
- }
- _, err := libpodNet.Setup("", setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("namespacePath is empty"))
- })
- })
-
- It("setup with invalid namespace path", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- },
- },
- },
- }
- _, err := libpodNet.Setup("some path", setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`"some path": no such file or directory`))
- })
- })
-
- It("setup without container ID", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: "",
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- },
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("ContainerID is empty"))
- })
- })
-
- It("setup without networks", func() {
- runTest(func() {
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("must specify at least one network"))
- })
- })
-
- It("setup without interface name", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: "",
- },
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("interface name on network %s is empty", defNet))
- })
- })
-
- It("setup does teardown on failure", func() {
- runTest(func() {
- subnet1, _ := types.ParseCIDR("192.168.0.0/24")
- network := types.Network{
- Subnets: []types.Subnet{
- {Subnet: subnet1},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- subnet2, _ := types.ParseCIDR("192.168.1.0/31")
- network = types.Network{
- Subnets: []types.Subnet{
- {Subnet: subnet2},
- },
- }
- network2, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- intName1 := "eth0"
- intName2 := "eth1"
- netName1 := network1.Name
- netName2 := network2.Name
-
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName1: {
- InterfaceName: intName1,
- },
- netName2: {
- InterfaceName: intName2,
- },
- },
- },
- }
- _, err = libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("Network 192.168.1.0/31 too small to allocate from"))
- // Note: we call teardown on the failing net and log the error, it should be the same.
- logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("Network 192.168.1.0/31 too small to allocate from"))
-
- // check in the container namespace that no interface is there
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- _, err := net.InterfaceByName(intName1)
- Expect(err).To(HaveOccurred())
-
- // Note: We can check if intName2 is removed because
- // the cni plugin fails before it removes the interface
-
- // check loopback adapter
- i, err := net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).To(BeNil())
- })
- })
-
- It("setup with exposed invalid port protocol", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- PortMappings: []types.PortMapping{{
- Protocol: "someproto",
- HostIP: "127.0.0.1",
- HostPort: 5000,
- ContainerPort: 5000,
- }},
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("unknown port protocol someproto"))
- })
- })
-
- It("setup with exposed empty port protocol", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- PortMappings: []types.PortMapping{{
- Protocol: "",
- HostIP: "127.0.0.1",
- HostPort: 5000,
- ContainerPort: 5000,
- }},
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("port protocol should not be empty"))
- })
- })
-
- It("setup with unknown network", func() {
- runTest(func() {
- defNet := "somenet"
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- _, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("unable to find network with name or ID somenet: network not found"))
- })
- })
-
- It("teardown with unknown network", func() {
- runTest(func() {
- interfaceName := "eth0"
- netName := "somenet"
- teardownOpts := types.TeardownOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName: {
- InterfaceName: interfaceName,
- },
- },
- },
- }
-
- err := libpodNet.Teardown(netNSContainer.Path(), teardownOpts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("network somenet: network not found"))
- logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("Failed to load cached network config"))
- })
- })
-
- It("teardown on not connected network", func() {
- runTest(func() {
- network := types.Network{}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
-
- interfaceName := "eth0"
- netName := network1.Name
- teardownOpts := types.TeardownOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName: {
- InterfaceName: interfaceName,
- },
- },
- },
- }
-
- // Most CNI plugins do not error on teardown when there is nothing to do.
- err = libpodNet.Teardown(netNSContainer.Path(), teardownOpts)
- Expect(err).To(BeNil())
- logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("Failed to load cached network config"))
- })
- })
- })
-})
-
-func runNetListener(wg *sync.WaitGroup, protocol, ip string, port int, expectedData string) {
- switch protocol {
- case "tcp":
- ln, err := net.Listen(protocol, net.JoinHostPort(ip, strconv.Itoa(port)))
- Expect(err).To(BeNil())
- // make sure to read in a separate goroutine to not block
- go func() {
- defer GinkgoRecover()
- defer wg.Done()
- conn, err := ln.Accept()
- Expect(err).To(BeNil())
- conn.SetDeadline(time.Now().Add(1 * time.Second))
- data, err := ioutil.ReadAll(conn)
- Expect(err).To(BeNil())
- Expect(string(data)).To(Equal(expectedData))
- conn.Close()
- ln.Close()
- }()
- case "udp":
- conn, err := net.ListenUDP("udp", &net.UDPAddr{
- IP: net.ParseIP(ip),
- Port: port,
- })
- Expect(err).To(BeNil())
- conn.SetDeadline(time.Now().Add(1 * time.Second))
- go func() {
- defer GinkgoRecover()
- defer wg.Done()
- data := make([]byte, len(expectedData))
- i, err := conn.Read(data)
- Expect(err).To(BeNil())
- Expect(i).To(Equal(len(expectedData)))
- Expect(string(data)).To(Equal(expectedData))
- conn.Close()
- }()
- default:
- Fail("unsupported protocol")
- }
-}
diff --git a/libpod/network/cni/testfiles/invalid/broken.conflist b/libpod/network/cni/testfiles/invalid/broken.conflist
deleted file mode 100644
index e5bf48b39..000000000
--- a/libpod/network/cni/testfiles/invalid/broken.conflist
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "bridge",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman9",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1"
- }
- ]
- ]
diff --git a/libpod/network/cni/testfiles/invalid/invalid_gateway.conflist b/libpod/network/cni/testfiles/invalid/invalid_gateway.conflist
deleted file mode 100644
index f03c1fde4..000000000
--- a/libpod/network/cni/testfiles/invalid/invalid_gateway.conflist
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "invalidgw",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman8",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8",
- "rangeStart": "10.89.8.20",
- "rangeEnd": "10.89.8.50"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/invalid/invalidname.conflist b/libpod/network/cni/testfiles/invalid/invalidname.conflist
deleted file mode 100644
index e35be69db..000000000
--- a/libpod/network/cni/testfiles/invalid/invalidname.conflist
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "bridge@123",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman9",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/invalid/noname.conflist b/libpod/network/cni/testfiles/invalid/noname.conflist
deleted file mode 100644
index 865abadf8..000000000
--- a/libpod/network/cni/testfiles/invalid/noname.conflist
+++ /dev/null
@@ -1,48 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman9",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/invalid/noplugin.conflist b/libpod/network/cni/testfiles/invalid/noplugin.conflist
deleted file mode 100644
index af192adca..000000000
--- a/libpod/network/cni/testfiles/invalid/noplugin.conflist
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "bridge",
- "plugins": []
-}
diff --git a/libpod/network/cni/testfiles/invalid/samename1.conflist b/libpod/network/cni/testfiles/invalid/samename1.conflist
deleted file mode 100644
index 57b325264..000000000
--- a/libpod/network/cni/testfiles/invalid/samename1.conflist
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "bridge",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman9",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/invalid/samename2.conflist b/libpod/network/cni/testfiles/invalid/samename2.conflist
deleted file mode 100644
index 57b325264..000000000
--- a/libpod/network/cni/testfiles/invalid/samename2.conflist
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "bridge",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman9",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/87-podman.conflist b/libpod/network/cni/testfiles/valid/87-podman.conflist
deleted file mode 100644
index ef760a61b..000000000
--- a/libpod/network/cni/testfiles/valid/87-podman.conflist
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "podman",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman0",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [{ "dst": "0.0.0.0/0" }],
- "ranges": [
- [
- {
- "subnet": "10.88.0.0/16",
- "gateway": "10.88.0.1"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall"
- },
- {
- "type": "tuning"
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/bridge.conflist b/libpod/network/cni/testfiles/valid/bridge.conflist
deleted file mode 100644
index 8952b50b7..000000000
--- a/libpod/network/cni/testfiles/valid/bridge.conflist
+++ /dev/null
@@ -1,51 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "bridge",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman9",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1",
- "rangeStart": "10.89.8.20",
- "rangeEnd": "10.89.8.50"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/dualstack.conflist b/libpod/network/cni/testfiles/valid/dualstack.conflist
deleted file mode 100644
index dd08382f0..000000000
--- a/libpod/network/cni/testfiles/valid/dualstack.conflist
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "dualstack",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman21",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "::/0"
- },
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "fd10:88:a::/64",
- "gateway": "fd10:88:a::1"
- }
- ],
- [
- {
- "subnet": "10.89.19.0/24",
- "gateway": "10.89.19.10"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/internal.conflist b/libpod/network/cni/testfiles/valid/internal.conflist
deleted file mode 100644
index 1b6f15a96..000000000
--- a/libpod/network/cni/testfiles/valid/internal.conflist
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "internal",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman8",
- "isGateway": false,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.7.0/24"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/label.conflist b/libpod/network/cni/testfiles/valid/label.conflist
deleted file mode 100644
index 1501f9bd7..000000000
--- a/libpod/network/cni/testfiles/valid/label.conflist
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "args": {
- "podman_labels": {
- "mykey": "value"
- }
- },
- "cniVersion": "0.4.0",
- "name": "label",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman15",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.13.0/24",
- "gateway": "10.89.13.1"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/macvlan.conflist b/libpod/network/cni/testfiles/valid/macvlan.conflist
deleted file mode 100644
index 8f3692334..000000000
--- a/libpod/network/cni/testfiles/valid/macvlan.conflist
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "macvlan",
- "plugins": [
- {
- "type": "macvlan",
- "master": "lo",
- "ipam": {
- "type": "dhcp"
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/macvlan_mtu.conflist b/libpod/network/cni/testfiles/valid/macvlan_mtu.conflist
deleted file mode 100644
index 2fd259117..000000000
--- a/libpod/network/cni/testfiles/valid/macvlan_mtu.conflist
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "macvlan_mtu",
- "plugins": [
- {
- "type": "macvlan",
- "master": "lo",
- "ipam": {
- "type": "dhcp"
- },
- "mtu": 1300
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/mtu.conflist b/libpod/network/cni/testfiles/valid/mtu.conflist
deleted file mode 100644
index db5f7e194..000000000
--- a/libpod/network/cni/testfiles/valid/mtu.conflist
+++ /dev/null
@@ -1,49 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "mtu",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman13",
- "isGateway": true,
- "ipMasq": true,
- "mtu": 1500,
- "hairpinMode": true,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.11.0/24"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/cni/testfiles/valid/vlan.conflist b/libpod/network/cni/testfiles/valid/vlan.conflist
deleted file mode 100644
index 75e8967f1..000000000
--- a/libpod/network/cni/testfiles/valid/vlan.conflist
+++ /dev/null
@@ -1,50 +0,0 @@
-{
- "cniVersion": "0.4.0",
- "name": "vlan",
- "plugins": [
- {
- "type": "bridge",
- "bridge": "cni-podman14",
- "isGateway": true,
- "ipMasq": true,
- "hairpinMode": true,
- "vlan": 5,
- "ipam": {
- "type": "host-local",
- "routes": [
- {
- "dst": "0.0.0.0/0"
- }
- ],
- "ranges": [
- [
- {
- "subnet": "10.89.12.0/24",
- "gateway": "10.89.12.1"
- }
- ]
- ]
- }
- },
- {
- "type": "portmap",
- "capabilities": {
- "portMappings": true
- }
- },
- {
- "type": "firewall",
- "backend": ""
- },
- {
- "type": "tuning"
- },
- {
- "type": "dnsname",
- "domainName": "dns.podman",
- "capabilities": {
- "aliases": true
- }
- }
- ]
-}
diff --git a/libpod/network/internal/util/bridge.go b/libpod/network/internal/util/bridge.go
deleted file mode 100644
index 476557050..000000000
--- a/libpod/network/internal/util/bridge.go
+++ /dev/null
@@ -1,69 +0,0 @@
-package util
-
-import (
- "net"
-
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
- pkgutil "github.com/containers/podman/v3/pkg/util"
- "github.com/pkg/errors"
-)
-
-func CreateBridge(n NetUtil, network *types.Network, usedNetworks []*net.IPNet) error {
- if network.NetworkInterface != "" {
- bridges := GetBridgeInterfaceNames(n)
- if pkgutil.StringInSlice(network.NetworkInterface, bridges) {
- return errors.Errorf("bridge name %s already in use", network.NetworkInterface)
- }
- if !define.NameRegex.MatchString(network.NetworkInterface) {
- return errors.Wrapf(define.RegexError, "bridge name %s invalid", network.NetworkInterface)
- }
- } else {
- var err error
- network.NetworkInterface, err = GetFreeDeviceName(n)
- if err != nil {
- return err
- }
- }
-
- if network.IPAMOptions["driver"] != types.DHCPIPAMDriver {
- if len(network.Subnets) == 0 {
- freeSubnet, err := GetFreeIPv4NetworkSubnet(usedNetworks)
- if err != nil {
- return err
- }
- network.Subnets = append(network.Subnets, *freeSubnet)
- }
- // ipv6 enabled means dual stack, check if we already have
- // a ipv4 or ipv6 subnet and add one if not.
- if network.IPv6Enabled {
- ipv4 := false
- ipv6 := false
- for _, subnet := range network.Subnets {
- if util.IsIPv6(subnet.Subnet.IP) {
- ipv6 = true
- }
- if util.IsIPv4(subnet.Subnet.IP) {
- ipv4 = true
- }
- }
- if !ipv4 {
- freeSubnet, err := GetFreeIPv4NetworkSubnet(usedNetworks)
- if err != nil {
- return err
- }
- network.Subnets = append(network.Subnets, *freeSubnet)
- }
- if !ipv6 {
- freeSubnet, err := GetFreeIPv6NetworkSubnet(usedNetworks)
- if err != nil {
- return err
- }
- network.Subnets = append(network.Subnets, *freeSubnet)
- }
- }
- network.IPAMOptions["driver"] = types.HostLocalIPAMDriver
- }
- return nil
-}
diff --git a/libpod/network/internal/util/create.go b/libpod/network/internal/util/create.go
deleted file mode 100644
index cecfd7133..000000000
--- a/libpod/network/internal/util/create.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package util
-
-import (
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/pkg/errors"
-)
-
-func CommonNetworkCreate(n NetUtil, network *types.Network) error {
- if network.Labels == nil {
- network.Labels = map[string]string{}
- }
- if network.Options == nil {
- network.Options = map[string]string{}
- }
- if network.IPAMOptions == nil {
- network.IPAMOptions = map[string]string{}
- }
-
- var name string
- var err error
- // validate the name when given
- if network.Name != "" {
- if !define.NameRegex.MatchString(network.Name) {
- return errors.Wrapf(define.RegexError, "network name %s invalid", network.Name)
- }
- if _, err := n.Network(network.Name); err == nil {
- return errors.Wrapf(define.ErrNetworkExists, "network name %s already used", network.Name)
- }
- } else {
- name, err = GetFreeDeviceName(n)
- if err != nil {
- return err
- }
- network.Name = name
- // also use the name as interface name when we create a bridge network
- if network.Driver == types.BridgeNetworkDriver && network.NetworkInterface == "" {
- network.NetworkInterface = name
- }
- }
- return nil
-}
diff --git a/libpod/network/internal/util/interface.go b/libpod/network/internal/util/interface.go
deleted file mode 100644
index 4b01a09b8..000000000
--- a/libpod/network/internal/util/interface.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package util
-
-import "github.com/containers/podman/v3/libpod/network/types"
-
-// This is a helper package to allow code sharing between the different
-// network interfaces.
-
-// NetUtil is a helper interface which all network interfaces should implement to allow easy code sharing
-type NetUtil interface {
- // ForEach eaxecutes the given function for each network
- ForEach(func(types.Network))
- // Len returns the number of networks
- Len() int
- // DefaultInterfaceName return the default interface name, this will be suffixed by a number
- DefaultInterfaceName() string
- // Network returns the network with the given name or ID.
- // It returns an error if the network is not found
- Network(nameOrID string) (*types.Network, error)
-}
diff --git a/libpod/network/internal/util/interfaces.go b/libpod/network/internal/util/interfaces.go
deleted file mode 100644
index 20819f756..000000000
--- a/libpod/network/internal/util/interfaces.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package util
-
-import "net"
-
-// getLiveNetworkSubnets returns a slice of subnets representing what the system
-// has defined as network interfaces
-func getLiveNetworkSubnets() ([]*net.IPNet, error) {
- addrs, err := net.InterfaceAddrs()
- if err != nil {
- return nil, err
- }
- nets := make([]*net.IPNet, 0, len(addrs))
- for _, address := range addrs {
- _, n, err := net.ParseCIDR(address.String())
- if err != nil {
- return nil, err
- }
- nets = append(nets, n)
- }
- return nets, nil
-}
-
-// GetLiveNetworkNames returns a list of network interface names on the system
-func GetLiveNetworkNames() ([]string, error) {
- liveInterfaces, err := net.Interfaces()
- if err != nil {
- return nil, err
- }
- interfaceNames := make([]string, 0, len(liveInterfaces))
- for _, i := range liveInterfaces {
- interfaceNames = append(interfaceNames, i.Name)
- }
- return interfaceNames, nil
-}
diff --git a/libpod/network/internal/util/ip.go b/libpod/network/internal/util/ip.go
deleted file mode 100644
index 7fe35d3d4..000000000
--- a/libpod/network/internal/util/ip.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package util
-
-import (
- "crypto/rand"
- "net"
-
- "github.com/pkg/errors"
-)
-
-func incByte(subnet *net.IPNet, idx int, shift uint) error {
- if idx < 0 {
- return errors.New("no more subnets left")
- }
- if subnet.IP[idx] == 255 {
- subnet.IP[idx] = 0
- return incByte(subnet, idx-1, 0)
- }
- subnet.IP[idx] += 1 << shift
- return nil
-}
-
-// NextSubnet returns subnet incremented by 1
-func NextSubnet(subnet *net.IPNet) (*net.IPNet, error) {
- newSubnet := &net.IPNet{
- IP: subnet.IP,
- Mask: subnet.Mask,
- }
- ones, bits := newSubnet.Mask.Size()
- if ones == 0 {
- return nil, errors.Errorf("%s has only one subnet", subnet.String())
- }
- zeroes := uint(bits - ones)
- shift := zeroes % 8
- idx := ones/8 - 1
- if idx < 0 {
- idx = 0
- }
- if err := incByte(newSubnet, idx, shift); err != nil {
- return nil, err
- }
- return newSubnet, nil
-}
-
-func NetworkIntersectsWithNetworks(n *net.IPNet, networklist []*net.IPNet) bool {
- for _, nw := range networklist {
- if networkIntersect(n, nw) {
- return true
- }
- }
- return false
-}
-
-func networkIntersect(n1, n2 *net.IPNet) bool {
- return n2.Contains(n1.IP) || n1.Contains(n2.IP)
-}
-
-// getRandomIPv6Subnet returns a random internal ipv6 subnet as described in RFC3879.
-func getRandomIPv6Subnet() (net.IPNet, error) {
- ip := make(net.IP, 8, net.IPv6len)
- // read 8 random bytes
- _, err := rand.Read(ip)
- if err != nil {
- return net.IPNet{}, nil
- }
- // first byte must be FD as per RFC3879
- ip[0] = 0xfd
- // add 8 zero bytes
- ip = append(ip, make([]byte, 8)...)
- return net.IPNet{IP: ip, Mask: net.CIDRMask(64, 128)}, nil
-}
diff --git a/libpod/network/internal/util/ip_test.go b/libpod/network/internal/util/ip_test.go
deleted file mode 100644
index eaed769d7..000000000
--- a/libpod/network/internal/util/ip_test.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package util
-
-import (
- "fmt"
- "net"
- "reflect"
- "testing"
-)
-
-func parseCIDR(n string) *net.IPNet {
- _, parsedNet, _ := net.ParseCIDR(n)
- return parsedNet
-}
-
-func TestNextSubnet(t *testing.T) {
- type args struct {
- subnet *net.IPNet
- }
- tests := []struct {
- name string
- args args
- want *net.IPNet
- wantErr bool
- }{
- {"class b", args{subnet: parseCIDR("192.168.0.0/16")}, parseCIDR("192.169.0.0/16"), false},
- {"class c", args{subnet: parseCIDR("192.168.1.0/24")}, parseCIDR("192.168.2.0/24"), false},
- }
- for _, tt := range tests {
- test := tt
- t.Run(test.name, func(t *testing.T) {
- got, err := NextSubnet(test.args.subnet)
- if (err != nil) != test.wantErr {
- t.Errorf("NextSubnet() error = %v, wantErr %v", err, test.wantErr)
- return
- }
- if !reflect.DeepEqual(got, test.want) {
- t.Errorf("NextSubnet() got = %v, want %v", got, test.want)
- }
- })
- }
-}
-
-func TestGetRandomIPv6Subnet(t *testing.T) {
- for i := 0; i < 1000; i++ {
- t.Run(fmt.Sprintf("GetRandomIPv6Subnet %d", i), func(t *testing.T) {
- sub, err := getRandomIPv6Subnet()
- if err != nil {
- t.Errorf("GetRandomIPv6Subnet() error should be nil: %v", err)
- return
- }
- if sub.IP.To4() != nil {
- t.Errorf("ip %s is not an ipv6 address", sub.IP)
- }
- if sub.IP[0] != 0xfd {
- t.Errorf("ipv6 %s does not start with fd", sub.IP)
- }
- ones, bytes := sub.Mask.Size()
- if ones != 64 || bytes != 128 {
- t.Errorf("wrong network mask %v, it should be /64", sub.Mask)
- }
- })
- }
-}
diff --git a/libpod/network/internal/util/parse.go b/libpod/network/internal/util/parse.go
deleted file mode 100644
index 1f68df0bb..000000000
--- a/libpod/network/internal/util/parse.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package util
-
-import (
- "strconv"
-
- "github.com/pkg/errors"
-)
-
-// ParseMTU parses the mtu option
-func ParseMTU(mtu string) (int, error) {
- if mtu == "" {
- return 0, nil // default
- }
- m, err := strconv.Atoi(mtu)
- if err != nil {
- return 0, err
- }
- if m < 0 {
- return 0, errors.Errorf("mtu %d is less than zero", m)
- }
- return m, nil
-}
-
-// ParseVlan parses the vlan option
-func ParseVlan(vlan string) (int, error) {
- if vlan == "" {
- return 0, nil // default
- }
- v, err := strconv.Atoi(vlan)
- if err != nil {
- return 0, err
- }
- if v < 0 || v > 4094 {
- return 0, errors.Errorf("vlan ID %d must be between 0 and 4094", v)
- }
- return v, nil
-}
diff --git a/libpod/network/internal/util/util.go b/libpod/network/internal/util/util.go
deleted file mode 100644
index d9b9a8dc0..000000000
--- a/libpod/network/internal/util/util.go
+++ /dev/null
@@ -1,123 +0,0 @@
-package util
-
-import (
- "errors"
- "fmt"
- "net"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/pkg/util"
- "github.com/sirupsen/logrus"
-)
-
-// GetBridgeInterfaceNames returns all bridge interface names
-// already used by network configs
-func GetBridgeInterfaceNames(n NetUtil) []string {
- names := make([]string, 0, n.Len())
- n.ForEach(func(net types.Network) {
- if net.Driver == types.BridgeNetworkDriver {
- names = append(names, net.NetworkInterface)
- }
- })
- return names
-}
-
-// GetUsedNetworkNames returns all network names already used
-// by network configs
-func GetUsedNetworkNames(n NetUtil) []string {
- names := make([]string, 0, n.Len())
- n.ForEach(func(net types.Network) {
- if net.Driver == types.BridgeNetworkDriver {
- names = append(names, net.NetworkInterface)
- }
- })
- return names
-}
-
-// GetFreeDeviceName returns a free device name which can
-// be used for new configs as name and bridge interface name.
-// The base name is suffixed by a number
-func GetFreeDeviceName(n NetUtil) (string, error) {
- bridgeNames := GetBridgeInterfaceNames(n)
- netNames := GetUsedNetworkNames(n)
- liveInterfaces, err := GetLiveNetworkNames()
- if err != nil {
- return "", nil
- }
- names := make([]string, 0, len(bridgeNames)+len(netNames)+len(liveInterfaces))
- names = append(names, bridgeNames...)
- names = append(names, netNames...)
- names = append(names, liveInterfaces...)
- // FIXME: Is a limit fine?
- // Start by 1, 0 is reserved for the default network
- for i := 1; i < 1000000; i++ {
- deviceName := fmt.Sprintf("%s%d", n.DefaultInterfaceName(), i)
- if !util.StringInSlice(deviceName, names) {
- logrus.Debugf("found free device name %s", deviceName)
- return deviceName, nil
- }
- }
- return "", errors.New("could not find free device name, to many iterations")
-}
-
-// GetUsedSubnets returns a list of all used subnets by network
-// configs and interfaces on the host.
-func GetUsedSubnets(n NetUtil) ([]*net.IPNet, error) {
- // first, load all used subnets from network configs
- subnets := make([]*net.IPNet, 0, n.Len())
- n.ForEach(func(n types.Network) {
- for i := range n.Subnets {
- subnets = append(subnets, &n.Subnets[i].Subnet.IPNet)
- }
- })
- // second, load networks from the current system
- liveSubnets, err := getLiveNetworkSubnets()
- if err != nil {
- return nil, err
- }
- return append(subnets, liveSubnets...), nil
-}
-
-// GetFreeIPv4NetworkSubnet returns a unused ipv4 subnet
-func GetFreeIPv4NetworkSubnet(usedNetworks []*net.IPNet) (*types.Subnet, error) {
- // the default podman network is 10.88.0.0/16
- // start locking for free /24 networks
- network := &net.IPNet{
- IP: net.IP{10, 89, 0, 0},
- Mask: net.IPMask{255, 255, 255, 0},
- }
-
- // TODO: make sure to not use public subnets
- for {
- if intersectsConfig := NetworkIntersectsWithNetworks(network, usedNetworks); !intersectsConfig {
- logrus.Debugf("found free ipv4 network subnet %s", network.String())
- return &types.Subnet{
- Subnet: types.IPNet{IPNet: *network},
- }, nil
- }
- var err error
- network, err = NextSubnet(network)
- if err != nil {
- return nil, err
- }
- }
-}
-
-// GetFreeIPv6NetworkSubnet returns a unused ipv6 subnet
-func GetFreeIPv6NetworkSubnet(usedNetworks []*net.IPNet) (*types.Subnet, error) {
- // FIXME: Is 10000 fine as limit? We should prevent an endless loop.
- for i := 0; i < 10000; i++ {
- // RFC4193: Choose the ipv6 subnet random and NOT sequentially.
- network, err := getRandomIPv6Subnet()
- if err != nil {
- return nil, err
- }
- if intersectsConfig := NetworkIntersectsWithNetworks(&network, usedNetworks); !intersectsConfig {
- logrus.Debugf("found free ipv6 network subnet %s", network.String())
- return &types.Subnet{
- Subnet: types.IPNet{IPNet: network},
- }, nil
- }
- }
- return nil, errors.New("failed to get random ipv6 subnet")
-}
diff --git a/libpod/network/internal/util/validate.go b/libpod/network/internal/util/validate.go
deleted file mode 100644
index 62c3f3951..000000000
--- a/libpod/network/internal/util/validate.go
+++ /dev/null
@@ -1,121 +0,0 @@
-package util
-
-import (
- "net"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
- "github.com/pkg/errors"
-)
-
-// ValidateSubnet will validate a given Subnet. It checks if the
-// given gateway and lease range are part of this subnet. If the
-// gateway is empty and addGateway is true it will get the first
-// available ip in the subnet assigned.
-func ValidateSubnet(s *types.Subnet, addGateway bool, usedNetworks []*net.IPNet) error {
- if s == nil {
- return errors.New("subnet is nil")
- }
- if s.Subnet.IP == nil {
- return errors.New("subnet ip is nil")
- }
-
- // Reparse to ensure subnet is valid.
- // Do not use types.ParseCIDR() because we want the ip to be
- // the network address and not a random ip in the subnet.
- _, net, err := net.ParseCIDR(s.Subnet.String())
- if err != nil {
- return errors.Wrap(err, "subnet invalid")
- }
-
- // check that the new subnet does not conflict with existing ones
- if NetworkIntersectsWithNetworks(net, usedNetworks) {
- return errors.Errorf("subnet %s is already used on the host or by another config", net.String())
- }
-
- s.Subnet = types.IPNet{IPNet: *net}
- if s.Gateway != nil {
- if !s.Subnet.Contains(s.Gateway) {
- return errors.Errorf("gateway %s not in subnet %s", s.Gateway, &s.Subnet)
- }
- util.NormalizeIP(&s.Gateway)
- } else if addGateway {
- ip, err := util.FirstIPInSubnet(net)
- if err != nil {
- return err
- }
- s.Gateway = ip
- }
-
- if s.LeaseRange != nil {
- if s.LeaseRange.StartIP != nil {
- if !s.Subnet.Contains(s.LeaseRange.StartIP) {
- return errors.Errorf("lease range start ip %s not in subnet %s", s.LeaseRange.StartIP, &s.Subnet)
- }
- util.NormalizeIP(&s.LeaseRange.StartIP)
- }
- if s.LeaseRange.EndIP != nil {
- if !s.Subnet.Contains(s.LeaseRange.EndIP) {
- return errors.Errorf("lease range end ip %s not in subnet %s", s.LeaseRange.EndIP, &s.Subnet)
- }
- util.NormalizeIP(&s.LeaseRange.EndIP)
- }
- }
- return nil
-}
-
-// ValidateSubnets will validate the subnets for this network.
-// It also sets the gateway if the gateway is empty and it sets
-// IPv6Enabled to true if at least one subnet is ipv6.
-func ValidateSubnets(network *types.Network, usedNetworks []*net.IPNet) error {
- for i := range network.Subnets {
- err := ValidateSubnet(&network.Subnets[i], !network.Internal, usedNetworks)
- if err != nil {
- return err
- }
- if util.IsIPv6(network.Subnets[i].Subnet.IP) {
- network.IPv6Enabled = true
- }
- }
- return nil
-}
-
-func ValidateSetupOptions(n NetUtil, namespacePath string, options types.SetupOptions) error {
- if namespacePath == "" {
- return errors.New("namespacePath is empty")
- }
- if options.ContainerID == "" {
- return errors.New("ContainerID is empty")
- }
- if len(options.Networks) == 0 {
- return errors.New("must specify at least one network")
- }
- for name, netOpts := range options.Networks {
- network, err := n.Network(name)
- if err != nil {
- return err
- }
- err = validatePerNetworkOpts(network, netOpts)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-// validatePerNetworkOpts checks that all given static ips are in a subnet on this network
-func validatePerNetworkOpts(network *types.Network, netOpts types.PerNetworkOptions) error {
- if netOpts.InterfaceName == "" {
- return errors.Errorf("interface name on network %s is empty", network.Name)
- }
-outer:
- for _, ip := range netOpts.StaticIPs {
- for _, s := range network.Subnets {
- if s.Subnet.Contains(ip) {
- continue outer
- }
- }
- return errors.Errorf("requested static ip %s not in any subnet on network %s", ip.String(), network.Name)
- }
- return nil
-}
diff --git a/libpod/network/netavark/config.go b/libpod/network/netavark/config.go
deleted file mode 100644
index 5cab76710..000000000
--- a/libpod/network/netavark/config.go
+++ /dev/null
@@ -1,210 +0,0 @@
-// +build linux
-
-package netavark
-
-import (
- "encoding/json"
- "net"
- "os"
- "path/filepath"
- "time"
-
- "github.com/containers/podman/v3/libpod/define"
- internalutil "github.com/containers/podman/v3/libpod/network/internal/util"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/storage/pkg/stringid"
- "github.com/pkg/errors"
-)
-
-// NetworkCreate will take a partial filled Network and fill the
-// missing fields. It creates the Network and returns the full Network.
-func (n *netavarkNetwork) NetworkCreate(net types.Network) (types.Network, error) {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return types.Network{}, err
- }
- network, err := n.networkCreate(net, false)
- if err != nil {
- return types.Network{}, err
- }
- // add the new network to the map
- n.networks[network.Name] = network
- return *network, nil
-}
-
-func (n *netavarkNetwork) networkCreate(newNetwork types.Network, defaultNet bool) (*types.Network, error) {
- // if no driver is set use the default one
- if newNetwork.Driver == "" {
- newNetwork.Driver = types.DefaultNetworkDriver
- }
- if !defaultNet {
- // FIXME: Should we use a different type for network create without the ID field?
- // the caller is not allowed to set a specific ID
- if newNetwork.ID != "" {
- return nil, errors.Wrap(define.ErrInvalidArg, "ID can not be set for network create")
- }
-
- // generate random network ID
- var i int
- for i = 0; i < 1000; i++ {
- id := stringid.GenerateNonCryptoID()
- if _, err := n.getNetwork(id); err != nil {
- newNetwork.ID = id
- break
- }
- }
- if i == 1000 {
- return nil, errors.New("failed to create random network ID")
- }
- }
-
- err := internalutil.CommonNetworkCreate(n, &newNetwork)
- if err != nil {
- return nil, err
- }
-
- // Only get the used networks for validation if we do not create the default network.
- // The default network should not be validated against used subnets, we have to ensure
- // that this network can always be created even when a subnet is already used on the host.
- // This could happen if you run a container on this net, then the cni interface will be
- // created on the host and "block" this subnet from being used again.
- // Therefore the next podman command tries to create the default net again and it would
- // fail because it thinks the network is used on the host.
- var usedNetworks []*net.IPNet
- if !defaultNet {
- usedNetworks, err = internalutil.GetUsedSubnets(n)
- if err != nil {
- return nil, err
- }
- }
-
- switch newNetwork.Driver {
- case types.BridgeNetworkDriver:
- err = internalutil.CreateBridge(n, &newNetwork, usedNetworks)
- if err != nil {
- return nil, err
- }
- // validate the given options, we do not need them but just check to make sure they are valid
- for key, value := range newNetwork.Options {
- switch key {
- case "mtu":
- _, err = internalutil.ParseMTU(value)
- if err != nil {
- return nil, err
- }
-
- case "vlan":
- _, err = internalutil.ParseVlan(value)
- if err != nil {
- return nil, err
- }
-
- default:
- return nil, errors.Errorf("unsupported network option %s", key)
- }
- }
-
- default:
- return nil, errors.Wrapf(define.ErrInvalidArg, "unsupported driver %s", newNetwork.Driver)
- }
-
- err = internalutil.ValidateSubnets(&newNetwork, usedNetworks)
- if err != nil {
- return nil, err
- }
-
- // FIXME: If we have a working solution for internal networks with dns this check should be removed.
- if newNetwork.DNSEnabled && newNetwork.Internal {
- return nil, errors.New("cannot set internal and dns enabled")
- }
-
- newNetwork.Created = time.Now()
-
- if !defaultNet {
- confPath := filepath.Join(n.networkConfigDir, newNetwork.Name+".json")
- f, err := os.Create(confPath)
- if err != nil {
- return nil, err
- }
- enc := json.NewEncoder(f)
- enc.SetIndent("", " ")
- err = enc.Encode(newNetwork)
- if err != nil {
- return nil, err
- }
- }
-
- return &newNetwork, nil
-}
-
-// NetworkRemove will remove the Network with the given name or ID.
-// It does not ensure that the network is unused.
-func (n *netavarkNetwork) NetworkRemove(nameOrID string) error {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return err
- }
-
- network, err := n.getNetwork(nameOrID)
- if err != nil {
- return err
- }
-
- // Removing the default network is not allowed.
- if network.Name == n.defaultNetwork {
- return errors.Errorf("default network %s cannot be removed", n.defaultNetwork)
- }
-
- file := filepath.Join(n.networkConfigDir, network.Name+".json")
- // make sure to not error for ErrNotExist
- if err := os.Remove(file); err != nil && !errors.Is(err, os.ErrNotExist) {
- return err
- }
- delete(n.networks, network.Name)
- return nil
-}
-
-// NetworkList will return all known Networks. Optionally you can
-// supply a list of filter functions. Only if a network matches all
-// functions it is returned.
-func (n *netavarkNetwork) NetworkList(filters ...types.FilterFunc) ([]types.Network, error) {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return nil, err
- }
-
- networks := make([]types.Network, 0, len(n.networks))
-outer:
- for _, net := range n.networks {
- for _, filter := range filters {
- // All filters have to match, if one does not match we can skip to the next network.
- if !filter(*net) {
- continue outer
- }
- }
- networks = append(networks, *net)
- }
- return networks, nil
-}
-
-// NetworkInspect will return the Network with the given name or ID.
-func (n *netavarkNetwork) NetworkInspect(nameOrID string) (types.Network, error) {
- n.lock.Lock()
- defer n.lock.Unlock()
- err := n.loadNetworks()
- if err != nil {
- return types.Network{}, err
- }
-
- network, err := n.getNetwork(nameOrID)
- if err != nil {
- return types.Network{}, err
- }
- return *network, nil
-}
diff --git a/libpod/network/netavark/config_test.go b/libpod/network/netavark/config_test.go
deleted file mode 100644
index ee4a825f1..000000000
--- a/libpod/network/netavark/config_test.go
+++ /dev/null
@@ -1,1123 +0,0 @@
-// +build linux
-
-package netavark_test
-
-import (
- "bytes"
- "io/ioutil"
- "net"
- "os"
- "path/filepath"
- "time"
-
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- gomegaTypes "github.com/onsi/gomega/types"
- "github.com/sirupsen/logrus"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
-)
-
-var _ = Describe("Config", func() {
- var (
- libpodNet types.ContainerNetwork
- networkConfDir string
- logBuffer bytes.Buffer
- )
-
- BeforeEach(func() {
- var err error
- networkConfDir, err = ioutil.TempDir("", "podman_netavark_test")
- if err != nil {
- Fail("Failed to create tmpdir")
-
- }
- logBuffer = bytes.Buffer{}
- logrus.SetOutput(&logBuffer)
- })
-
- JustBeforeEach(func() {
- var err error
- libpodNet, err = getNetworkInterface(networkConfDir, false)
- if err != nil {
- Fail("Failed to create NewCNINetworkInterface")
- }
- })
-
- AfterEach(func() {
- os.RemoveAll(networkConfDir)
- })
-
- Context("basic network config tests", func() {
-
- It("check default network config exists", func() {
- networks, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks[0].Name).To(Equal("podman"))
- Expect(networks[0].Driver).To(Equal("bridge"))
- Expect(networks[0].ID).To(Equal("2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9"))
- Expect(networks[0].NetworkInterface).To(Equal("podman0"))
- Expect(networks[0].Created.Before(time.Now())).To(BeTrue())
- Expect(networks[0].Subnets).To(HaveLen(1))
- Expect(networks[0].Subnets[0].Subnet.String()).To(Equal("10.88.0.0/16"))
- Expect(networks[0].Subnets[0].Gateway.String()).To(Equal("10.88.0.1"))
- Expect(networks[0].Subnets[0].LeaseRange).To(BeNil())
- Expect(networks[0].IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- Expect(networks[0].Options).To(BeEmpty())
- Expect(networks[0].Labels).To(BeEmpty())
- Expect(networks[0].DNSEnabled).To(BeFalse())
- Expect(networks[0].Internal).To(BeFalse())
- })
-
- It("basic network create, inspect and remove", func() {
- // Because we get the time from the file create timestamp there is small precision
- // loss so lets remove 500 milliseconds to make sure this test does not flake.
- now := time.Now().Add(-500 * time.Millisecond)
- network := types.Network{}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- path := filepath.Join(networkConfDir, network1.Name+".json")
- Expect(path).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.IPAMOptions).ToNot(BeEmpty())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- Expect(network1.Created.After(now)).To(BeTrue())
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal("10.89.0.0/24"))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.89.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
-
- // inspect by name
- network2, err := libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- EqualNetwork(network2, network1)
-
- // inspect by ID
- network2, err = libpodNet.NetworkInspect(network1.ID)
- Expect(err).To(BeNil())
- EqualNetwork(network2, network1)
-
- // inspect by partial ID
- network2, err = libpodNet.NetworkInspect(network1.ID[:10])
- Expect(err).To(BeNil())
- EqualNetwork(network2, network1)
-
- // create a new interface to force a config load from disk
- libpodNet, err = getNetworkInterface(networkConfDir, false)
- Expect(err).To(BeNil())
-
- network2, err = libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- EqualNetwork(network2, network1)
-
- err = libpodNet.NetworkRemove(network1.Name)
- Expect(err).To(BeNil())
- Expect(path).ToNot(BeARegularFile())
-
- _, err = libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("network not found"))
- })
-
- It("create two networks", func() {
- network := types.Network{}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.Subnets).To(HaveLen(1))
-
- network = types.Network{}
- network2, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network2.Name).ToNot(Equal(network1.Name))
- Expect(network2.ID).ToNot(Equal(network1.ID))
- Expect(network2.NetworkInterface).ToNot(Equal(network1.NetworkInterface))
- Expect(network2.Subnets).To(HaveLen(1))
- Expect(network2.Subnets[0].Subnet.Contains(network1.Subnets[0].Subnet.IP)).To(BeFalse())
- })
-
- It("create bridge config", func() {
- network := types.Network{Driver: "bridge"}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(filepath.Join(networkConfDir, network1.Name+".json")).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Labels).To(BeEmpty())
- Expect(network1.Options).To(BeEmpty())
- Expect(network1.IPAMOptions).ToNot(BeEmpty())
- Expect(network1.IPAMOptions).To(HaveKeyWithValue("driver", "host-local"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal("10.89.0.0/24"))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.89.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.DNSEnabled).To(BeFalse())
- Expect(network1.Internal).To(BeFalse())
- })
-
- It("create bridge with same name should fail", func() {
- network := types.Network{
- Driver: "bridge",
- NetworkInterface: "podman2",
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).To(Equal("podman2"))
- Expect(network1.Driver).To(Equal("bridge"))
-
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("bridge name podman2 already in use"))
- })
-
- It("create bridge with subnet", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 subnet", func() {
- subnet := "fdcc::/64"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.IPv6Enabled).To(BeTrue())
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("fdcc::1"))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
-
- // reload configs from disk
- libpodNet, err = getNetworkInterface(networkConfDir, false)
- Expect(err).To(BeNil())
- // check the the networks are identical
- network2, err := libpodNet.NetworkInspect(network1.Name)
- Expect(err).To(BeNil())
- EqualNetwork(network2, network1)
- })
-
- It("create bridge with ipv6 enabled", func() {
- network := types.Network{
- Driver: "bridge",
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(ContainSubstring(".0/24"))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(ContainSubstring("::/64"))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and ipv4 subnet", func() {
- subnet := "10.100.0.0/24"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(ContainSubstring("::/64"))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and ipv6 subnet", func() {
- subnet := "fd66::/64"
- n, _ := types.ParseCIDR(subnet)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(ContainSubstring(".0/24"))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and ipv4+ipv6 subnet", func() {
- subnet1 := "10.100.0.0/24"
- n1, _ := types.ParseCIDR(subnet1)
- subnet2 := "fd66::/64"
- n2, _ := types.ParseCIDR(subnet2)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n1}, {Subnet: n2},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(2))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet1))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(Equal(subnet2))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- })
-
- It("create bridge with ipv6 enabled and two ipv4 subnets", func() {
- subnet1 := "10.100.0.0/24"
- n1, _ := types.ParseCIDR(subnet1)
- subnet2 := "10.200.0.0/24"
- n2, _ := types.ParseCIDR(subnet2)
-
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n1}, {Subnet: n2},
- },
- IPv6Enabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(3))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet1))
- Expect(network1.Subnets[0].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- Expect(network1.Subnets[1].Subnet.String()).To(Equal(subnet2))
- Expect(network1.Subnets[1].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[1].LeaseRange).To(BeNil())
- Expect(network1.Subnets[2].Subnet.String()).To(ContainSubstring("::/64"))
- Expect(network1.Subnets[2].Gateway).ToNot(BeNil())
- Expect(network1.Subnets[2].LeaseRange).To(BeNil())
- })
-
- It("create bridge with subnet and gateway", func() {
- subnet := "10.0.0.5/24"
- n, _ := types.ParseCIDR(subnet)
- gateway := "10.0.0.50"
- g := net.ParseIP(gateway)
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, Gateway: g},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal("10.0.0.0/24"))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal(gateway))
- Expect(network1.Subnets[0].LeaseRange).To(BeNil())
- })
-
- It("create bridge with subnet and gateway not in the same subnet", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- gateway := "10.10.0.50"
- g := net.ParseIP(gateway)
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, Gateway: g},
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("not in subnet"))
- })
-
- It("create bridge with subnet and lease range", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- startIP := "10.0.0.10"
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- StartIP: net.ParseIP(startIP),
- }},
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange.StartIP.String()).To(Equal(startIP))
-
- err = libpodNet.NetworkRemove(network1.Name)
- Expect(err).To(BeNil())
-
- endIP := "10.0.0.10"
- network = types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- EndIP: net.ParseIP(endIP),
- }},
- },
- }
- network1, err = libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(filepath.Join(networkConfDir, network1.Name+".json")).To(BeARegularFile())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange.EndIP.String()).To(Equal(endIP))
-
- err = libpodNet.NetworkRemove(network1.Name)
- Expect(err).To(BeNil())
-
- network = types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- StartIP: net.ParseIP(startIP),
- EndIP: net.ParseIP(endIP),
- }},
- },
- }
- network1, err = libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(BeEmpty())
- Expect(network1.ID).ToNot(BeEmpty())
- Expect(network1.NetworkInterface).ToNot(BeEmpty())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).To(Equal(subnet))
- Expect(network1.Subnets[0].Gateway.String()).To(Equal("10.0.0.1"))
- Expect(network1.Subnets[0].LeaseRange.StartIP.String()).To(Equal(startIP))
- Expect(network1.Subnets[0].LeaseRange.EndIP.String()).To(Equal(endIP))
- })
-
- It("create bridge with subnet and invalid lease range", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- startIP := "10.0.1.2"
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- StartIP: net.ParseIP(startIP),
- }},
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("not in subnet"))
-
- endIP := "10.1.1.1"
- network = types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: n, LeaseRange: &types.LeaseRange{
- EndIP: net.ParseIP(endIP),
- }},
- },
- }
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("not in subnet"))
- })
-
- It("create bridge with broken subnet", func() {
- network := types.Network{
- Driver: "bridge",
- Subnets: []types.Subnet{
- {Subnet: types.IPNet{}},
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("subnet ip is nil"))
- })
-
- It("create network with name", func() {
- name := "myname"
- network := types.Network{
- Name: name,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).To(Equal(name))
- Expect(network1.NetworkInterface).ToNot(Equal(name))
- Expect(network1.Driver).To(Equal("bridge"))
- })
-
- It("create network with invalid name", func() {
- name := "myname@some"
- network := types.Network{
- Name: name,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- })
-
- It("create network with name", func() {
- name := "myname"
- network := types.Network{
- Name: name,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).To(Equal(name))
- Expect(network1.NetworkInterface).ToNot(Equal(name))
- Expect(network1.Driver).To(Equal("bridge"))
- })
-
- It("create network with invalid name", func() {
- name := "myname@some"
- network := types.Network{
- Name: name,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- })
-
- It("create network with interface name", func() {
- name := "myname"
- network := types.Network{
- NetworkInterface: name,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).ToNot(Equal(name))
- Expect(network1.NetworkInterface).To(Equal(name))
- Expect(network1.Driver).To(Equal("bridge"))
- })
-
- It("create network with invalid interface name", func() {
- name := "myname@some"
- network := types.Network{
- NetworkInterface: name,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- })
-
- It("create network with ID should fail", func() {
- id := "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"
- network := types.Network{
- ID: id,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("ID can not be set for network create"))
- })
-
- It("create bridge with dns", func() {
- network := types.Network{
- Driver: "bridge",
- DNSEnabled: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.DNSEnabled).To(BeTrue())
- path := filepath.Join(networkConfDir, network1.Name+".json")
- Expect(path).To(BeARegularFile())
- grepInFile(path, `"dns_enabled": true`)
- })
-
- It("create bridge with internal", func() {
- network := types.Network{
- Driver: "bridge",
- Internal: true,
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Subnets).To(HaveLen(1))
- Expect(network1.Subnets[0].Subnet.String()).ToNot(BeEmpty())
- Expect(network1.Subnets[0].Gateway).To(BeNil())
- Expect(network1.Internal).To(BeTrue())
- })
-
- It("create network with labels", func() {
- network := types.Network{
- Labels: map[string]string{
- "key": "value",
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Labels).ToNot(BeNil())
- Expect(network1.Labels).To(ContainElement("value"))
- })
-
- It("create network with mtu option", func() {
- network := types.Network{
- Options: map[string]string{
- "mtu": "1500",
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Options).ToNot(BeNil())
- path := filepath.Join(networkConfDir, network1.Name+".json")
- Expect(path).To(BeARegularFile())
- grepInFile(path, `"mtu": "1500"`)
- Expect(network1.Options).To(HaveKeyWithValue("mtu", "1500"))
- })
-
- It("create network with invalid mtu option", func() {
- network := types.Network{
- Options: map[string]string{
- "mtu": "abc",
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`parsing "abc": invalid syntax`))
-
- network = types.Network{
- Options: map[string]string{
- "mtu": "-1",
- },
- }
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`mtu -1 is less than zero`))
- })
-
- It("create network with vlan option", func() {
- network := types.Network{
- Options: map[string]string{
- "vlan": "5",
- },
- }
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Driver).To(Equal("bridge"))
- Expect(network1.Options).ToNot(BeNil())
- path := filepath.Join(networkConfDir, network1.Name+".json")
- Expect(path).To(BeARegularFile())
- grepInFile(path, `"vlan": "5"`)
- Expect(network1.Options).To(HaveKeyWithValue("vlan", "5"))
- })
-
- It("create network with invalid vlan option", func() {
- network := types.Network{
- Options: map[string]string{
- "vlan": "abc",
- },
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`parsing "abc": invalid syntax`))
-
- network = types.Network{
- Options: map[string]string{
- "vlan": "-1",
- },
- }
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring(`vlan ID -1 must be between 0 and 4094`))
- })
-
- It("network create unsupported option", func() {
- network := types.Network{Options: map[string]string{
- "someopt": "",
- }}
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("unsupported network option someopt"))
- })
-
- It("network create unsupported driver", func() {
- network := types.Network{
- Driver: "someDriver",
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("unsupported driver someDriver"))
- })
-
- It("network create internal and dns", func() {
- network := types.Network{
- Driver: "bridge",
- Internal: true,
- DNSEnabled: true,
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("cannot set internal and dns enabled"))
- })
-
- It("network inspect partial ID", func() {
- network := types.Network{Name: "net4"}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.ID).To(HaveLen(64))
-
- network2, err := libpodNet.NetworkInspect(network1.ID[:10])
- Expect(err).ToNot(HaveOccurred())
- EqualNetwork(network2, network1)
- })
-
- It("network create two with same name", func() {
- network := types.Network{Name: "net"}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Name).To(Equal("net"))
- network = types.Network{Name: "net"}
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("network name net already used"))
- })
-
- It("remove default network config should fail", func() {
- err := libpodNet.NetworkRemove("podman")
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("default network podman cannot be removed"))
-
- network, err := libpodNet.NetworkInspect("podman")
- Expect(err).To(BeNil())
- err = libpodNet.NetworkRemove(network.ID)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("default network podman cannot be removed"))
- })
-
- It("network create with same subnet", func() {
- subnet := "10.0.0.0/24"
- n, _ := types.ParseCIDR(subnet)
- subnet2 := "10.10.0.0/24"
- n2, _ := types.ParseCIDR(subnet2)
- network := types.Network{Subnets: []types.Subnet{{Subnet: n}, {Subnet: n2}}}
- network1, err := libpodNet.NetworkCreate(network)
- Expect(err).To(BeNil())
- Expect(network1.Subnets).To(HaveLen(2))
- network = types.Network{Subnets: []types.Subnet{{Subnet: n}}}
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("subnet 10.0.0.0/24 is already used on the host or by another config"))
- network = types.Network{Subnets: []types.Subnet{{Subnet: n2}}}
- _, err = libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("subnet 10.10.0.0/24 is already used on the host or by another config"))
- })
- })
-
- Context("network load valid existing ones", func() {
-
- BeforeEach(func() {
- dir := "testfiles/valid"
- files, err := ioutil.ReadDir(dir)
- if err != nil {
- Fail("Failed to read test directory")
- }
- for _, file := range files {
- filename := file.Name()
- data, err := ioutil.ReadFile(filepath.Join(dir, filename))
- if err != nil {
- Fail("Failed to copy test files")
- }
- err = ioutil.WriteFile(filepath.Join(networkConfDir, filename), data, 0700)
- if err != nil {
- Fail("Failed to copy test files")
- }
- }
- })
-
- It("load networks from disk", func() {
- nets, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(7))
- // test the we do not show logrus warnings/errors
- logString := logBuffer.String()
- Expect(logString).To(BeEmpty())
- })
-
- It("change network struct fields should not affect network struct in the backend", func() {
- nets, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(7))
-
- nets[0].Name = "myname"
- nets, err = libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(7))
- Expect(nets).ToNot(ContainElement(HaveNetworkName("myname")))
-
- network, err := libpodNet.NetworkInspect("bridge")
- Expect(err).To(BeNil())
- network.NetworkInterface = "abc"
-
- network, err = libpodNet.NetworkInspect("bridge")
- Expect(err).To(BeNil())
- Expect(network.NetworkInterface).ToNot(Equal("abc"))
- })
-
- It("bridge network", func() {
- network, err := libpodNet.NetworkInspect("bridge")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("bridge"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("podman9"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Subnets[0].Subnet.String()).To(Equal("10.89.8.0/24"))
- Expect(network.Subnets[0].Gateway.String()).To(Equal("10.89.8.1"))
- Expect(network.Subnets[0].LeaseRange).ToNot(BeNil())
- Expect(network.Subnets[0].LeaseRange.StartIP.String()).To(Equal("10.89.8.20"))
- Expect(network.Subnets[0].LeaseRange.EndIP.String()).To(Equal("10.89.8.50"))
- Expect(network.Internal).To(BeFalse())
- })
-
- It("internal network", func() {
- network, err := libpodNet.NetworkInspect("internal")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("internal"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("podman8"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Subnets[0].Subnet.String()).To(Equal("10.89.7.0/24"))
- Expect(network.Subnets[0].Gateway).To(BeNil())
- Expect(network.Internal).To(BeTrue())
- })
-
- It("bridge network with mtu", func() {
- network, err := libpodNet.NetworkInspect("mtu")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("mtu"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("podman13"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Subnets[0].Subnet.String()).To(Equal("10.89.11.0/24"))
- Expect(network.Subnets[0].Gateway.String()).To(Equal("10.89.11.1"))
- Expect(network.Internal).To(BeFalse())
- Expect(network.Options).To(HaveLen(1))
- Expect(network.Options).To(HaveKeyWithValue("mtu", "1500"))
- })
-
- It("bridge network with vlan", func() {
- network, err := libpodNet.NetworkInspect("vlan")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("vlan"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("podman14"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Options).To(HaveLen(1))
- Expect(network.Options).To(HaveKeyWithValue("vlan", "5"))
- })
-
- It("bridge network with labels", func() {
- network, err := libpodNet.NetworkInspect("label")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("label"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("podman15"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(1))
- Expect(network.Labels).To(HaveLen(1))
- Expect(network.Labels).To(HaveKeyWithValue("mykey", "value"))
- })
-
- It("dual stack network", func() {
- network, err := libpodNet.NetworkInspect("dualstack")
- Expect(err).To(BeNil())
- Expect(network.Name).To(Equal("dualstack"))
- Expect(network.ID).To(HaveLen(64))
- Expect(network.NetworkInterface).To(Equal("podman21"))
- Expect(network.Driver).To(Equal("bridge"))
- Expect(network.Subnets).To(HaveLen(2))
-
- sub1, _ := types.ParseCIDR("fd10:88:a::/64")
- sub2, _ := types.ParseCIDR("10.89.19.0/24")
- Expect(network.Subnets).To(ContainElements(
- types.Subnet{Subnet: sub1, Gateway: net.ParseIP("fd10:88:a::1")},
- types.Subnet{Subnet: sub2, Gateway: net.ParseIP("10.89.19.10").To4()},
- ))
- })
-
- It("network list with filters (name)", func() {
- filters := map[string][]string{
- "name": {"internal", "bridge"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (partial name)", func() {
- filters := map[string][]string{
- "name": {"inte", "bri"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (id)", func() {
- filters := map[string][]string{
- "id": {"3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f", "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (id)", func() {
- filters := map[string][]string{
- "id": {"3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f", "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (partial id)", func() {
- filters := map[string][]string{
- "id": {"3bed2cb3a3acf7b6a8ef408420", "17f29b073143d8cd97b5bbe492bde"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(2))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge")))
- })
-
- It("network list with filters (driver)", func() {
- filters := map[string][]string{
- "driver": {"bridge"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(7))
- Expect(networks).To(ConsistOf(HaveNetworkName("internal"), HaveNetworkName("bridge"),
- HaveNetworkName("mtu"), HaveNetworkName("vlan"), HaveNetworkName("podman"),
- HaveNetworkName("label"), HaveNetworkName("dualstack")))
- })
-
- It("network list with filters (label)", func() {
- filters := map[string][]string{
- "label": {"mykey"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks).To(ConsistOf(HaveNetworkName("label")))
-
- filters = map[string][]string{
- "label": {"mykey=value"},
- }
- filterFuncs, err = util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err = libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks).To(ConsistOf(HaveNetworkName("label")))
- })
-
- It("network list with filters", func() {
- filters := map[string][]string{
- "driver": {"bridge"},
- "label": {"mykey"},
- }
- filterFuncs, err := util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
- Expect(filterFuncs).To(HaveLen(2))
-
- networks, err := libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(1))
- Expect(networks).To(ConsistOf(HaveNetworkName("label")))
-
- filters = map[string][]string{
- "driver": {"macvlan"},
- "label": {"mykey"},
- }
- filterFuncs, err = util.GenerateNetworkFilters(filters)
- Expect(err).To(BeNil())
-
- networks, err = libpodNet.NetworkList(filterFuncs...)
- Expect(err).To(BeNil())
- Expect(networks).To(HaveLen(0))
- })
-
- It("create bridge network with used interface name", func() {
- network := types.Network{
- NetworkInterface: "podman9",
- }
- _, err := libpodNet.NetworkCreate(network)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("bridge name podman9 already in use"))
- })
- })
-
- Context("network load invalid existing ones", func() {
-
- BeforeEach(func() {
- dir := "testfiles/invalid"
- files, err := ioutil.ReadDir(dir)
- if err != nil {
- Fail("Failed to read test directory")
- }
- for _, file := range files {
- filename := file.Name()
- data, err := ioutil.ReadFile(filepath.Join(dir, filename))
- if err != nil {
- Fail("Failed to copy test files")
- }
- err = ioutil.WriteFile(filepath.Join(networkConfDir, filename), data, 0700)
- if err != nil {
- Fail("Failed to copy test files")
- }
- }
- })
-
- It("load invalid networks from disk", func() {
- nets, err := libpodNet.NetworkList()
- Expect(err).To(BeNil())
- Expect(nets).To(HaveLen(1))
- logString := logBuffer.String()
- Expect(logString).To(ContainSubstring("Error reading network config file \\\"%s/broken.json\\\": unexpected EOF", networkConfDir))
- Expect(logString).To(ContainSubstring("Network config \\\"%s/invalid name.json\\\" has invalid name: \\\"invalid name\\\", skipping: names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*: invalid argument", networkConfDir))
- Expect(logString).To(ContainSubstring("Network config name \\\"name_miss\\\" does not match file name \\\"name_missmatch.json\\\", skipping"))
- Expect(logString).To(ContainSubstring("Network config \\\"%s/wrongID.json\\\" could not be parsed, skipping: invalid network ID \\\"someID\\\"", networkConfDir))
- Expect(logString).To(ContainSubstring("Network config \\\"%s/invalid_gateway.json\\\" could not be parsed, skipping: gateway 10.89.100.1 not in subnet 10.89.9.0/24", networkConfDir))
- })
-
- })
-
-})
-
-func grepInFile(path string, match string) {
- data, err := ioutil.ReadFile(path)
- ExpectWithOffset(1, err).To(BeNil())
- ExpectWithOffset(1, string(data)).To(ContainSubstring(match))
-}
-
-// HaveNetworkName is a custom GomegaMatcher to match a network name
-func HaveNetworkName(name string) gomegaTypes.GomegaMatcher {
- return WithTransform(func(e types.Network) string {
- return e.Name
- }, Equal(name))
-}
-
-// EqualNetwork must be used because comparing the time with deep equal does not work
-func EqualNetwork(net1, net2 types.Network) {
- ExpectWithOffset(1, net1.Created.Equal(net2.Created)).To(BeTrue(), "net1 created: %v is not equal net2 created: %v", net1.Created, net2.Created)
- net1.Created = time.Time{}
- net2.Created = time.Time{}
- ExpectWithOffset(1, net1).To(Equal(net2))
-}
diff --git a/libpod/network/netavark/const.go b/libpod/network/netavark/const.go
deleted file mode 100644
index 9709315c6..000000000
--- a/libpod/network/netavark/const.go
+++ /dev/null
@@ -1,5 +0,0 @@
-// +build linux
-
-package netavark
-
-const defaultBridgeName = "podman"
diff --git a/libpod/network/netavark/exec.go b/libpod/network/netavark/exec.go
deleted file mode 100644
index 01dea8489..000000000
--- a/libpod/network/netavark/exec.go
+++ /dev/null
@@ -1,159 +0,0 @@
-package netavark
-
-import (
- "encoding/json"
- "errors"
- "io"
- "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,
- }
-}
-
-// 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()
- // rust env_log uses warn instead of warning
- if level == "warning" {
- level = "warn"
- }
- // the rust netlink library is very verbose
- // make sure to only log netavark logs
- return "RUST_LOG=netavark=" + level
-}
-
-// 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 (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)
- }
- 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)
- }
- stdoutWClosed := false
- defer func() {
- stdoutR.Close()
- if !stdoutWClosed {
- stdoutW.Close()
- }
- }()
-
- // 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
- 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
- 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)
- // 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)
- }
-
- 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) {
- 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
-}
diff --git a/libpod/network/netavark/ipam.go b/libpod/network/netavark/ipam.go
deleted file mode 100644
index db46ee652..000000000
--- a/libpod/network/netavark/ipam.go
+++ /dev/null
@@ -1,368 +0,0 @@
-package netavark
-
-import (
- "encoding/json"
- "fmt"
- "net"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
- "github.com/pkg/errors"
- "go.etcd.io/bbolt"
-)
-
-// IPAM boltdb structure
-// Each network has their own bucket with the network name as bucket key.
-// Inside the network bucket there is an ID bucket which maps the container ID (key)
-// to a json array of ip addresses (value).
-// The network bucket also has a bucket for each subnet, the subnet is used as key.
-// Inside the subnet bucket an ip is used as key and the container ID as value.
-
-const (
- idBucket = "ids"
- // lastIP this is used as key to store the last allocated ip
- // note that this string should not be 4 or 16 byte long
- lastIP = "lastIP"
-)
-
-var (
- idBucketKey = []byte(idBucket)
- lastIPKey = []byte(lastIP)
-)
-
-type ipamError struct {
- msg string
- cause error
-}
-
-func (e *ipamError) Error() string {
- msg := "IPAM error"
- if e.msg != "" {
- msg += ": " + e.msg
- }
- if e.cause != nil {
- msg += ": " + e.cause.Error()
- }
- return msg
-}
-
-func newIPAMError(cause error, msg string, args ...interface{}) *ipamError {
- return &ipamError{
- msg: fmt.Sprintf(msg, args...),
- cause: cause,
- }
-}
-
-// openDB will open the ipam database
-// Note that the caller has to Close it.
-func (n *netavarkNetwork) openDB() (*bbolt.DB, error) {
- db, err := bbolt.Open(n.ipamDBPath, 0600, nil)
- if err != nil {
- return nil, newIPAMError(err, "failed to open database %s", n.ipamDBPath)
- }
- return db, nil
-}
-
-// allocIPs will allocate ips for the the container. It will change the
-// NetworkOptions in place. When static ips are given it will validate
-// that these are free to use and will allocate them to the container.
-func (n *netavarkNetwork) allocIPs(opts *types.NetworkOptions) error {
- db, err := n.openDB()
- if err != nil {
- return err
- }
- defer db.Close()
-
- err = db.Update(func(tx *bbolt.Tx) error {
- for netName, netOpts := range opts.Networks {
- network := n.networks[netName]
- if network == nil {
- return newIPAMError(nil, "could not find network %q", netName)
- }
-
- // check if we have to alloc ips
- if !requiresIPAMAlloc(network) {
- continue
- }
-
- // create/get network bucket
- netBkt, err := tx.CreateBucketIfNotExists([]byte(netName))
- if err != nil {
- return newIPAMError(err, "failed to create/get network bucket for network %s", netName)
- }
-
- // requestIPs is the list of ips which should be used for this container
- requestIPs := make([]net.IP, 0, len(network.Subnets))
-
- for _, subnet := range network.Subnets {
- subnetBkt, err := netBkt.CreateBucketIfNotExists([]byte(subnet.Subnet.String()))
- if err != nil {
- return newIPAMError(err, "failed to create/get subnet bucket for network %s", netName)
- }
-
- // search for a static ip which matches the current subnet
- // in this case the user wants this one and we should not assign a free one
- var ip net.IP
- for _, staticIP := range netOpts.StaticIPs {
- if subnet.Subnet.Contains(staticIP) {
- ip = staticIP
- break
- }
- }
-
- // when static ip is requested for this network
- if ip != nil {
- // convert to 4 byte ipv4 if needed
- util.NormalizeIP(&ip)
- id := subnetBkt.Get(ip)
- if id != nil {
- return newIPAMError(nil, "requested ip address %s is already allocated to container ID %s", ip.String(), string(id))
- }
- } else {
- ip, err = getFreeIPFromBucket(subnetBkt, subnet)
- if err != nil {
- return err
- }
- err = subnetBkt.Put(lastIPKey, ip)
- if err != nil {
- return newIPAMError(err, "failed to store last ip in database")
- }
- }
-
- err = subnetBkt.Put(ip, []byte(opts.ContainerID))
- if err != nil {
- return newIPAMError(err, "failed to store ip in database")
- }
-
- requestIPs = append(requestIPs, ip)
- }
-
- idsBucket, err := netBkt.CreateBucketIfNotExists(idBucketKey)
- if err != nil {
- return newIPAMError(err, "failed to create/get id bucket for network %s", netName)
- }
-
- ipsBytes, err := json.Marshal(requestIPs)
- if err != nil {
- return newIPAMError(err, "failed to marshal ips")
- }
-
- err = idsBucket.Put([]byte(opts.ContainerID), ipsBytes)
- if err != nil {
- return newIPAMError(err, "failed to store ips in database")
- }
-
- netOpts.StaticIPs = requestIPs
- opts.Networks[netName] = netOpts
- }
- return nil
- })
- return err
-}
-
-func getFreeIPFromBucket(bucket *bbolt.Bucket, subnet types.Subnet) (net.IP, error) {
- var rangeStart net.IP
- var rangeEnd net.IP
- if subnet.LeaseRange != nil {
- rangeStart = subnet.LeaseRange.StartIP
- rangeEnd = subnet.LeaseRange.EndIP
- }
-
- if rangeStart == nil {
- // let start with the first ip in subnet
- rangeStart = util.NextIP(subnet.Subnet.IP)
- }
-
- if rangeEnd == nil {
- lastIP, err := util.LastIPInSubnet(&subnet.Subnet.IPNet)
- // this error should never happen but lets check anyways to prevent panics
- if err != nil {
- return nil, errors.Wrap(err, "failed to get lastIP")
- }
- // ipv4 uses the last ip in a subnet for broadcast so we cannot use it
- if util.IsIPv4(lastIP) {
- lastIP = util.PrevIP(lastIP)
- }
- rangeEnd = lastIP
- }
-
- lastIPByte := bucket.Get(lastIPKey)
- curIP := net.IP(lastIPByte)
- if curIP == nil {
- curIP = rangeStart
- } else {
- curIP = util.NextIP(curIP)
- }
-
- // store the start ip to make sure we know when we looped over all available ips
- startIP := curIP
-
- for {
- // skip the gateway
- if subnet.Gateway != nil {
- if util.Cmp(curIP, subnet.Gateway) == 0 {
- curIP = util.NextIP(curIP)
- continue
- }
- }
-
- // if we are at the end we need to jump back to the start ip
- if util.Cmp(curIP, rangeEnd) > 0 {
- if util.Cmp(rangeStart, startIP) == 0 {
- return nil, newIPAMError(nil, "failed to find free IP in range: %s - %s", rangeStart.String(), rangeEnd.String())
- }
- curIP = rangeStart
- continue
- }
-
- // check if ip is already used by another container
- // if not return it
- if bucket.Get(curIP) == nil {
- return curIP, nil
- }
-
- curIP = util.NextIP(curIP)
-
- if util.Cmp(curIP, startIP) == 0 {
- return nil, newIPAMError(nil, "failed to find free IP in range: %s - %s", rangeStart.String(), rangeEnd.String())
- }
- }
-}
-
-// getAssignedIPs will read the ipam database and will fill in the used ips for this container.
-// It will change the NetworkOptions in place.
-func (n *netavarkNetwork) getAssignedIPs(opts *types.NetworkOptions) error {
- db, err := n.openDB()
- if err != nil {
- return err
- }
- defer db.Close()
-
- err = db.View(func(tx *bbolt.Tx) error {
- for netName, netOpts := range opts.Networks {
- network := n.networks[netName]
- if network == nil {
- return newIPAMError(nil, "could not find network %q", netName)
- }
-
- // check if we have to alloc ips
- if !requiresIPAMAlloc(network) {
- continue
- }
- // get network bucket
- netBkt := tx.Bucket([]byte(netName))
- if netBkt == nil {
- return newIPAMError(nil, "failed to get network bucket for network %s", netName)
- }
-
- idBkt := netBkt.Bucket(idBucketKey)
- if idBkt == nil {
- return newIPAMError(nil, "failed to get id bucket for network %s", netName)
- }
-
- ipJSON := idBkt.Get([]byte(opts.ContainerID))
- if ipJSON == nil {
- return newIPAMError(nil, "failed to get ips for container ID %s on network %s", opts.ContainerID, netName)
- }
-
- // assignedIPs is the list of ips which should be used for this container
- assignedIPs := make([]net.IP, 0, len(network.Subnets))
-
- err = json.Unmarshal(ipJSON, &assignedIPs)
- if err != nil {
- return newIPAMError(err, "failed to unmarshal ips from database")
- }
-
- for i := range assignedIPs {
- util.NormalizeIP(&assignedIPs[i])
- }
-
- netOpts.StaticIPs = assignedIPs
- opts.Networks[netName] = netOpts
- }
- return nil
- })
- return err
-}
-
-// deallocIPs will release the ips in the network options from the DB so that
-// they can be reused by other containers. It expects that the network options
-// are already filled with the correct ips. Use getAssignedIPs() for this.
-func (n *netavarkNetwork) deallocIPs(opts *types.NetworkOptions) error {
- db, err := n.openDB()
- if err != nil {
- return err
- }
- defer db.Close()
-
- err = db.Update(func(tx *bbolt.Tx) error {
- for netName, netOpts := range opts.Networks {
- network := n.networks[netName]
- if network == nil {
- return newIPAMError(nil, "could not find network %q", netName)
- }
-
- // check if we have to alloc ips
- if !requiresIPAMAlloc(network) {
- continue
- }
- // get network bucket
- netBkt := tx.Bucket([]byte(netName))
- if netBkt == nil {
- return newIPAMError(nil, "failed to get network bucket for network %s", netName)
- }
-
- for _, subnet := range network.Subnets {
- subnetBkt := netBkt.Bucket([]byte(subnet.Subnet.String()))
- if subnetBkt == nil {
- return newIPAMError(nil, "failed to get subnet bucket for network %s", netName)
- }
-
- // search for a static ip which matches the current subnet
- // in this case the user wants this one and we should not assign a free one
- var ip net.IP
- for _, staticIP := range netOpts.StaticIPs {
- if subnet.Subnet.Contains(staticIP) {
- ip = staticIP
- break
- }
- }
- if ip == nil {
- return newIPAMError(nil, "failed to find ip for subnet %s on network %s", subnet.Subnet.String(), netName)
- }
- util.NormalizeIP(&ip)
-
- err = subnetBkt.Delete(ip)
- if err != nil {
- return newIPAMError(err, "failed to remove ip %s from subnet bucket for network %s", ip.String(), netName)
- }
- }
-
- idBkt := netBkt.Bucket(idBucketKey)
- if idBkt == nil {
- return newIPAMError(nil, "failed to get id bucket for network %s", netName)
- }
-
- err = idBkt.Delete([]byte(opts.ContainerID))
- if err != nil {
- return newIPAMError(err, "failed to remove allocated ips for container ID %s on network %s", opts.ContainerID, netName)
- }
- }
- return nil
- })
- return err
-}
-
-// requiresIPAMAlloc return true when we have to allocate ips for this network
-// it checks the ipam driver and if subnets are set
-func requiresIPAMAlloc(network *types.Network) bool {
- // only do host allocation when driver is set to HostLocalIPAMDriver or unset
- switch network.IPAMOptions["driver"] {
- case "", types.HostLocalIPAMDriver:
- default:
- return false
- }
-
- // no subnets == no ips to assign
- return len(network.Subnets) > 0
-}
diff --git a/libpod/network/netavark/ipam_test.go b/libpod/network/netavark/ipam_test.go
deleted file mode 100644
index 4b3947501..000000000
--- a/libpod/network/netavark/ipam_test.go
+++ /dev/null
@@ -1,433 +0,0 @@
-package netavark
-
-import (
- "bytes"
- "fmt"
- "io/ioutil"
- "net"
- "os"
- "path/filepath"
-
- "github.com/containers/podman/v3/libpod/network/types"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- "github.com/sirupsen/logrus"
-)
-
-var _ = Describe("IPAM", func() {
- var (
- networkInterface *netavarkNetwork
- networkConfDir string
- logBuffer bytes.Buffer
- )
-
- BeforeEach(func() {
- var err error
- networkConfDir, err = ioutil.TempDir("", "podman_netavark_test")
- if err != nil {
- Fail("Failed to create tmpdir")
-
- }
- logBuffer = bytes.Buffer{}
- logrus.SetOutput(&logBuffer)
- })
-
- JustBeforeEach(func() {
- libpodNet, err := NewNetworkInterface(InitConfig{
- NetworkConfigDir: networkConfDir,
- IPAMDBPath: filepath.Join(networkConfDir, "ipam.db"),
- LockFile: filepath.Join(networkConfDir, "netavark.lock"),
- })
- if err != nil {
- Fail("Failed to create NewCNINetworkInterface")
- }
-
- networkInterface = libpodNet.(*netavarkNetwork)
- // run network list to force a network load
- networkInterface.NetworkList()
- })
-
- AfterEach(func() {
- os.RemoveAll(networkConfDir)
- })
-
- It("simple ipam alloc", func() {
- netName := types.DefaultNetworkName
- for i := 2; i < 100; i++ {
- opts := &types.NetworkOptions{
- ContainerID: "someContainerID",
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
-
- err := networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.88.0.%d", i)).To4()))
- }
- })
-
- It("ipam try to alloc same ip", func() {
- netName := types.DefaultNetworkName
- opts := &types.NetworkOptions{
- ContainerID: "someContainerID",
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
-
- err := networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.88.0.2").To4()))
-
- opts = &types.NetworkOptions{
- ContainerID: "otherID",
- Networks: map[string]types.PerNetworkOptions{
- netName: {StaticIPs: []net.IP{net.ParseIP("10.88.0.2")}},
- },
- }
- err = networkInterface.allocIPs(opts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("IPAM error: requested ip address 10.88.0.2 is already allocated to container ID someContainerID"))
- })
-
- It("ipam try to alloc more ips as in range", func() {
- s, _ := types.ParseCIDR("10.0.0.1/24")
- network, err := networkInterface.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {
- Subnet: s,
- LeaseRange: &types.LeaseRange{
- StartIP: net.ParseIP("10.0.0.10"),
- EndIP: net.ParseIP("10.0.0.20"),
- },
- },
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName := network.Name
-
- for i := 10; i < 21; i++ {
- opts := &types.NetworkOptions{
- ContainerID: fmt.Sprintf("someContainerID-%d", i),
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
-
- err = networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", i)).To4()))
- }
-
- opts := &types.NetworkOptions{
- ContainerID: "someContainerID-22",
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
-
- // now this should fail because all free ips are already assigned
- err = networkInterface.allocIPs(opts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("IPAM error: failed to find free IP in range: 10.0.0.10 - 10.0.0.20"))
- })
-
- It("ipam basic setup", func() {
- netName := types.DefaultNetworkName
- opts := &types.NetworkOptions{
- ContainerID: "someContainerID",
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
-
- expectedIP := net.ParseIP("10.88.0.2").To4()
-
- err := networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(expectedIP))
-
- // remove static ips from opts
- netOpts := opts.Networks[netName]
- netOpts.StaticIPs = nil
- opts.Networks[netName] = netOpts
-
- err = networkInterface.getAssignedIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(expectedIP))
-
- err = networkInterface.allocIPs(opts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("IPAM error: requested ip address 10.88.0.2 is already allocated to container ID someContainerID"))
-
- // dealloc the ip
- err = networkInterface.deallocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
-
- err = networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(expectedIP))
- })
-
- It("ipam dual stack", func() {
- s1, _ := types.ParseCIDR("10.0.0.0/26")
- s2, _ := types.ParseCIDR("fd80::/24")
- network, err := networkInterface.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {
- Subnet: s1,
- },
- {
- Subnet: s2,
- },
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName := network.Name
-
- opts := &types.NetworkOptions{
- ContainerID: "someContainerID",
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
-
- err = networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(2))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
- Expect(opts.Networks[netName].StaticIPs[1]).To(Equal(net.ParseIP("fd80::2")))
-
- // remove static ips from opts
- netOpts := opts.Networks[netName]
- netOpts.StaticIPs = nil
- opts.Networks[netName] = netOpts
-
- err = networkInterface.getAssignedIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(2))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
- Expect(opts.Networks[netName].StaticIPs[1]).To(Equal(net.ParseIP("fd80::2")))
-
- err = networkInterface.deallocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
-
- // try to alloc the same again
- err = networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(2))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
- Expect(opts.Networks[netName].StaticIPs[1]).To(Equal(net.ParseIP("fd80::2")))
- })
-
- It("ipam with two networks", func() {
- s, _ := types.ParseCIDR("10.0.0.0/24")
- network, err := networkInterface.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {
- Subnet: s,
- },
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName1 := network.Name
-
- s, _ = types.ParseCIDR("10.0.1.0/24")
- network, err = networkInterface.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {
- Subnet: s,
- },
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName2 := network.Name
-
- opts := &types.NetworkOptions{
- ContainerID: "someContainerID",
- Networks: map[string]types.PerNetworkOptions{
- netName1: {},
- netName2: {},
- },
- }
-
- err = networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName1))
- Expect(opts.Networks[netName1].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName1].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
- Expect(opts.Networks).To(HaveKey(netName2))
- Expect(opts.Networks[netName2].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName2].StaticIPs[0]).To(Equal(net.ParseIP("10.0.1.2").To4()))
-
- // remove static ips from opts
- netOpts := opts.Networks[netName1]
- netOpts.StaticIPs = nil
- opts.Networks[netName1] = netOpts
- netOpts = opts.Networks[netName2]
- netOpts.StaticIPs = nil
- opts.Networks[netName2] = netOpts
-
- err = networkInterface.getAssignedIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName1))
- Expect(opts.Networks[netName1].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName1].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
- Expect(opts.Networks).To(HaveKey(netName2))
- Expect(opts.Networks[netName2].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName2].StaticIPs[0]).To(Equal(net.ParseIP("10.0.1.2").To4()))
-
- err = networkInterface.deallocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
-
- // try to alloc the same again
- err = networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName1))
- Expect(opts.Networks[netName1].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName1].StaticIPs[0]).To(Equal(net.ParseIP("10.0.0.2").To4()))
- Expect(opts.Networks).To(HaveKey(netName2))
- Expect(opts.Networks[netName2].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName2].StaticIPs[0]).To(Equal(net.ParseIP("10.0.1.2").To4()))
- })
-
- It("ipam alloc more ips as in subnet", func() {
- s, _ := types.ParseCIDR("10.0.0.0/26")
- network, err := networkInterface.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {
- Subnet: s,
- },
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName := network.Name
-
- for i := 2; i < 64; i++ {
- opts := &types.NetworkOptions{
- ContainerID: fmt.Sprintf("id-%d", i),
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
- err = networkInterface.allocIPs(opts)
- if i < 63 {
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", i)).To4()))
- } else {
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("IPAM error: failed to find free IP in range: 10.0.0.1 - 10.0.0.62"))
- }
- }
- })
-
- It("ipam alloc -> dealloc -> alloc", func() {
- s, _ := types.ParseCIDR("10.0.0.0/27")
- network, err := networkInterface.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {
- Subnet: s,
- },
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName := network.Name
-
- for i := 2; i < 10; i++ {
- opts := types.NetworkOptions{
- ContainerID: fmt.Sprintf("id-%d", i),
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
- err = networkInterface.allocIPs(&opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", i)).To4()))
-
- err = networkInterface.deallocIPs(&opts)
- Expect(err).ToNot(HaveOccurred())
- }
-
- for i := 0; i < 30; i++ {
- opts := types.NetworkOptions{
- ContainerID: fmt.Sprintf("id-%d", i),
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
- err = networkInterface.allocIPs(&opts)
- if i < 29 {
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(1))
- // The (i+8)%29+2 part looks cryptic but it is actually simple, we already have 8 ips allocated above
- // so we expect the 8 available ip. We have 29 assignable ip addresses in this subnet because "i"+8 can
- // be greater than 30 we have to modulo by 29 to go back to the beginning. Also the first free ip is
- // network address + 2, so we have to add 2 to the result
- Expect(opts.Networks[netName].StaticIPs[0]).To(Equal(net.ParseIP(fmt.Sprintf("10.0.0.%d", (i+8)%29+2)).To4()))
- } else {
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(Equal("IPAM error: failed to find free IP in range: 10.0.0.1 - 10.0.0.30"))
- }
- }
- })
-
- It("ipam with dhcp driver should not set ips", func() {
- network, err := networkInterface.NetworkCreate(types.Network{
- IPAMOptions: map[string]string{
- "driver": types.DHCPIPAMDriver,
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName := network.Name
-
- opts := &types.NetworkOptions{
- ContainerID: "someContainerID",
- Networks: map[string]types.PerNetworkOptions{
- netName: {},
- },
- }
-
- err = networkInterface.allocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(0))
-
- err = networkInterface.getAssignedIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(opts.Networks).To(HaveKey(netName))
- Expect(opts.Networks[netName].StaticIPs).To(HaveLen(0))
-
- // dealloc the ip
- err = networkInterface.deallocIPs(opts)
- Expect(err).ToNot(HaveOccurred())
- })
-
-})
diff --git a/libpod/network/netavark/netavark_suite_test.go b/libpod/network/netavark/netavark_suite_test.go
deleted file mode 100644
index 6063a54e3..000000000
--- a/libpod/network/netavark/netavark_suite_test.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// +build linux
-
-package netavark_test
-
-import (
- "fmt"
- "net"
- "os"
- "path/filepath"
- "reflect"
- "testing"
-
- "github.com/containers/podman/v3/libpod/network/netavark"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- gomegaTypes "github.com/onsi/gomega/types"
-)
-
-func TestNetavark(t *testing.T) {
- RegisterFailHandler(Fail)
- RunSpecs(t, "Netavark Suite")
-}
-
-var netavarkBinary string
-
-func init() {
- netavarkBinary = os.Getenv("NETAVARK_BINARY")
- if netavarkBinary == "" {
- netavarkBinary = "/usr/libexec/podman/netavark"
- }
-}
-
-func getNetworkInterface(confDir string, machine bool) (types.ContainerNetwork, error) {
- return netavark.NewNetworkInterface(netavark.InitConfig{
- NetworkConfigDir: confDir,
- IsMachine: machine,
- NetavarkBinary: netavarkBinary,
- IPAMDBPath: filepath.Join(confDir, "ipam.db"),
- LockFile: filepath.Join(confDir, "netavark.lock"),
- })
-}
-
-// EqualSubnet is a custom GomegaMatcher to match a subnet
-// This makes sure to not use the 16 bytes ip representation.
-func EqualSubnet(subnet *net.IPNet) gomegaTypes.GomegaMatcher {
- return &equalSubnetMatcher{
- expected: subnet,
- }
-}
-
-type equalSubnetMatcher struct {
- expected *net.IPNet
-}
-
-func (m *equalSubnetMatcher) Match(actual interface{}) (bool, error) {
- util.NormalizeIP(&m.expected.IP)
-
- subnet, ok := actual.(*net.IPNet)
- if !ok {
- return false, fmt.Errorf("EqualSubnet expects a *net.IPNet")
- }
- util.NormalizeIP(&subnet.IP)
-
- return reflect.DeepEqual(subnet, m.expected), nil
-}
-
-func (m *equalSubnetMatcher) FailureMessage(actual interface{}) string {
- return fmt.Sprintf("Expected subnet %#v to equal subnet %#v", actual, m.expected)
-}
-
-func (m *equalSubnetMatcher) NegatedFailureMessage(actual interface{}) string {
- return fmt.Sprintf("Expected subnet %#v not to equal subnet %#v", actual, m.expected)
-}
diff --git a/libpod/network/netavark/network.go b/libpod/network/netavark/network.go
deleted file mode 100644
index 540d8d6e5..000000000
--- a/libpod/network/netavark/network.go
+++ /dev/null
@@ -1,314 +0,0 @@
-// +build linux
-
-package netavark
-
-import (
- "encoding/json"
- "io/ioutil"
- "os"
- "path/filepath"
- "strings"
- "time"
-
- "github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/libpod/network/internal/util"
- "github.com/containers/podman/v3/libpod/network/types"
- pkgutil "github.com/containers/podman/v3/pkg/util"
- "github.com/containers/storage/pkg/lockfile"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-type netavarkNetwork struct {
- // networkConfigDir is directory where the network config files are stored.
- networkConfigDir string
-
- // netavarkBinary is the path to the netavark binary.
- netavarkBinary string
-
- // defaultNetwork is the name for the default network.
- defaultNetwork string
- // defaultSubnet is the default subnet for the default network.
- defaultSubnet types.IPNet
-
- // ipamDBPath is the path to the ip allocation bolt db
- ipamDBPath string
-
- // 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
-
- // modTime is the timestamp when the config dir was modified
- modTime time.Time
-
- // networks is a map with loaded networks, the key is the network name
- networks map[string]*types.Network
-}
-
-type InitConfig struct {
- // NetworkConfigDir is directory where the network config files are stored.
- NetworkConfigDir string
-
- // NetavarkBinary is the path to the netavark binary.
- NetavarkBinary string
-
- // IPAMDBPath is the path to the ipam database. This should be on a tmpfs.
- // If empty defaults to XDG_RUNTIME_DIR/netavark/ipam.db or /run/netavark/ipam.db as root.
- IPAMDBPath string
-
- // DefaultNetwork is the name for the default network.
- DefaultNetwork string
- // DefaultSubnet is the default subnet for the default network.
- DefaultSubnet string
-
- // IsMachine describes whenever podman runs in a podman machine environment.
- IsMachine bool
-
- // 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.
-// Note: The networks are not loaded from disk until a method is called.
-func NewNetworkInterface(conf InitConfig) (types.ContainerNetwork, error) {
- // TODO: consider using a shared memory lock
- lock, err := lockfile.GetLockfile(conf.LockFile)
- if err != nil {
- return nil, err
- }
-
- defaultNetworkName := conf.DefaultNetwork
- if defaultNetworkName == "" {
- defaultNetworkName = types.DefaultNetworkName
- }
-
- defaultSubnet := conf.DefaultSubnet
- if defaultSubnet == "" {
- defaultSubnet = types.DefaultSubnet
- }
- defaultNet, err := types.ParseCIDR(defaultSubnet)
- if err != nil {
- return nil, errors.Wrap(err, "failed to parse default subnet")
- }
-
- ipamdbPath := conf.IPAMDBPath
- if ipamdbPath == "" {
- runDir, err := pkgutil.GetRuntimeDir()
- if err != nil {
- return nil, err
- }
- // as root runtimeDir is empty so use /run
- if runDir == "" {
- runDir = "/run"
- }
- ipamdbPath = filepath.Join(runDir, "netavark")
- if err := os.MkdirAll(ipamdbPath, 0700); err != nil {
- return nil, errors.Wrap(err, "failed to create ipam db path")
- }
- ipamdbPath = filepath.Join(ipamdbPath, "ipam.db")
- }
-
- if err := os.MkdirAll(conf.NetworkConfigDir, 0755); err != nil {
- return nil, err
- }
-
- n := &netavarkNetwork{
- networkConfigDir: conf.NetworkConfigDir,
- netavarkBinary: conf.NetavarkBinary,
- ipamDBPath: ipamdbPath,
- defaultNetwork: defaultNetworkName,
- defaultSubnet: defaultNet,
- isMachine: conf.IsMachine,
- lock: lock,
- syslog: conf.Syslog,
- }
-
- return n, nil
-}
-
-// Drivers will return the list of supported network drivers
-// for this interface.
-func (n *netavarkNetwork) Drivers() []string {
- return []string{types.BridgeNetworkDriver}
-}
-
-func (n *netavarkNetwork) loadNetworks() error {
- // check the mod time of the config dir
- f, err := os.Stat(n.networkConfigDir)
- if err != nil {
- return err
- }
- modTime := f.ModTime()
-
- // skip loading networks if they are already loaded and
- // if the config dir was not modified since the last call
- if n.networks != nil && modTime.Equal(n.modTime) {
- return nil
- }
- // make sure the remove all networks before we reload them
- n.networks = nil
- n.modTime = modTime
-
- files, err := ioutil.ReadDir(n.networkConfigDir)
- if err != nil && !errors.Is(err, os.ErrNotExist) {
- return err
- }
-
- networks := make(map[string]*types.Network, len(files))
- for _, f := range files {
- if f.IsDir() {
- continue
- }
- if filepath.Ext(f.Name()) != ".json" {
- continue
- }
-
- path := filepath.Join(n.networkConfigDir, f.Name())
- file, err := os.Open(path)
- if err != nil {
- // do not log ENOENT errors
- if !errors.Is(err, os.ErrNotExist) {
- logrus.Warnf("Error loading network config file %q: %v", path, err)
- }
- continue
- }
- network := new(types.Network)
- err = json.NewDecoder(file).Decode(network)
- if err != nil {
- logrus.Warnf("Error reading network config file %q: %v", path, err)
- continue
- }
-
- // check that the filename matches the network name
- if network.Name+".json" != f.Name() {
- logrus.Warnf("Network config name %q does not match file name %q, skipping", network.Name, f.Name())
- continue
- }
-
- if !define.NameRegex.MatchString(network.Name) {
- logrus.Warnf("Network config %q has invalid name: %q, skipping: %v", path, network.Name, define.RegexError)
- continue
- }
-
- err = parseNetwork(network)
- if err != nil {
- logrus.Warnf("Network config %q could not be parsed, skipping: %v", path, err)
- continue
- }
-
- logrus.Debugf("Successfully loaded network %s: %v", network.Name, network)
- networks[network.Name] = network
- }
-
- // create the default network in memory if it did not exists on disk
- if networks[n.defaultNetwork] == nil {
- networkInfo, err := n.createDefaultNetwork()
- if err != nil {
- return errors.Wrapf(err, "failed to create default network %s", n.defaultNetwork)
- }
- networks[n.defaultNetwork] = networkInfo
- }
- logrus.Debugf("Successfully loaded %d networks", len(networks))
- n.networks = networks
- return nil
-}
-
-func parseNetwork(network *types.Network) error {
- if network.Labels == nil {
- network.Labels = map[string]string{}
- }
- if network.Options == nil {
- network.Options = map[string]string{}
- }
- if network.IPAMOptions == nil {
- network.IPAMOptions = map[string]string{}
- }
-
- if len(network.ID) != 64 {
- return errors.Errorf("invalid network ID %q", network.ID)
- }
-
- return util.ValidateSubnets(network, nil)
-}
-
-func (n *netavarkNetwork) createDefaultNetwork() (*types.Network, error) {
- net := types.Network{
- Name: n.defaultNetwork,
- NetworkInterface: defaultBridgeName + "0",
- // Important do not change this ID
- ID: "2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9",
- Driver: types.BridgeNetworkDriver,
- Subnets: []types.Subnet{
- {Subnet: n.defaultSubnet},
- },
- }
- return n.networkCreate(net, true)
-}
-
-// getNetwork will lookup a network by name or ID. It returns an
-// error when no network was found or when more than one network
-// with the given (partial) ID exists.
-// getNetwork will read from the networks map, therefore the caller
-// must ensure that n.lock is locked before using it.
-func (n *netavarkNetwork) getNetwork(nameOrID string) (*types.Network, error) {
- // fast path check the map key, this will only work for names
- if val, ok := n.networks[nameOrID]; ok {
- return val, nil
- }
- // If there was no match we might got a full or partial ID.
- var net *types.Network
- for _, val := range n.networks {
- // This should not happen because we already looked up the map by name but check anyway.
- if val.Name == nameOrID {
- return val, nil
- }
-
- if strings.HasPrefix(val.ID, nameOrID) {
- if net != nil {
- return nil, errors.Errorf("more than one result for network ID %s", nameOrID)
- }
- net = val
- }
- }
- if net != nil {
- return net, nil
- }
- return nil, errors.Wrapf(define.ErrNoSuchNetwork, "unable to find network with name or ID %s", nameOrID)
-}
-
-// Implement the NetUtil interface for easy code sharing with other network interfaces.
-
-// ForEach call the given function for each network
-func (n *netavarkNetwork) ForEach(run func(types.Network)) {
- for _, val := range n.networks {
- run(*val)
- }
-}
-
-// Len return the number of networks
-func (n *netavarkNetwork) Len() int {
- return len(n.networks)
-}
-
-// DefaultInterfaceName return the default cni bridge name, must be suffixed with a number.
-func (n *netavarkNetwork) DefaultInterfaceName() string {
- return defaultBridgeName
-}
-
-func (n *netavarkNetwork) Network(nameOrID string) (*types.Network, error) {
- network, err := n.getNetwork(nameOrID)
- if err != nil {
- return nil, err
- }
- return network, nil
-}
diff --git a/libpod/network/netavark/run.go b/libpod/network/netavark/run.go
deleted file mode 100644
index 0ac20daee..000000000
--- a/libpod/network/netavark/run.go
+++ /dev/null
@@ -1,127 +0,0 @@
-// +build linux
-
-package netavark
-
-import (
- "encoding/json"
- "fmt"
-
- "github.com/containers/podman/v3/libpod/network/internal/util"
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
-)
-
-type netavarkOptions struct {
- types.NetworkOptions
- Networks map[string]*types.Network `json:"network_info"`
-}
-
-// 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, err := n.convertNetOpts(options.NetworkOptions)
- if err != nil {
- return nil, errors.Wrap(err, "failed to convert net opts")
- }
-
- // 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{}
- 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))
- }
-
- 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, err := n.convertNetOpts(options.NetworkOptions)
- if err != nil {
- return errors.Wrap(err, "failed to convert net opts")
- }
-
- 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
- err = n.deallocIPs(&netavarkOpts.NetworkOptions)
- if err != nil {
- if retErr != nil {
- logrus.Error(err)
- } else {
- retErr = err
- }
- }
-
- return retErr
-}
-
-func (n *netavarkNetwork) convertNetOpts(opts types.NetworkOptions) (*netavarkOptions, error) {
- netavarkOptions := netavarkOptions{
- NetworkOptions: opts,
- Networks: make(map[string]*types.Network, len(opts.Networks)),
- }
-
- for network := range opts.Networks {
- net, err := n.getNetwork(network)
- if err != nil {
- return nil, err
- }
- netavarkOptions.Networks[network] = net
- }
- return &netavarkOptions, nil
-}
diff --git a/libpod/network/netavark/run_test.go b/libpod/network/netavark/run_test.go
deleted file mode 100644
index f79e6d812..000000000
--- a/libpod/network/netavark/run_test.go
+++ /dev/null
@@ -1,699 +0,0 @@
-// +build linux
-
-package netavark_test
-
-// The tests have to be run as root.
-// For each test there will be two network namespaces created,
-// netNSTest and netNSContainer. Each test must be run inside
-// netNSTest to prevent leakage in the host netns, therefore
-// it should use the following structure:
-// It("test name", func() {
-// runTest(func() {
-// // add test logic here
-// })
-// })
-
-import (
- "io/ioutil"
- "net"
- "os"
- "strconv"
- "sync"
- "time"
-
- "github.com/containernetworking/plugins/pkg/ns"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- "github.com/sirupsen/logrus"
- "github.com/vishvananda/netlink"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/libpod/network/util"
- "github.com/containers/podman/v3/pkg/netns"
- "github.com/containers/podman/v3/pkg/rootless"
- "github.com/containers/storage/pkg/stringid"
-)
-
-var _ = Describe("run netavark", func() {
- var (
- libpodNet types.ContainerNetwork
- confDir string
- netNSTest ns.NetNS
- netNSContainer ns.NetNS
- )
-
- // runTest is a helper function to run a test. It ensures that each test
- // is run in its own netns. It also creates a mountns to mount a tmpfs to /var/lib/cni.
- runTest := func(run func()) {
- netNSTest.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- // we have to setup the loopback adapter in this netns to use port forwarding
- link, err := netlink.LinkByName("lo")
- Expect(err).To(BeNil(), "Failed to get loopback adapter")
- err = netlink.LinkSetUp(link)
- Expect(err).To(BeNil(), "Failed to set loopback adapter up")
- run()
- return nil
- })
- }
-
- BeforeEach(func() {
- if _, ok := os.LookupEnv("NETAVARK_BINARY"); !ok {
- Skip("NETAVARK_BINARY not set skip run tests")
- }
-
- // set the logrus settings
- logrus.SetLevel(logrus.TraceLevel)
- // disable extra quotes so we can easily copy the netavark command
- logrus.SetFormatter(&logrus.TextFormatter{DisableQuote: true})
- logrus.SetOutput(os.Stderr)
- // The tests need root privileges.
- // Technically we could work around that by using user namespaces and
- // the rootless cni code but this is to much work to get it right for a unit test.
- if rootless.IsRootless() {
- Skip("this test needs to be run as root")
- }
-
- var err error
- confDir, err = ioutil.TempDir("", "podman_netavark_test")
- if err != nil {
- Fail("Failed to create tmpdir")
- }
-
- netNSTest, err = netns.NewNS()
- if err != nil {
- Fail("Failed to create netns")
- }
-
- netNSContainer, err = netns.NewNS()
- 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() {
- var err error
- libpodNet, err = getNetworkInterface(confDir, false)
- if err != nil {
- Fail("Failed to create NewCNINetworkInterface")
- }
- })
-
- AfterEach(func() {
- logrus.SetFormatter(&logrus.TextFormatter{})
- logrus.SetLevel(logrus.InfoLevel)
- os.RemoveAll(confDir)
-
- netns.UnmountNS(netNSTest)
- netNSTest.Close()
-
- netns.UnmountNS(netNSContainer)
- netNSContainer.Close()
-
- _ = os.Unsetenv("NETAVARK_FW")
- })
-
- It("test basic setup", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- opts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: "someID",
- ContainerName: "someName",
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- },
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- ip := res[defNet].Interfaces[intName].Subnets[0].IPNet.IP
- Expect(ip.String()).To(ContainSubstring("10.88.0."))
- gw := res[defNet].Interfaces[intName].Subnets[0].Gateway
- util.NormalizeIP(&gw)
- Expect(gw.String()).To(Equal("10.88.0.1"))
- macAddress := res[defNet].Interfaces[intName].MacAddress
- Expect(macAddress).To(HaveLen(6))
- // default network has no dns
- Expect(res[defNet].DNSServerIPs).To(BeEmpty())
- Expect(res[defNet].DNSSearchDomains).To(BeEmpty())
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(intName)
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal(intName))
- Expect(i.HardwareAddr).To(Equal(net.HardwareAddr(macAddress)))
- addrs, err := i.Addrs()
- Expect(err).To(BeNil())
- subnet := &net.IPNet{
- IP: ip,
- Mask: net.CIDRMask(16, 32),
- }
- Expect(addrs).To(ContainElements(EqualSubnet(subnet)))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).To(BeNil())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).To(BeNil())
-
- // default bridge name
- bridgeName := "podman0"
- // check settings on the host side
- i, err := net.InterfaceByName(bridgeName)
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal(bridgeName))
- addrs, err := i.Addrs()
- Expect(err).ToNot(HaveOccurred())
- // test that the gateway ip is assigned to the interface
- subnet := &net.IPNet{
- IP: gw,
- Mask: net.CIDRMask(16, 32),
- }
- Expect(addrs).To(ContainElements(EqualSubnet(subnet)))
-
- wg := &sync.WaitGroup{}
- expected := stringid.GenerateNonCryptoID()
- // now check ip connectivity
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- wg.Add(1)
- runNetListener(wg, "tcp", "0.0.0.0", 5000, expected)
- return nil
- })
- Expect(err).ToNot(HaveOccurred())
-
- conn, err := net.Dial("tcp", ip.String()+":5000")
- Expect(err).To(BeNil())
- _, err = conn.Write([]byte(expected))
- Expect(err).To(BeNil())
- conn.Close()
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(opts))
- Expect(err).ToNot(HaveOccurred())
- wg.Wait()
- })
- })
-
- It("setup two containers", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts1 := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts1)
- Expect(err).ToNot(HaveOccurred())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- ip1 := res[defNet].Interfaces[intName].Subnets[0].IPNet.IP
- Expect(ip1.String()).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
-
- setupOpts2 := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
-
- netNSContainer2, err := netns.NewNS()
- Expect(err).ToNot(HaveOccurred())
- defer netns.UnmountNS(netNSContainer2)
- defer netNSContainer2.Close()
-
- res, err = libpodNet.Setup(netNSContainer2.Path(), setupOpts2)
- Expect(err).ToNot(HaveOccurred())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- ip2 := res[defNet].Interfaces[intName].Subnets[0].IPNet.IP
- Expect(ip2.String()).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
- Expect(ip1.Equal(ip2)).To(BeFalse(), "IP1 %s should not be equal to IP2 %s", ip1.String(), ip2.String())
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts1))
- Expect(err).ToNot(HaveOccurred())
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts2))
- Expect(err).ToNot(HaveOccurred())
- })
- })
-
- It("setup dualstack network", func() {
- runTest(func() {
- s1, _ := types.ParseCIDR("10.0.0.1/24")
- s2, _ := types.ParseCIDR("fd10:88:a::/64")
- network, err := libpodNet.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {Subnet: s1}, {Subnet: s2},
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName := network.Name
- intName := "eth0"
-
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).ToNot(HaveOccurred())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(netName))
- Expect(res[netName].Interfaces).To(HaveKey(intName))
- Expect(res[netName].Interfaces[intName].Subnets).To(HaveLen(2))
- ip1 := res[netName].Interfaces[intName].Subnets[0].IPNet.IP
- Expect(ip1.String()).To(ContainSubstring("10.0.0."))
- gw1 := res[netName].Interfaces[intName].Subnets[0].Gateway
- Expect(gw1.String()).To(Equal("10.0.0.1"))
- ip2 := res[netName].Interfaces[intName].Subnets[1].IPNet.IP
- Expect(ip2.String()).To(ContainSubstring("fd10:88:a::"))
- gw2 := res[netName].Interfaces[intName].Subnets[0].Gateway
- Expect(gw2.String()).To(Equal("fd10:88:a::1"))
- Expect(res[netName].Interfaces[intName].MacAddress).To(HaveLen(6))
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(intName)
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal(intName))
- addrs, err := i.Addrs()
- Expect(err).ToNot(HaveOccurred())
- subnet1 := s1.IPNet
- subnet1.IP = ip1
- subnet2 := s2.IPNet
- subnet2.IP = ip2
- Expect(addrs).To(ContainElements(EqualSubnet(&subnet1), EqualSubnet(&subnet2)))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).ToNot(HaveOccurred())
-
- bridgeName := network.NetworkInterface
- // check settings on the host side
- i, err := net.InterfaceByName(bridgeName)
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal(bridgeName))
- addrs, err := i.Addrs()
- Expect(err).ToNot(HaveOccurred())
- // test that the gateway ip is assigned to the interface
- subnet1 := s1.IPNet
- subnet1.IP = gw1
- subnet2 := s2.IPNet
- subnet2.IP = gw2
- Expect(addrs).To(ContainElements(EqualSubnet(&subnet1), EqualSubnet(&subnet2)))
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).ToNot(HaveOccurred())
- })
- })
-
- It("setup two networks", func() {
- runTest(func() {
- s1, _ := types.ParseCIDR("10.0.0.1/24")
- network1, err := libpodNet.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {Subnet: s1},
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName1 := network1.Name
- intName1 := "eth0"
-
- s2, _ := types.ParseCIDR("10.1.0.0/24")
- network2, err := libpodNet.NetworkCreate(types.Network{
- Subnets: []types.Subnet{
- {Subnet: s2},
- },
- })
- Expect(err).ToNot(HaveOccurred())
-
- netName2 := network2.Name
- intName2 := "eth1"
-
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- Networks: map[string]types.PerNetworkOptions{
- netName1: {InterfaceName: intName1},
- netName2: {InterfaceName: intName2},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).ToNot(HaveOccurred())
- Expect(res).To(HaveLen(2))
- Expect(res).To(HaveKey(netName1))
- Expect(res).To(HaveKey(netName2))
- Expect(res[netName1].Interfaces).To(HaveKey(intName1))
- Expect(res[netName2].Interfaces).To(HaveKey(intName2))
- Expect(res[netName1].Interfaces[intName1].Subnets).To(HaveLen(1))
- ip1 := res[netName1].Interfaces[intName1].Subnets[0].IPNet.IP
- Expect(ip1.String()).To(ContainSubstring("10.0.0."))
- gw1 := res[netName1].Interfaces[intName1].Subnets[0].Gateway
- Expect(gw1.String()).To(Equal("10.0.0.1"))
- ip2 := res[netName2].Interfaces[intName2].Subnets[0].IPNet.IP
- Expect(ip2.String()).To(ContainSubstring("10.1.0."))
- gw2 := res[netName2].Interfaces[intName2].Subnets[0].Gateway
- Expect(gw2.String()).To(Equal("10.1.0.1"))
- mac1 := res[netName1].Interfaces[intName1].MacAddress
- Expect(mac1).To(HaveLen(6))
- mac2 := res[netName2].Interfaces[intName2].MacAddress
- Expect(mac2).To(HaveLen(6))
-
- // check in the container namespace if the settings are applied
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- i, err := net.InterfaceByName(intName1)
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal(intName1))
- addrs, err := i.Addrs()
- Expect(err).ToNot(HaveOccurred())
- subnet1 := s1.IPNet
- subnet1.IP = ip1
- Expect(addrs).To(ContainElements(EqualSubnet(&subnet1)))
-
- i, err = net.InterfaceByName(intName2)
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal(intName2))
- addrs, err = i.Addrs()
- Expect(err).ToNot(HaveOccurred())
- subnet2 := s2.IPNet
- subnet2.IP = ip2
- Expect(addrs).To(ContainElements(EqualSubnet(&subnet2)))
-
- // check loopback adapter
- i, err = net.InterfaceByName("lo")
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal("lo"))
- Expect(i.Flags & net.FlagLoopback).To(Equal(net.FlagLoopback))
- Expect(i.Flags&net.FlagUp).To(Equal(net.FlagUp), "Loopback adapter should be up")
- return nil
- })
- Expect(err).ToNot(HaveOccurred())
-
- bridgeName1 := network1.NetworkInterface
- // check settings on the host side
- i, err := net.InterfaceByName(bridgeName1)
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal(bridgeName1))
- addrs, err := i.Addrs()
- Expect(err).ToNot(HaveOccurred())
- // test that the gateway ip is assigned to the interface
- subnet1 := s1.IPNet
- subnet1.IP = gw1
- Expect(addrs).To(ContainElements(EqualSubnet(&subnet1)))
-
- bridgeName2 := network2.NetworkInterface
- // check settings on the host side
- i, err = net.InterfaceByName(bridgeName2)
- Expect(err).ToNot(HaveOccurred())
- Expect(i.Name).To(Equal(bridgeName2))
- addrs, err = i.Addrs()
- Expect(err).ToNot(HaveOccurred())
- // test that the gateway ip is assigned to the interface
- subnet2 := s2.IPNet
- subnet2.IP = gw2
- Expect(addrs).To(ContainElements(EqualSubnet(&subnet2)))
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).ToNot(HaveOccurred())
- })
- })
-
- for _, proto := range []string{"tcp", "udp"} {
- // copy proto to extra var to keep correct references in the goroutines
- protocol := proto
- It("run with exposed ports protocol "+protocol, func() {
- runTest(func() {
- testdata := stringid.GenerateNonCryptoID()
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- PortMappings: []types.PortMapping{{
- Protocol: protocol,
- HostIP: "127.0.0.1",
- HostPort: 5000,
- ContainerPort: 5000,
- }},
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- Expect(res[defNet].Interfaces[intName].Subnets[0].IPNet.IP.String()).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
- // default network has no dns
- Expect(res[defNet].DNSServerIPs).To(BeEmpty())
- Expect(res[defNet].DNSSearchDomains).To(BeEmpty())
- var wg sync.WaitGroup
- wg.Add(1)
- // start a listener in the container ns
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- runNetListener(&wg, protocol, "0.0.0.0", 5000, testdata)
- return nil
- })
- Expect(err).To(BeNil())
-
- conn, err := net.Dial(protocol, "127.0.0.1:5000")
- Expect(err).To(BeNil())
- _, err = conn.Write([]byte(testdata))
- Expect(err).To(BeNil())
- conn.Close()
-
- // wait for the listener to finish
- wg.Wait()
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- })
- })
-
- It("run with range ports protocol "+protocol, func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- setupOpts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: stringid.GenerateNonCryptoID(),
- PortMappings: []types.PortMapping{{
- Protocol: protocol,
- HostIP: "127.0.0.1",
- HostPort: 5001,
- ContainerPort: 5000,
- Range: 3,
- }},
- Networks: map[string]types.PerNetworkOptions{
- defNet: {InterfaceName: intName},
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), setupOpts)
- Expect(err).To(BeNil())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- containerIP := res[defNet].Interfaces[intName].Subnets[0].IPNet.IP.String()
- Expect(containerIP).To(ContainSubstring("10.88.0."))
- Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6))
- // default network has no dns
- Expect(res[defNet].DNSServerIPs).To(BeEmpty())
- Expect(res[defNet].DNSSearchDomains).To(BeEmpty())
-
- // loop over all ports
- for p := 5001; p < 5004; p++ {
- port := p
- var wg sync.WaitGroup
- wg.Add(1)
- testdata := stringid.GenerateNonCryptoID()
- // start a listener in the container ns
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- runNetListener(&wg, protocol, containerIP, port-1, testdata)
- return nil
- })
- Expect(err).To(BeNil())
-
- conn, err := net.Dial(protocol, net.JoinHostPort("127.0.0.1", strconv.Itoa(port)))
- Expect(err).To(BeNil())
- _, err = conn.Write([]byte(testdata))
- Expect(err).To(BeNil())
- conn.Close()
-
- // wait for the listener to finish
- wg.Wait()
- }
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(setupOpts))
- Expect(err).To(BeNil())
- })
- })
- }
-
- It("simple teardown", func() {
- runTest(func() {
- defNet := types.DefaultNetworkName
- intName := "eth0"
- opts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: "someID",
- ContainerName: "someName",
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- },
- },
- },
- }
- res, err := libpodNet.Setup(netNSContainer.Path(), opts)
- Expect(err).ToNot(HaveOccurred())
- Expect(res).To(HaveLen(1))
- Expect(res).To(HaveKey(defNet))
- Expect(res[defNet].Interfaces).To(HaveKey(intName))
- Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1))
- ip := res[defNet].Interfaces[intName].Subnets[0].IPNet.IP
- Expect(ip.String()).To(ContainSubstring("10.88.0."))
- gw := res[defNet].Interfaces[intName].Subnets[0].Gateway
- Expect(gw.String()).To(Equal("10.88.0.1"))
- macAddress := res[defNet].Interfaces[intName].MacAddress
- Expect(macAddress).To(HaveLen(6))
-
- err = libpodNet.Teardown(netNSContainer.Path(), types.TeardownOptions(opts))
- Expect(err).ToNot(HaveOccurred())
- err = netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
- // check that the container interface is removed
- _, err := net.InterfaceByName(intName)
- Expect(err).To(HaveOccurred())
- return nil
- })
- Expect(err).ToNot(HaveOccurred())
-
- // default bridge name
- bridgeName := "podman0"
- // check that bridge interface was removed
- _, err = net.InterfaceByName(bridgeName)
- Expect(err).To(HaveOccurred())
- })
- })
-
- It("test netavark error", func() {
- runTest(func() {
- intName := "eth0"
- err := netNSContainer.Do(func(_ ns.NetNS) error {
- defer GinkgoRecover()
-
- attr := netlink.NewLinkAttrs()
- attr.Name = "eth0"
- err := netlink.LinkAdd(&netlink.Bridge{LinkAttrs: attr})
- Expect(err).ToNot(HaveOccurred())
- return nil
- })
- Expect(err).ToNot(HaveOccurred())
- defNet := types.DefaultNetworkName
- opts := types.SetupOptions{
- NetworkOptions: types.NetworkOptions{
- ContainerID: "someID",
- ContainerName: "someName",
- Networks: map[string]types.PerNetworkOptions{
- defNet: {
- InterfaceName: intName,
- },
- },
- },
- }
- _, err = libpodNet.Setup(netNSContainer.Path(), opts)
- Expect(err).To(HaveOccurred())
- Expect(err.Error()).To(ContainSubstring("interface eth0 already exists on container namespace"))
- })
- })
-})
-
-func runNetListener(wg *sync.WaitGroup, protocol, ip string, port int, expectedData string) {
- switch protocol {
- case "tcp":
- ln, err := net.Listen(protocol, net.JoinHostPort(ip, strconv.Itoa(port)))
- Expect(err).To(BeNil())
- // make sure to read in a separate goroutine to not block
- go func() {
- defer GinkgoRecover()
- defer wg.Done()
- defer ln.Close()
- conn, err := ln.Accept()
- Expect(err).To(BeNil())
- defer conn.Close()
- conn.SetDeadline(time.Now().Add(1 * time.Second))
- data, err := ioutil.ReadAll(conn)
- Expect(err).To(BeNil())
- Expect(string(data)).To(Equal(expectedData))
- }()
- case "udp":
- conn, err := net.ListenUDP("udp", &net.UDPAddr{
- IP: net.ParseIP(ip),
- Port: port,
- })
- Expect(err).To(BeNil())
- conn.SetDeadline(time.Now().Add(1 * time.Second))
- go func() {
- defer GinkgoRecover()
- defer wg.Done()
- defer conn.Close()
- data := make([]byte, len(expectedData))
- i, err := conn.Read(data)
- Expect(err).To(BeNil())
- Expect(i).To(Equal(len(expectedData)))
- Expect(string(data)).To(Equal(expectedData))
- }()
- default:
- Fail("unsupported protocol")
- }
-}
diff --git a/libpod/network/netavark/testfiles/invalid/broken.json b/libpod/network/netavark/testfiles/invalid/broken.json
deleted file mode 100644
index 8968ddc73..000000000
--- a/libpod/network/netavark/testfiles/invalid/broken.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "name": "bridge",
- "id": "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121",
- "driver": "bridge",
- "network_interface": "podman9",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1",
- "lease_range": {
- "start_ip": "10.89.8.20",
- "end_ip": "10.89.8.50"
- }
- }
- ],
diff --git a/libpod/network/netavark/testfiles/invalid/invalid name.json b/libpod/network/netavark/testfiles/invalid/invalid name.json
deleted file mode 100644
index 02b441279..000000000
--- a/libpod/network/netavark/testfiles/invalid/invalid name.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "invalid name",
- "id": "6839f44f0fd01c5c5830856b66a1d7ce46842dd8798be0addf96f7255ce9f889",
- "driver": "bridge",
- "network_interface": "podman9",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": true,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/invalid/invalid_gateway.json b/libpod/network/netavark/testfiles/invalid/invalid_gateway.json
deleted file mode 100644
index 6e3a83156..000000000
--- a/libpod/network/netavark/testfiles/invalid/invalid_gateway.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "invalid_gateway",
- "id": "49be6e401e7f8b9844afb969dcbc96e78205ed86ec1e5a46150bd4ab4fdd5686",
- "driver": "bridge",
- "network_interface": "podman9",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.9.0/24",
- "gateway": "10.89.100.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": true,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/invalid/name_missmatch.json b/libpod/network/netavark/testfiles/invalid/name_missmatch.json
deleted file mode 100644
index a3142d8bb..000000000
--- a/libpod/network/netavark/testfiles/invalid/name_missmatch.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "name_miss",
- "id": "3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f",
- "driver": "bridge",
- "network_interface": "podman8",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.7.0/24",
- "gateway": "10.89.7.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": true,
- "dns_enabled": false,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/invalid/wrongID.json b/libpod/network/netavark/testfiles/invalid/wrongID.json
deleted file mode 100644
index 7c1446306..000000000
--- a/libpod/network/netavark/testfiles/invalid/wrongID.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "wrongID",
- "id": "someID",
- "driver": "bridge",
- "network_interface": "podman1",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.0.0/24",
- "gateway": "10.89.0.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": false,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/valid/bridge.json b/libpod/network/netavark/testfiles/valid/bridge.json
deleted file mode 100644
index f4ec82188..000000000
--- a/libpod/network/netavark/testfiles/valid/bridge.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "name": "bridge",
- "id": "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121",
- "driver": "bridge",
- "network_interface": "podman9",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.8.0/24",
- "gateway": "10.89.8.1",
- "lease_range": {
- "start_ip": "10.89.8.20",
- "end_ip": "10.89.8.50"
- }
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": true,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/valid/dualstack.json b/libpod/network/netavark/testfiles/valid/dualstack.json
deleted file mode 100644
index bb4168f3a..000000000
--- a/libpod/network/netavark/testfiles/valid/dualstack.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "name": "dualstack",
- "id": "6839f44f0fd01c5c5830856b66a1d7ce46842dd8798be0addf96f7255ce9f889",
- "driver": "bridge",
- "network_interface": "podman21",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "fd10:88:a::/64",
- "gateway": "fd10:88:a::1"
- },
- {
- "subnet": "10.89.19.0/24",
- "gateway": "10.89.19.10"
- }
- ],
- "ipv6_enabled": true,
- "internal": false,
- "dns_enabled": true,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/valid/internal.json b/libpod/network/netavark/testfiles/valid/internal.json
deleted file mode 100644
index 3ccdd3889..000000000
--- a/libpod/network/netavark/testfiles/valid/internal.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "name": "internal",
- "id": "3bed2cb3a3acf7b6a8ef408420cc682d5520e26976d354254f528c965612054f",
- "driver": "bridge",
- "network_interface": "podman8",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.7.0/24"
- }
- ],
- "ipv6_enabled": false,
- "internal": true,
- "dns_enabled": false,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/valid/label.json b/libpod/network/netavark/testfiles/valid/label.json
deleted file mode 100644
index c4ed637ec..000000000
--- a/libpod/network/netavark/testfiles/valid/label.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "label",
- "id": "1aca80e8b55c802f7b43740da2990e1b5735bbb323d93eb5ebda8395b04025e2",
- "driver": "bridge",
- "network_interface": "podman15",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.13.0/24",
- "gateway": "10.89.13.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": true,
- "labels": {
- "mykey": "value"
- },
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/valid/mtu.json b/libpod/network/netavark/testfiles/valid/mtu.json
deleted file mode 100644
index 53fa4c9bc..000000000
--- a/libpod/network/netavark/testfiles/valid/mtu.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "mtu",
- "id": "49be6e401e7f8b9844afb969dcbc96e78205ed86ec1e5a46150bd4ab4fdd5686",
- "driver": "bridge",
- "network_interface": "podman13",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.11.0/24",
- "gateway": "10.89.11.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": true,
- "options": {
- "mtu": "1500"
- },
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/valid/podman.json b/libpod/network/netavark/testfiles/valid/podman.json
deleted file mode 100644
index 19acddc83..000000000
--- a/libpod/network/netavark/testfiles/valid/podman.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "podman",
- "id": "2f259bab93aaaaa2542ba43ef33eb990d0999ee1b9924b557b7be53c0b7a1bb9",
- "driver": "bridge",
- "network_interface": "podman0",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.88.0.0/16",
- "gateway": "10.88.0.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": false,
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/netavark/testfiles/valid/vlan.json b/libpod/network/netavark/testfiles/valid/vlan.json
deleted file mode 100644
index 30c88ec49..000000000
--- a/libpod/network/netavark/testfiles/valid/vlan.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "vlan",
- "id": "c3b258168c41c0bce97616716bef315eeed33eb1142904bfe7f32eb392c7cf80",
- "driver": "bridge",
- "network_interface": "podman14",
- "created": "2021-10-06T18:50:54.25770461+02:00",
- "subnets": [
- {
- "subnet": "10.89.12.0/24",
- "gateway": "10.89.12.1"
- }
- ],
- "ipv6_enabled": false,
- "internal": false,
- "dns_enabled": true,
- "options": {
- "vlan": "5"
- },
- "ipam_options": {
- "driver": "host-local"
- }
-}
diff --git a/libpod/network/types/const.go b/libpod/network/types/const.go
deleted file mode 100644
index 916c6e6bf..000000000
--- a/libpod/network/types/const.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package types
-
-const (
- // BridgeNetworkDriver defines the bridge driver
- BridgeNetworkDriver = "bridge"
- // DefaultNetworkDriver is the default network type used
- DefaultNetworkDriver = BridgeNetworkDriver
- // MacVLANNetworkDriver defines the macvlan driver
- MacVLANNetworkDriver = "macvlan"
- // MacVLANNetworkDriver defines the macvlan driver
- IPVLANNetworkDriver = "ipvlan"
-
- // IPAM drivers
- // HostLocalIPAMDriver store the ip
- HostLocalIPAMDriver = "host-local"
- // DHCPIPAMDriver get subnet and ip from dhcp server
- DHCPIPAMDriver = "dhcp"
-
- // DefaultSubnet is the name that will be used for the default CNI network.
- DefaultNetworkName = "podman"
- // DefaultSubnet is the subnet that will be used for the default CNI network.
- DefaultSubnet = "10.88.0.0/16"
-)
diff --git a/libpod/network/types/network.go b/libpod/network/types/network.go
deleted file mode 100644
index 37fa11461..000000000
--- a/libpod/network/types/network.go
+++ /dev/null
@@ -1,278 +0,0 @@
-package types
-
-import (
- "encoding/json"
- "net"
- "time"
-)
-
-type ContainerNetwork interface {
- // NetworkCreate will take a partial filled Network and fill the
- // missing fields. It creates the Network and returns the full Network.
- NetworkCreate(Network) (Network, error)
- // NetworkRemove will remove the Network with the given name or ID.
- NetworkRemove(nameOrID string) error
- // NetworkList will return all known Networks. Optionally you can
- // supply a list of filter functions. Only if a network matches all
- // functions it is returned.
- NetworkList(...FilterFunc) ([]Network, error)
- // NetworkInspect will return the Network with the given name or ID.
- NetworkInspect(nameOrID string) (Network, error)
-
- // Setup will setup the container network namespace. It returns
- // a map of StatusBlocks, the key is the network name.
- Setup(namespacePath string, options SetupOptions) (map[string]StatusBlock, error)
- // Teardown will teardown the container network namespace.
- Teardown(namespacePath string, options TeardownOptions) error
-
- // Drivers will return the list of supported network drivers
- // for this interface.
- Drivers() []string
-}
-
-// Network describes the Network attributes.
-type Network struct {
- // Name of the Network.
- Name string `json:"name"`
- // ID of the Network.
- ID string `json:"id"`
- // Driver for this Network, e.g. bridge, macvlan...
- Driver string `json:"driver"`
- // NetworkInterface is the network interface name on the host.
- NetworkInterface string `json:"network_interface,omitempty"`
- // Created contains the timestamp when this network was created.
- Created time.Time `json:"created,omitempty"`
- // Subnets to use for this network.
- Subnets []Subnet `json:"subnets,omitempty"`
- // IPv6Enabled if set to true an ipv6 subnet should be created for this net.
- IPv6Enabled bool `json:"ipv6_enabled"`
- // Internal is whether the Network should not have external routes
- // to public or other Networks.
- Internal bool `json:"internal"`
- // DNSEnabled is whether name resolution is active for container on
- // this Network.
- DNSEnabled bool `json:"dns_enabled"`
- // Labels is a set of key-value labels that have been applied to the
- // Network.
- Labels map[string]string `json:"labels,omitempty"`
- // Options is a set of key-value options that have been applied to
- // the Network.
- Options map[string]string `json:"options,omitempty"`
- // IPAMOptions contains options used for the ip assignment.
- IPAMOptions map[string]string `json:"ipam_options,omitempty"`
-}
-
-// IPNet is used as custom net.IPNet type to add Marshal/Unmarshal methods.
-type IPNet struct {
- net.IPNet
-}
-
-// ParseCIDR parse a string to IPNet
-func ParseCIDR(cidr string) (IPNet, error) {
- ip, net, err := net.ParseCIDR(cidr)
- if err != nil {
- return IPNet{}, err
- }
- // convert to 4 bytes if ipv4
- ipv4 := ip.To4()
- if ipv4 != nil {
- ip = ipv4
- }
- net.IP = ip
- return IPNet{*net}, err
-}
-
-func (n *IPNet) MarshalText() ([]byte, error) {
- return []byte(n.String()), nil
-}
-
-func (n *IPNet) UnmarshalText(text []byte) error {
- net, err := ParseCIDR(string(text))
- if err != nil {
- return err
- }
- *n = net
- return nil
-}
-
-// HardwareAddr is the same as net.HardwareAddr except
-// that it adds the json marshal/unmarshal methods.
-// This allows us to read the mac from a json string
-// and a byte array.
-// swagger:model MacAddress
-type HardwareAddr net.HardwareAddr
-
-func (h *HardwareAddr) String() string {
- return (*net.HardwareAddr)(h).String()
-}
-
-func (h *HardwareAddr) MarshalText() ([]byte, error) {
- return []byte((*net.HardwareAddr)(h).String()), nil
-}
-
-func (h *HardwareAddr) UnmarshalJSON(text []byte) error {
- if len(text) == 0 {
- *h = nil
- return nil
- }
-
- // if the json string start with a quote we got a string
- // unmarshal the string and parse the mac from this string
- if string(text[0]) == `"` {
- var macString string
- err := json.Unmarshal(text, &macString)
- if err == nil {
- mac, err := net.ParseMAC(macString)
- if err == nil {
- *h = HardwareAddr(mac)
- return nil
- }
- }
- }
- // not a string or got an error fallback to the normal parsing
- mac := make(net.HardwareAddr, 0, 6)
- // use the standard json unmarshal for backwards compat
- err := json.Unmarshal(text, &mac)
- if err != nil {
- return err
- }
- *h = HardwareAddr(mac)
- return nil
-}
-
-type Subnet struct {
- // Subnet for this Network in CIDR form.
- // swagger:strfmt string
- Subnet IPNet `json:"subnet"`
- // Gateway IP for this Network.
- // swagger:strfmt string
- Gateway net.IP `json:"gateway,omitempty"`
- // LeaseRange contains the range where IP are leased. Optional.
- LeaseRange *LeaseRange `json:"lease_range,omitempty"`
-}
-
-// LeaseRange contains the range where IP are leased.
-type LeaseRange struct {
- // StartIP first IP in the subnet which should be used to assign ips.
- // swagger:strfmt string
- StartIP net.IP `json:"start_ip,omitempty"`
- // EndIP last IP in the subnet which should be used to assign ips.
- // swagger:strfmt string
- EndIP net.IP `json:"end_ip,omitempty"`
-}
-
-// StatusBlock contains the network information about a container
-// connected to one Network.
-type StatusBlock struct {
- // Interfaces contains the created network interface in the container.
- // The map key is the interface name.
- Interfaces map[string]NetInterface `json:"interfaces,omitempty"`
- // DNSServerIPs nameserver addresses which should be added to
- // the containers resolv.conf file.
- DNSServerIPs []net.IP `json:"dns_server_ips,omitempty"`
- // DNSSearchDomains search domains which should be added to
- // the containers resolv.conf file.
- DNSSearchDomains []string `json:"dns_search_domains,omitempty"`
-}
-
-// NetInterface contains the settings for a given network interface.
-type NetInterface struct {
- // Subnets list of assigned subnets with their gateway.
- Subnets []NetAddress `json:"subnets,omitempty"`
- // MacAddress for this Interface.
- MacAddress HardwareAddr `json:"mac_address"`
-}
-
-// NetAddress contains the ip address, subnet and gateway.
-type NetAddress struct {
- // IPNet of this NetAddress. Note that this is a subnet but it has to contain the
- // actual ip of the network interface and not the network address.
- IPNet IPNet `json:"ipnet"`
- // Gateway for the network. This can be empty if there is no gateway, e.g. internal network.
- Gateway net.IP `json:"gateway,omitempty"`
-}
-
-// PerNetworkOptions are options which should be set on a per network basis.
-type PerNetworkOptions struct {
- // StaticIPs for this container. Optional.
- StaticIPs []net.IP `json:"static_ips,omitempty"`
- // Aliases contains a list of names which the dns server should resolve
- // to this container. Should only be set when DNSEnabled is true on the Network.
- // If aliases are set but there is no dns support for this network the
- // network interface implementation should ignore this and NOT error.
- // Optional.
- Aliases []string `json:"aliases,omitempty"`
- // StaticMac for this container. Optional.
- StaticMAC HardwareAddr `json:"static_mac,omitempty"`
- // InterfaceName for this container. Required in the backend.
- // Optional in the frontend. Will be filled with ethX (where X is a integer) when empty.
- InterfaceName string `json:"interface_name"`
-}
-
-// NetworkOptions for a given container.
-type NetworkOptions struct {
- // ContainerID is the container id, used for iptables comments and ipam allocation.
- ContainerID string `json:"container_id"`
- // ContainerName is the container name, used as dns name.
- ContainerName string `json:"container_name"`
- // PortMappings contains the port mappings for this container
- PortMappings []PortMapping `json:"port_mappings,omitempty"`
- // Networks contains all networks with the PerNetworkOptions.
- // The map should contain at least one element.
- Networks map[string]PerNetworkOptions `json:"networks"`
-}
-
-// PortMapping is one or more ports that will be mapped into the container.
-type PortMapping struct {
- // HostIP is the IP that we will bind to on the host.
- // If unset, assumed to be 0.0.0.0 (all interfaces).
- HostIP string `json:"host_ip"`
- // ContainerPort is the port number that will be exposed from the
- // container.
- // Mandatory.
- ContainerPort uint16 `json:"container_port"`
- // HostPort is the port number that will be forwarded from the host into
- // the container.
- // If omitted, a random port on the host (guaranteed to be over 1024)
- // will be assigned.
- HostPort uint16 `json:"host_port"`
- // Range is the number of ports that will be forwarded, starting at
- // HostPort and ContainerPort and counting up.
- // This is 1-indexed, so 1 is assumed to be a single port (only the
- // Hostport:Containerport mapping will be added), 2 is two ports (both
- // Hostport:Containerport and Hostport+1:Containerport+1), etc.
- // If unset, assumed to be 1 (a single port).
- // Both hostport + range and containerport + range must be less than
- // 65536.
- Range uint16 `json:"range"`
- // Protocol is the protocol forward.
- // Must be either "tcp", "udp", and "sctp", or some combination of these
- // separated by commas.
- // If unset, assumed to be TCP.
- Protocol string `json:"protocol"`
-}
-
-// OCICNIPortMapping maps to the standard CNI portmapping Capability.
-// Deprecated, do not use this struct for new fields. This only exists
-// for backwards compatibility.
-type OCICNIPortMapping struct {
- // HostPort is the port number on the host.
- HostPort int32 `json:"hostPort"`
- // ContainerPort is the port number inside the sandbox.
- ContainerPort int32 `json:"containerPort"`
- // Protocol is the protocol of the port mapping.
- Protocol string `json:"protocol"`
- // HostIP is the host ip to use.
- HostIP string `json:"hostIP"`
-}
-
-type SetupOptions struct {
- NetworkOptions
-}
-
-type TeardownOptions struct {
- NetworkOptions
-}
-
-// FilterFunc can be passed to NetworkList to filter the networks.
-type FilterFunc func(Network) bool
diff --git a/libpod/network/types/network_test.go b/libpod/network/types/network_test.go
deleted file mode 100644
index 91ee93692..000000000
--- a/libpod/network/types/network_test.go
+++ /dev/null
@@ -1,82 +0,0 @@
-package types_test
-
-import (
- "encoding/json"
- "reflect"
- "testing"
-
- "github.com/containers/podman/v3/libpod/network/types"
-)
-
-func TestUnmarshalMacAddress(t *testing.T) {
- tests := []struct {
- name string
- json string
- want types.HardwareAddr
- wantErr bool
- }{
- {
- name: "mac as string with colon",
- json: `"52:54:00:1c:2e:46"`,
- want: types.HardwareAddr{0x52, 0x54, 0x00, 0x1c, 0x2e, 0x46},
- },
- {
- name: "mac as string with dash",
- json: `"52-54-00-1c-2e-46"`,
- want: types.HardwareAddr{0x52, 0x54, 0x00, 0x1c, 0x2e, 0x46},
- },
- {
- name: "mac as byte array",
- json: `[82, 84, 0, 28, 46, 70]`,
- want: types.HardwareAddr{0x52, 0x54, 0x00, 0x1c, 0x2e, 0x46},
- },
- {
- name: "null value",
- json: `null`,
- want: nil,
- },
- {
- name: "mac as base64",
- json: `"qrvM3e7/"`,
- want: types.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
- },
- {
- name: "invalid string",
- json: `"52:54:00:1c:2e`,
- wantErr: true,
- },
- {
- name: "invalid array",
- json: `[82, 84, 0, 28, 46`,
- wantErr: true,
- },
-
- {
- name: "invalid value",
- json: `ab`,
- wantErr: true,
- },
- {
- name: "invalid object",
- json: `{}`,
- wantErr: true,
- },
- }
- for _, tt := range tests {
- test := tt
- t.Run(test.name, func(t *testing.T) {
- mac := types.HardwareAddr{}
- err := json.Unmarshal([]byte(test.json), &mac)
- if (err != nil) != test.wantErr {
- t.Errorf("types.HardwareAddress Unmarshal() error = %v, wantErr %v", err, test.wantErr)
- return
- }
- if test.wantErr {
- return
- }
- if !reflect.DeepEqual(mac, test.want) {
- t.Errorf("types.HardwareAddress Unmarshal() got = %v, want %v", mac, test.want)
- }
- })
- }
-}
diff --git a/libpod/network/util/filters.go b/libpod/network/util/filters.go
deleted file mode 100644
index c3c80b352..000000000
--- a/libpod/network/util/filters.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package util
-
-import (
- "strings"
-
- "github.com/containers/podman/v3/libpod/network/types"
- "github.com/containers/podman/v3/pkg/util"
- "github.com/pkg/errors"
-)
-
-func GenerateNetworkFilters(filters map[string][]string) ([]types.FilterFunc, error) {
- filterFuncs := make([]types.FilterFunc, 0, len(filters))
- for key, filterValues := range filters {
- filterFunc, err := createFilterFuncs(key, filterValues)
- if err != nil {
- return nil, err
- }
- filterFuncs = append(filterFuncs, filterFunc)
- }
- return filterFuncs, nil
-}
-
-func createFilterFuncs(key string, filterValues []string) (types.FilterFunc, error) {
- switch strings.ToLower(key) {
- case "name":
- // matches one name, regex allowed
- return func(net types.Network) bool {
- return util.StringMatchRegexSlice(net.Name, filterValues)
- }, nil
-
- case "driver":
- // matches network driver
- return func(net types.Network) bool {
- return util.StringInSlice(net.Driver, filterValues)
- }, nil
-
- case "id":
- // matches part of one id
- return func(net types.Network) bool {
- return util.StringMatchRegexSlice(net.ID, filterValues)
- }, nil
-
- // TODO: add dns enabled, internal filter
- }
- return createPruneFilterFuncs(key, filterValues)
-}
-
-func GenerateNetworkPruneFilters(filters map[string][]string) ([]types.FilterFunc, error) {
- filterFuncs := make([]types.FilterFunc, 0, len(filters))
- for key, filterValues := range filters {
- filterFunc, err := createPruneFilterFuncs(key, filterValues)
- if err != nil {
- return nil, err
- }
- filterFuncs = append(filterFuncs, filterFunc)
- }
- return filterFuncs, nil
-}
-
-func createPruneFilterFuncs(key string, filterValues []string) (types.FilterFunc, error) {
- switch strings.ToLower(key) {
- case "label":
- // matches all labels
- return func(net types.Network) bool {
- return util.MatchLabelFilters(filterValues, net.Labels)
- }, nil
-
- case "until":
- until, err := util.ComputeUntilTimestamp(filterValues)
- if err != nil {
- return nil, err
- }
- return func(net types.Network) bool {
- return net.Created.Before(until)
- }, nil
- default:
- return nil, errors.Errorf("invalid filter %q", key)
- }
-}
diff --git a/libpod/network/util/ip.go b/libpod/network/util/ip.go
deleted file mode 100644
index e82b4a781..000000000
--- a/libpod/network/util/ip.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package util
-
-import (
- "net"
-)
-
-// IsIPv6 returns true if netIP is IPv6.
-func IsIPv6(netIP net.IP) bool {
- return netIP != nil && netIP.To4() == nil
-}
-
-// IsIPv4 returns true if netIP is IPv4.
-func IsIPv4(netIP net.IP) bool {
- return netIP != nil && netIP.To4() != nil
-}
-
-// LastIPInSubnet gets the last IP in a subnet
-func LastIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
- // re-parse to ensure clean network address
- _, cidr, err := net.ParseCIDR(addr.String())
- if err != nil {
- return nil, err
- }
-
- ones, bits := cidr.Mask.Size()
- if ones == bits {
- return cidr.IP, nil
- }
- for i := range cidr.IP {
- cidr.IP[i] = cidr.IP[i] | ^cidr.Mask[i]
- }
- return cidr.IP, nil
-}
-
-// FirstIPInSubnet gets the first IP in a subnet
-func FirstIPInSubnet(addr *net.IPNet) (net.IP, error) { //nolint:interfacer
- // re-parse to ensure clean network address
- _, cidr, err := net.ParseCIDR(addr.String())
- if err != nil {
- return nil, err
- }
- ones, bits := cidr.Mask.Size()
- if ones == bits {
- return cidr.IP, nil
- }
- cidr.IP[len(cidr.IP)-1]++
- return cidr.IP, nil
-}
-
-// NormalizeIP will transform the given ip to the 4 byte len ipv4 if possible
-func NormalizeIP(ip *net.IP) {
- ipv4 := ip.To4()
- if ipv4 != nil {
- *ip = ipv4
- }
-}
diff --git a/libpod/network/util/ip_calc.go b/libpod/network/util/ip_calc.go
deleted file mode 100644
index a27ddf78b..000000000
--- a/libpod/network/util/ip_calc.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 CNI authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package util
-
-import (
- "math/big"
- "net"
-)
-
-// NextIP returns IP incremented by 1
-func NextIP(ip net.IP) net.IP {
- i := ipToInt(ip)
- return intToIP(i.Add(i, big.NewInt(1)))
-}
-
-// PrevIP returns IP decremented by 1
-func PrevIP(ip net.IP) net.IP {
- i := ipToInt(ip)
- return intToIP(i.Sub(i, big.NewInt(1)))
-}
-
-// Cmp compares two IPs, returning the usual ordering:
-// a < b : -1
-// a == b : 0
-// a > b : 1
-func Cmp(a, b net.IP) int {
- aa := ipToInt(a)
- bb := ipToInt(b)
- return aa.Cmp(bb)
-}
-
-func ipToInt(ip net.IP) *big.Int {
- if v := ip.To4(); v != nil {
- return big.NewInt(0).SetBytes(v)
- }
- return big.NewInt(0).SetBytes(ip.To16())
-}
-
-func intToIP(i *big.Int) net.IP {
- return net.IP(i.Bytes())
-}
diff --git a/libpod/network/util/ip_test.go b/libpod/network/util/ip_test.go
deleted file mode 100644
index 63ac555f0..000000000
--- a/libpod/network/util/ip_test.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package util
-
-import (
- "net"
- "testing"
-)
-
-func parseCIDR(n string) *net.IPNet {
- _, parsedNet, _ := net.ParseCIDR(n)
- return parsedNet
-}
-
-func TestFirstIPInSubnet(t *testing.T) {
- tests := []struct {
- name string
- args *net.IPNet
- want net.IP
- wantErr bool
- }{
- {"class b", parseCIDR("192.168.0.0/16"), net.ParseIP("192.168.0.1"), false},
- {"class c", parseCIDR("192.168.1.0/24"), net.ParseIP("192.168.1.1"), false},
- {"cidr /23", parseCIDR("192.168.0.0/23"), net.ParseIP("192.168.0.1"), false},
- {"cidr /25", parseCIDR("192.168.1.0/25"), net.ParseIP("192.168.1.1"), false},
- {"cidr /26", parseCIDR("172.16.1.128/26"), net.ParseIP("172.16.1.129"), false},
- {"class a", parseCIDR("10.0.0.0/8"), net.ParseIP("10.0.0.1"), false},
- {"cidr /32", parseCIDR("192.168.255.4/32"), net.ParseIP("192.168.255.4"), false},
- {"cidr /31", parseCIDR("192.168.255.4/31"), net.ParseIP("192.168.255.5"), false},
- }
- for _, tt := range tests {
- test := tt
- t.Run(test.name, func(t *testing.T) {
- got, err := FirstIPInSubnet(test.args)
- if (err != nil) != test.wantErr {
- t.Errorf("FirstIPInSubnet() error = %v, wantErr %v", err, test.wantErr)
- return
- }
- if !got.Equal(test.want) {
- t.Errorf("FirstIPInSubnet() got = %v, want %v", got, test.want)
- }
- })
- }
-}
-
-func TestLastIPInSubnet(t *testing.T) {
- tests := []struct {
- name string
- args *net.IPNet
- want net.IP
- wantErr bool
- }{
- {"class b", parseCIDR("192.168.0.0/16"), net.ParseIP("192.168.255.255"), false},
- {"class c", parseCIDR("192.168.1.0/24"), net.ParseIP("192.168.1.255"), false},
- {"cidr /23", parseCIDR("192.168.0.0/23"), net.ParseIP("192.168.1.255"), false},
- {"cidr /25", parseCIDR("192.168.1.0/25"), net.ParseIP("192.168.1.127"), false},
- {"cidr /26", parseCIDR("172.16.1.128/26"), net.ParseIP("172.16.1.191"), false},
- {"class a", parseCIDR("10.0.0.0/8"), net.ParseIP("10.255.255.255"), false},
- {"cidr /32", parseCIDR("192.168.255.4/32"), net.ParseIP("192.168.255.4"), false},
- {"cidr /31", parseCIDR("192.168.255.4/31"), net.ParseIP("192.168.255.5"), false},
- }
- for _, tt := range tests {
- test := tt
- t.Run(test.name, func(t *testing.T) {
- got, err := LastIPInSubnet(test.args)
- if (err != nil) != test.wantErr {
- t.Errorf("LastIPInSubnet() error = %v, wantErr %v", err, test.wantErr)
- return
- }
- if !got.Equal(test.want) {
- t.Errorf("LastIPInSubnet() got = %v, want %v", got, test.want)
- }
- })
- }
-}