summaryrefslogtreecommitdiff
path: root/libpod/network/netavark
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/network/netavark')
-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
22 files changed, 0 insertions, 3754 deletions
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"
- }
-}