diff options
Diffstat (limited to 'libpod/network/netavark')
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" - } -} |