diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_inspect.go | 3 | ||||
-rw-r--r-- | libpod/container_internal.go | 4 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 22 | ||||
-rw-r--r-- | libpod/network/cni/cni_conversion.go | 15 | ||||
-rw-r--r-- | libpod/network/cni/cni_types.go | 15 | ||||
-rw-r--r-- | libpod/network/cni/config_test.go | 13 | ||||
-rw-r--r-- | libpod/network/cni/network.go | 7 | ||||
-rw-r--r-- | libpod/network/cni/run.go | 8 | ||||
-rw-r--r-- | libpod/network/cni/run_test.go | 66 | ||||
-rw-r--r-- | libpod/network/netavark/run_test.go | 48 | ||||
-rw-r--r-- | libpod/network/types/network.go | 20 | ||||
-rw-r--r-- | libpod/networking_linux.go | 80 | ||||
-rw-r--r-- | libpod/networking_machine.go | 121 | ||||
-rw-r--r-- | libpod/networking_slirp4netns.go | 10 |
14 files changed, 267 insertions, 165 deletions
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 277c3b960..0dae810de 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -300,8 +300,7 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) *define.Insp ctrConfig.User = c.config.User if spec.Process != nil { ctrConfig.Tty = spec.Process.Terminal - ctrConfig.Env = []string{} - ctrConfig.Env = append(ctrConfig.Env, spec.Process.Env...) + ctrConfig.Env = append([]string{}, spec.Process.Env...) ctrConfig.WorkingDir = spec.Process.Cwd } diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 4bf15be86..871c6787a 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -1050,8 +1050,8 @@ func (c *Container) cniHosts() string { var hosts string for _, status := range c.getNetworkStatus() { for _, netInt := range status.Interfaces { - for _, netAddress := range netInt.Networks { - hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.Subnet.IP.String(), c.Hostname(), c.config.Name) + for _, netAddress := range netInt.Subnets { + hosts += fmt.Sprintf("%s\t%s %s\n", netAddress.IPNet.IP.String(), c.Hostname(), c.config.Name) } } } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 1a4508448..364b77f29 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -709,18 +709,6 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { g.AddAnnotation(annotations.ContainerManager, annotations.ContainerManagerLibpod) } - // Only add container environment variable if not already present - foundContainerEnv := false - for _, env := range g.Config.Process.Env { - if strings.HasPrefix(env, "container=") { - foundContainerEnv = true - break - } - } - if !foundContainerEnv { - g.AddProcessEnv("container", "libpod") - } - cgroupPath, err := c.getOCICgroupPath() if err != nil { return nil, err @@ -1353,8 +1341,8 @@ func (c *Container) restore(ctx context.Context, options ContainerCheckpointOpti perNetOpts.StaticMAC = netInt.MacAddress } if !options.IgnoreStaticIP { - for _, netAddress := range netInt.Networks { - perNetOpts.StaticIPs = append(perNetOpts.StaticIPs, netAddress.Subnet.IP) + for _, netAddress := range netInt.Subnets { + perNetOpts.StaticIPs = append(perNetOpts.StaticIPs, netAddress.IPNet.IP) } } // Normally interfaces have a length of 1, only for some special cni configs we could get more. @@ -1955,9 +1943,9 @@ func (c *Container) generateResolvConf() (string, error) { netStatus := c.getNetworkStatus() for _, status := range netStatus { for _, netInt := range status.Interfaces { - for _, netAddress := range netInt.Networks { + for _, netAddress := range netInt.Subnets { // Note: only using To16() does not work since it also returns a valid ip for ipv4 - if netAddress.Subnet.IP.To4() == nil && netAddress.Subnet.IP.To16() != nil { + if netAddress.IPNet.IP.To4() == nil && netAddress.IPNet.IP.To16() != nil { ipv6 = true } } @@ -2163,7 +2151,7 @@ func (c *Container) getHosts() string { if depCtr != nil { for _, status := range depCtr.getNetworkStatus() { for _, netInt := range status.Interfaces { - for _, netAddress := range netInt.Networks { + for _, netAddress := range netInt.Subnets { if netAddress.Gateway != nil { hosts += fmt.Sprintf("%s host.containers.internal\n", netAddress.Gateway.String()) } diff --git a/libpod/network/cni/cni_conversion.go b/libpod/network/cni/cni_conversion.go index 70d259b60..788165b5e 100644 --- a/libpod/network/cni/cni_conversion.go +++ b/libpod/network/cni/cni_conversion.go @@ -295,10 +295,6 @@ func (n *cniNetwork) createCNIConfigListFromNetwork(network *types.Network, writ // Note: in the future we might like to allow for dynamic domain names plugins = append(plugins, newDNSNamePlugin(defaultPodmanDomainName)) } - // Add the podman-machine CNI plugin if we are in a machine - if n.isMachine { - plugins = append(plugins, newPodmanMachinePlugin()) - } case types.MacVLANNetworkDriver: plugins = append(plugins, newVLANPlugin(types.MacVLANNetworkDriver, network.NetworkInterface, vlanPluginMode, mtu, ipamConf)) @@ -369,3 +365,14 @@ func convertSpecgenPortsToCNIPorts(ports []types.PortMapping) ([]cniPortMapEntry } return cniPorts, nil } + +func removeMachinePlugin(conf *libcni.NetworkConfigList) *libcni.NetworkConfigList { + plugins := make([]*libcni.NetworkConfig, 0, len(conf.Plugins)) + for _, net := range conf.Plugins { + if net.Network.Type != "podman-machine" { + plugins = append(plugins, net) + } + } + conf.Plugins = plugins + return conf +} diff --git a/libpod/network/cni/cni_types.go b/libpod/network/cni/cni_types.go index c70cb92b6..e5eb777de 100644 --- a/libpod/network/cni/cni_types.go +++ b/libpod/network/cni/cni_types.go @@ -110,12 +110,6 @@ type dnsNameConfig struct { Capabilities map[string]bool `json:"capabilities"` } -// podmanMachineConfig enables port handling on the host OS -type podmanMachineConfig struct { - PluginType string `json:"type"` - Capabilities map[string]bool `json:"capabilities"` -} - // ncList describes a generic map type ncList map[string]interface{} @@ -285,12 +279,3 @@ func newVLANPlugin(pluginType, device, mode string, mtu int, ipam ipamConfig) VL } return m } - -func newPodmanMachinePlugin() podmanMachineConfig { - caps := make(map[string]bool, 1) - caps["portMappings"] = true - return podmanMachineConfig{ - PluginType: "podman-machine", - Capabilities: caps, - } -} diff --git a/libpod/network/cni/config_test.go b/libpod/network/cni/config_test.go index 0dfc6173c..c2e5fc985 100644 --- a/libpod/network/cni/config_test.go +++ b/libpod/network/cni/config_test.go @@ -965,19 +965,6 @@ var _ = Describe("Config", func() { Expect(logString).To(ContainSubstring("dnsname and internal networks are incompatible")) }) - It("create config with podman machine plugin", func() { - libpodNet, err := getNetworkInterface(cniConfDir, true) - Expect(err).To(BeNil()) - - network := types.Network{} - network1, err := libpodNet.NetworkCreate(network) - Expect(err).To(BeNil()) - Expect(network1.Driver).To(Equal("bridge")) - path := filepath.Join(cniConfDir, network1.Name+".conflist") - Expect(path).To(BeARegularFile()) - grepInFile(path, `"type": "podman-machine",`) - }) - It("network inspect partial ID", func() { network := types.Network{Name: "net4"} network1, err := libpodNet.NetworkCreate(network) diff --git a/libpod/network/cni/network.go b/libpod/network/cni/network.go index 3e9cdaa47..41e3e414e 100644 --- a/libpod/network/cni/network.go +++ b/libpod/network/cni/network.go @@ -150,6 +150,13 @@ func (n *cniNetwork) loadNetworks() error { continue } + // podman < v4.0 used the podman-machine cni plugin for podman machine port forwarding + // since this is now build into podman we no longer use the plugin + // old configs may still contain it so we just remove it here + if n.isMachine { + conf = removeMachinePlugin(conf) + } + if _, err := n.cniConf.ValidateNetworkList(context.Background(), conf); err != nil { logrus.Warnf("Error validating CNI config file %s: %v", file, err) continue diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go index 667ed3ab1..d0ff49b73 100644 --- a/libpod/network/cni/run.go +++ b/libpod/network/cni/run.go @@ -135,8 +135,8 @@ func CNIResultToStatus(res cnitypes.Result) (types.StatusBlock, error) { cniInt := cniResult.Interfaces[*ip.Interface] netInt, ok := interfaces[cniInt.Name] if ok { - netInt.Networks = append(netInt.Networks, types.NetAddress{ - Subnet: types.IPNet{IPNet: ip.Address}, + netInt.Subnets = append(netInt.Subnets, types.NetAddress{ + IPNet: types.IPNet{IPNet: ip.Address}, Gateway: ip.Gateway, }) interfaces[cniInt.Name] = netInt @@ -147,8 +147,8 @@ func CNIResultToStatus(res cnitypes.Result) (types.StatusBlock, error) { } interfaces[cniInt.Name] = types.NetInterface{ MacAddress: types.HardwareAddr(mac), - Networks: []types.NetAddress{{ - Subnet: types.IPNet{IPNet: ip.Address}, + Subnets: []types.NetAddress{{ + IPNet: types.IPNet{IPNet: ip.Address}, Gateway: ip.Gateway, }}, } diff --git a/libpod/network/cni/run_test.go b/libpod/network/cni/run_test.go index 6c54f82ef..f6cc2d412 100644 --- a/libpod/network/cni/run_test.go +++ b/libpod/network/cni/run_test.go @@ -133,8 +133,8 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String()).To(ContainSubstring("10.88.0.")) + 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()) @@ -170,8 +170,8 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP).To(Equal(ip)) + Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1)) + Expect(res[defNet].Interfaces[intName].Subnets[0].IPNet.IP).To(Equal(ip)) Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6)) // default network has no dns Expect(res[defNet].DNSServerIPs).To(BeEmpty()) @@ -209,8 +209,8 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String()).To(ContainSubstring("10.88.0.")) + 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()) @@ -263,8 +263,8 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - containerIP := res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String() + 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 @@ -324,8 +324,8 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String()).To(ContainSubstring("10.88.0.")) + Expect(res[defNet].Interfaces[intName].Subnets).To(HaveLen(1)) + Expect(res[defNet].Interfaces[intName].Subnets[0].IPNet.IP.String()).To(ContainSubstring("10.88.0.")) Expect(res[defNet].Interfaces[intName].MacAddress).To(HaveLen(6)) for _, proto := range []string{"tcp", "udp"} { @@ -386,8 +386,8 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveKey(netName1)) Expect(res[netName1].Interfaces).To(HaveKey(intName1)) - Expect(res[netName1].Interfaces[intName1].Networks).To(HaveLen(1)) - ipInt1 := res[netName1].Interfaces[intName1].Networks[0].Subnet.IP + Expect(res[netName1].Interfaces[intName1].Subnets).To(HaveLen(1)) + ipInt1 := res[netName1].Interfaces[intName1].Subnets[0].IPNet.IP Expect(ipInt1).ToNot(BeEmpty()) macInt1 := res[netName1].Interfaces[intName1].MacAddress Expect(macInt1).To(HaveLen(6)) @@ -436,8 +436,8 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveKey(netName2)) Expect(res[netName2].Interfaces).To(HaveKey(intName2)) - Expect(res[netName2].Interfaces[intName2].Networks).To(HaveLen(1)) - ipInt2 := res[netName2].Interfaces[intName2].Networks[0].Subnet.IP + Expect(res[netName2].Interfaces[intName2].Subnets).To(HaveLen(1)) + ipInt2 := res[netName2].Interfaces[intName2].Subnets[0].IPNet.IP Expect(ipInt2).ToNot(BeEmpty()) macInt2 := res[netName2].Interfaces[intName2].MacAddress Expect(macInt2).To(HaveLen(6)) @@ -576,16 +576,16 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveKey(netName1)) Expect(res[netName1].Interfaces).To(HaveKey(intName1)) - Expect(res[netName1].Interfaces[intName1].Networks).To(HaveLen(1)) - ipInt1 := res[netName1].Interfaces[intName1].Networks[0].Subnet.IP + Expect(res[netName1].Interfaces[intName1].Subnets).To(HaveLen(1)) + ipInt1 := res[netName1].Interfaces[intName1].Subnets[0].IPNet.IP Expect(ipInt1.String()).To(ContainSubstring("192.168.0.")) macInt1 := res[netName1].Interfaces[intName1].MacAddress Expect(macInt1).To(HaveLen(6)) Expect(res).To(HaveKey(netName2)) Expect(res[netName2].Interfaces).To(HaveKey(intName2)) - Expect(res[netName2].Interfaces[intName2].Networks).To(HaveLen(1)) - ipInt2 := res[netName2].Interfaces[intName2].Networks[0].Subnet.IP + Expect(res[netName2].Interfaces[intName2].Subnets).To(HaveLen(1)) + ipInt2 := res[netName2].Interfaces[intName2].Subnets[0].IPNet.IP Expect(ipInt2.String()).To(ContainSubstring("192.168.1.")) macInt2 := res[netName2].Interfaces[intName2].MacAddress Expect(macInt2).To(HaveLen(6)) @@ -701,13 +701,13 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(netName)) Expect(res[netName].Interfaces).To(HaveKey(interfaceName)) - Expect(res[netName].Interfaces[interfaceName].Networks).To(HaveLen(2)) - Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.IP.String()).To(Equal(ip1.String())) - Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.Mask).To(Equal(subnet1.Mask)) - Expect(res[netName].Interfaces[interfaceName].Networks[0].Gateway).To(Equal(net.ParseIP("192.168.0.1"))) - Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.IP.String()).To(Equal(ip2.String())) - Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.Mask).To(Equal(subnet2.Mask)) - Expect(res[netName].Interfaces[interfaceName].Networks[1].Gateway).To(Equal(net.ParseIP("fd41:0a75:2ca0:48a9::1"))) + Expect(res[netName].Interfaces[interfaceName].Subnets).To(HaveLen(2)) + Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.IP.String()).To(Equal(ip1.String())) + Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.Mask).To(Equal(subnet1.Mask)) + Expect(res[netName].Interfaces[interfaceName].Subnets[0].Gateway).To(Equal(net.ParseIP("192.168.0.1"))) + Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.IP.String()).To(Equal(ip2.String())) + Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.Mask).To(Equal(subnet2.Mask)) + Expect(res[netName].Interfaces[interfaceName].Subnets[1].Gateway).To(Equal(net.ParseIP("fd41:0a75:2ca0:48a9::1"))) Expect(res[netName].Interfaces[interfaceName].MacAddress).To(Equal(types.HardwareAddr(mac))) // default network has no dns Expect(res[netName].DNSServerIPs).To(BeEmpty()) @@ -799,9 +799,9 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(netName)) Expect(res[netName].Interfaces).To(HaveKey(intName)) - Expect(res[netName].Interfaces[intName].Networks).To(HaveLen(1)) - Expect(res[netName].Interfaces[intName].Networks[0].Subnet.IP.String()).To(Equal(ip)) - Expect(res[netName].Interfaces[intName].Networks[0].Subnet.Mask).To(Equal(net.CIDRMask(24, 32))) + Expect(res[netName].Interfaces[intName].Subnets).To(HaveLen(1)) + Expect(res[netName].Interfaces[intName].Subnets[0].IPNet.IP.String()).To(Equal(ip)) + Expect(res[netName].Interfaces[intName].Subnets[0].IPNet.Mask).To(Equal(net.CIDRMask(24, 32))) // check in the container namespace if the settings are applied err = netNSContainer.Do(func(_ ns.NetNS) error { @@ -902,11 +902,11 @@ var _ = Describe("run CNI", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(netName)) Expect(res[netName].Interfaces).To(HaveKey(interfaceName)) - Expect(res[netName].Interfaces[interfaceName].Networks).To(HaveLen(2)) - Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.IP.String()).To(Equal(ip1.String())) - Expect(res[netName].Interfaces[interfaceName].Networks[0].Subnet.Mask).To(Equal(mask1)) - Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.IP.String()).To(Equal(ip2.String())) - Expect(res[netName].Interfaces[interfaceName].Networks[1].Subnet.Mask).To(Equal(mask2)) + Expect(res[netName].Interfaces[interfaceName].Subnets).To(HaveLen(2)) + Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.IP.String()).To(Equal(ip1.String())) + Expect(res[netName].Interfaces[interfaceName].Subnets[0].IPNet.Mask).To(Equal(mask1)) + Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.IP.String()).To(Equal(ip2.String())) + Expect(res[netName].Interfaces[interfaceName].Subnets[1].IPNet.Mask).To(Equal(mask2)) // dualstack network dns Expect(res[netName].DNSServerIPs).To(HaveLen(2)) Expect(res[netName].DNSSearchDomains).To(HaveLen(1)) diff --git a/libpod/network/netavark/run_test.go b/libpod/network/netavark/run_test.go index 3279203cc..67dc51c10 100644 --- a/libpod/network/netavark/run_test.go +++ b/libpod/network/netavark/run_test.go @@ -131,10 +131,10 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - ip := res[defNet].Interfaces[intName].Networks[0].Subnet.IP + 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].Networks[0].Gateway + 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 @@ -222,8 +222,8 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - ip1 := res[defNet].Interfaces[intName].Networks[0].Subnet.IP + 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)) @@ -246,8 +246,8 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - ip2 := res[defNet].Interfaces[intName].Networks[0].Subnet.IP + 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()) @@ -286,14 +286,14 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(netName)) Expect(res[netName].Interfaces).To(HaveKey(intName)) - Expect(res[netName].Interfaces[intName].Networks).To(HaveLen(2)) - ip1 := res[netName].Interfaces[intName].Networks[0].Subnet.IP + 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].Networks[0].Gateway + gw1 := res[netName].Interfaces[intName].Subnets[0].Gateway Expect(gw1.String()).To(Equal("10.0.0.1")) - ip2 := res[netName].Interfaces[intName].Networks[1].Subnet.IP + ip2 := res[netName].Interfaces[intName].Subnets[1].IPNet.IP Expect(ip2.String()).To(ContainSubstring("fd10:88:a::")) - gw2 := res[netName].Interfaces[intName].Networks[0].Gateway + 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)) @@ -380,14 +380,14 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveKey(netName2)) Expect(res[netName1].Interfaces).To(HaveKey(intName1)) Expect(res[netName2].Interfaces).To(HaveKey(intName2)) - Expect(res[netName1].Interfaces[intName1].Networks).To(HaveLen(1)) - ip1 := res[netName1].Interfaces[intName1].Networks[0].Subnet.IP + 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].Networks[0].Gateway + gw1 := res[netName1].Interfaces[intName1].Subnets[0].Gateway Expect(gw1.String()).To(Equal("10.0.0.1")) - ip2 := res[netName2].Interfaces[intName2].Networks[0].Subnet.IP + ip2 := res[netName2].Interfaces[intName2].Subnets[0].IPNet.IP Expect(ip2.String()).To(ContainSubstring("10.1.0.")) - gw2 := res[netName2].Interfaces[intName2].Networks[0].Gateway + 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)) @@ -481,8 +481,8 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - Expect(res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String()).To(ContainSubstring("10.88.0.")) + 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()) @@ -535,8 +535,8 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - containerIP := res[defNet].Interfaces[intName].Networks[0].Subnet.IP.String() + 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 @@ -593,10 +593,10 @@ var _ = Describe("run netavark", func() { Expect(res).To(HaveLen(1)) Expect(res).To(HaveKey(defNet)) Expect(res[defNet].Interfaces).To(HaveKey(intName)) - Expect(res[defNet].Interfaces[intName].Networks).To(HaveLen(1)) - ip := res[defNet].Interfaces[intName].Networks[0].Subnet.IP + 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].Networks[0].Gateway + 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)) diff --git a/libpod/network/types/network.go b/libpod/network/types/network.go index ba5e018fd..105641e70 100644 --- a/libpod/network/types/network.go +++ b/libpod/network/types/network.go @@ -38,11 +38,11 @@ type Network struct { ID string `json:"id"` // Driver for this Network, e.g. bridge, macvlan... Driver string `json:"driver"` - // InterfaceName is the network interface name on the host. + // NetworkInterface is the network interface name on the host. NetworkInterface string `json:"network_interface,omitempty"` // Created contains the timestamp when this network was created. Created time.Time `json:"created,omitempty"` - // Subnets to use. + // Subnets to use for this network. Subnets []Subnet `json:"subnets,omitempty"` // IPv6Enabled if set to true an ipv6 subnet should be created for this net. IPv6Enabled bool `json:"ipv6_enabled"` @@ -177,24 +177,24 @@ type StatusBlock struct { // NetInterface contains the settings for a given network interface. type NetInterface struct { - // Networks list of assigned subnets with their gateway. - Networks []NetAddress `json:"networks,omitempty"` + // Subnets list of assigned subnets with their gateway. + Subnets []NetAddress `json:"subnets,omitempty"` // MacAddress for this Interface. MacAddress HardwareAddr `json:"mac_address"` } -// NetAddress contains the subnet and gateway. +// NetAddress contains the ip address, subnet and gateway. type NetAddress struct { - // Subnet of this NetAddress. Note that the subnet contains the - // actual ip of the net interface and not the network address. - Subnet IPNet `json:"subnet"` - // Gateway for the Subnet. This can be nil if there is no gateway, e.g. internal network. + // IPNet of this NetAddress. Note that this is a subnet but it has to contain the + // actual ip of the network interface and not the network address. + IPNet IPNet `json:"ipnet"` + // Gateway for the network. This can be empty if there is no gateway, e.g. internal network. Gateway net.IP `json:"gateway,omitempty"` } // PerNetworkOptions are options which should be set on a per network basis. type PerNetworkOptions struct { - // StaticIPv4 for this container. Optional. + // StaticIPs for this container. Optional. StaticIPs []net.IP `json:"static_ips,omitempty"` // Aliases contains a list of names which the dns server should resolve // to this container. Should only be set when DNSEnabled is true on the Network. diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index fc91155fa..9be600bb4 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -87,12 +87,28 @@ func (c *Container) GetNetworkAliases(netName string) ([]string, error) { return aliases, nil } +// convertPortMappings will remove the HostIP part from the ports when running inside podman machine. +// This is need because a HostIP of 127.0.0.1 would now allow the gvproxy forwarder to reach to open ports. +// For machine the HostIP must only be used by gvproxy and never in the VM. +func (c *Container) convertPortMappings() []types.PortMapping { + if !c.runtime.config.Engine.MachineEnabled || len(c.config.PortMappings) == 0 { + return c.config.PortMappings + } + // if we run in a machine VM we have to ignore the host IP part + newPorts := make([]types.PortMapping, 0, len(c.config.PortMappings)) + for _, port := range c.config.PortMappings { + port.HostIP = "" + newPorts = append(newPorts, port) + } + return newPorts +} + func (c *Container) getNetworkOptions() (types.NetworkOptions, error) { opts := types.NetworkOptions{ ContainerID: c.config.ID, ContainerName: getCNIPodName(c), } - opts.PortMappings = c.config.PortMappings + opts.PortMappings = c.convertPortMappings() networks, _, err := c.networks() if err != nil { return opts, err @@ -591,32 +607,9 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) { return rootlessNetNS, nil } -// setPrimaryMachineIP is used for podman-machine and it sets -// and environment variable with the IP address of the podman-machine -// host. -func setPrimaryMachineIP() error { - // no connection is actually made here - conn, err := net.Dial("udp", "8.8.8.8:80") - if err != nil { - return err - } - defer func() { - if err := conn.Close(); err != nil { - logrus.Error(err) - } - }() - addr := conn.LocalAddr().(*net.UDPAddr) - return os.Setenv("PODMAN_MACHINE_HOST", addr.IP.String()) -} - // setUpNetwork will set up the the networks, on error it will also tear down the cni // networks. If rootless it will join/create the rootless network namespace. func (r *Runtime) setUpNetwork(ns string, opts types.NetworkOptions) (map[string]types.StatusBlock, error) { - if r.config.MachineEnabled() { - if err := setPrimaryMachineIP(); err != nil { - return nil, err - } - } rootlessNetNS, err := r.GetRootlessNetNs(true) if err != nil { return nil, err @@ -650,7 +643,18 @@ func getCNIPodName(c *Container) string { } // Create and configure a new network namespace for a container -func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (map[string]types.StatusBlock, error) { +func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[string]types.StatusBlock, rerr error) { + if err := r.exposeMachinePorts(ctr.config.PortMappings); err != nil { + return nil, err + } + defer func() { + // make sure to unexpose the gvproxy ports when an error happens + if rerr != nil { + if err := r.unexposeMachinePorts(ctr.config.PortMappings); err != nil { + logrus.Errorf("failed to free gvproxy machine ports: %v", err) + } + } + }() if ctr.config.NetMode.IsSlirp4netns() { return nil, r.setupSlirp4netns(ctr, ctrNS) } @@ -836,6 +840,10 @@ func (r *Runtime) teardownCNI(ctr *Container) error { // Tear down a network namespace, undoing all state associated with it. func (r *Runtime) teardownNetNS(ctr *Container) error { + if err := r.unexposeMachinePorts(ctr.config.PortMappings); err != nil { + // do not return an error otherwise we would prevent network cleanup + logrus.Errorf("failed to free gvproxy machine ports: %v", err) + } if err := r.teardownCNI(ctr); err != nil { return err } @@ -929,8 +937,8 @@ func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.Statu Aliases: aliases[network], StaticMAC: netInt.MacAddress, } - for _, netAddress := range netInt.Networks { - perNetOpts.StaticIPs = append(perNetOpts.StaticIPs, netAddress.Subnet.IP) + for _, netAddress := range netInt.Subnets { + perNetOpts.StaticIPs = append(perNetOpts.StaticIPs, netAddress.IPNet.IP) } // Normally interfaces have a length of 1, only for some special cni configs we could get more. // For now just use the first interface to get the ips this should be good enough for most cases. @@ -1116,25 +1124,25 @@ func (c *Container) setupNetworkDescriptions(networks []string) error { func resultToBasicNetworkConfig(result types.StatusBlock) (define.InspectBasicNetworkConfig, error) { config := define.InspectBasicNetworkConfig{} for _, netInt := range result.Interfaces { - for _, netAddress := range netInt.Networks { - size, _ := netAddress.Subnet.Mask.Size() - if netAddress.Subnet.IP.To4() != nil { + for _, netAddress := range netInt.Subnets { + size, _ := netAddress.IPNet.Mask.Size() + if netAddress.IPNet.IP.To4() != nil { //ipv4 if config.IPAddress == "" { - config.IPAddress = netAddress.Subnet.IP.String() + config.IPAddress = netAddress.IPNet.IP.String() config.IPPrefixLen = size config.Gateway = netAddress.Gateway.String() } else { - config.SecondaryIPAddresses = append(config.SecondaryIPAddresses, netAddress.Subnet.IP.String()) + config.SecondaryIPAddresses = append(config.SecondaryIPAddresses, netAddress.IPNet.IP.String()) } } else { //ipv6 if config.GlobalIPv6Address == "" { - config.GlobalIPv6Address = netAddress.Subnet.IP.String() + config.GlobalIPv6Address = netAddress.IPNet.IP.String() config.GlobalIPv6PrefixLen = size config.IPv6Gateway = netAddress.Gateway.String() } else { - config.SecondaryIPv6Addresses = append(config.SecondaryIPv6Addresses, netAddress.Subnet.IP.String()) + config.SecondaryIPv6Addresses = append(config.SecondaryIPv6Addresses, netAddress.IPNet.IP.String()) } } } @@ -1206,7 +1214,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro ContainerID: c.config.ID, ContainerName: getCNIPodName(c), } - opts.PortMappings = c.config.PortMappings + opts.PortMappings = c.convertPortMappings() eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName) if !exists { return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName) @@ -1298,7 +1306,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, aliases []string) e ContainerID: c.config.ID, ContainerName: getCNIPodName(c), } - opts.PortMappings = c.config.PortMappings + opts.PortMappings = c.convertPortMappings() eth, exists := c.state.NetInterfaceDescriptions.getInterfaceByName(netName) if !exists { return errors.Errorf("no network interface name for container %s on network %s", c.config.ID, netName) diff --git a/libpod/networking_machine.go b/libpod/networking_machine.go new file mode 100644 index 000000000..7cb2a00f7 --- /dev/null +++ b/libpod/networking_machine.go @@ -0,0 +1,121 @@ +package libpod + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "io/ioutil" + "net" + "net/http" + "strconv" + "strings" + + "github.com/containers/podman/v3/libpod/network/types" + "github.com/sirupsen/logrus" +) + +const machineGvproxyEndpoint = "gateway.containers.internal" + +// machineExpose is the struct for the gvproxy port forwarding api send via json +type machineExpose struct { + // Local is the local address on the vm host, format is ip:port + Local string `json:"local"` + // Remote is used to specify the vm ip:port + Remote string `json:"remote,omitempty"` + // Protocol to forward, tcp or udp + Protocol string `json:"protocol"` +} + +func requestMachinePorts(expose bool, ports []types.PortMapping) error { + url := "http://" + machineGvproxyEndpoint + "/services/forwarder/" + if expose { + url = url + "expose" + } else { + url = url + "unexpose" + } + ctx := context.Background() + client := &http.Client{} + buf := new(bytes.Buffer) + for num, port := range ports { + protocols := strings.Split(port.Protocol, ",") + for _, protocol := range protocols { + for i := uint16(0); i < port.Range; i++ { + machinePort := machineExpose{ + Local: net.JoinHostPort(port.HostIP, strconv.FormatInt(int64(port.HostPort+i), 10)), + Protocol: protocol, + } + if expose { + // only set the remote port the ip will be automatically be set by gvproxy + machinePort.Remote = ":" + strconv.FormatInt(int64(port.HostPort+i), 10) + } + + // post request + if err := json.NewEncoder(buf).Encode(machinePort); err != nil { + if expose { + // in case of an error make sure to unexpose the other ports + if cerr := requestMachinePorts(false, ports[:num]); cerr != nil { + logrus.Errorf("failed to free gvproxy machine ports: %v", cerr) + } + } + return err + } + if err := makeMachineRequest(ctx, client, url, buf); err != nil { + if expose { + // in case of an error make sure to unexpose the other ports + if cerr := requestMachinePorts(false, ports[:num]); cerr != nil { + logrus.Errorf("failed to free gvproxy machine ports: %v", cerr) + } + } + return err + } + buf.Reset() + } + } + } + return nil +} + +func makeMachineRequest(ctx context.Context, client *http.Client, url string, buf io.Reader) error { + //var buf io.ReadWriter + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, buf) + if err != nil { + return err + } + req.Header.Add("Accept", "application/json") + req.Header.Add("Content-Type", "application/json") + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return annotateGvproxyResponseError(resp.Body) + } + return nil +} + +func annotateGvproxyResponseError(r io.Reader) error { + b, err := ioutil.ReadAll(r) + if err == nil && len(b) > 0 { + return fmt.Errorf("something went wrong with the request: %q", string(b)) + } + return errors.New("something went wrong with the request, could not read response") +} + +// exposeMachinePorts exposes the ports for podman machine via gvproxy +func (r *Runtime) exposeMachinePorts(ports []types.PortMapping) error { + if !r.config.Engine.MachineEnabled { + return nil + } + return requestMachinePorts(true, ports) +} + +// unexposeMachinePorts closes the ports for podman machine via gvproxy +func (r *Runtime) unexposeMachinePorts(ports []types.PortMapping) error { + if !r.config.Engine.MachineEnabled { + return nil + } + return requestMachinePorts(false, ports) +} diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go index 674075e23..cc1b3cfdc 100644 --- a/libpod/networking_slirp4netns.go +++ b/libpod/networking_slirp4netns.go @@ -509,7 +509,7 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin childIP := getRootlessPortChildIP(ctr, netStatus) cfg := rootlessport.Config{ - Mappings: ctr.config.PortMappings, + Mappings: ctr.convertPortMappings(), NetNSPath: netnsPath, ExitFD: 3, ReadyFD: 4, @@ -594,7 +594,7 @@ func (r *Runtime) setupRootlessPortMappingViaSlirp(ctr *Container, cmd *exec.Cmd // for each port we want to add we need to open a connection to the slirp4netns control socket // and send the add_hostfwd command. - for _, i := range ctr.config.PortMappings { + for _, i := range ctr.convertPortMappings() { conn, err := net.Dial("unix", apiSocket) if err != nil { return errors.Wrapf(err, "cannot open connection to %s", apiSocket) @@ -660,12 +660,12 @@ func getRootlessPortChildIP(c *Container, netStatus map[string]types.StatusBlock var ipv6 net.IP for _, status := range netStatus { for _, netInt := range status.Interfaces { - for _, netAddress := range netInt.Networks { - ipv4 := netAddress.Subnet.IP.To4() + for _, netAddress := range netInt.Subnets { + ipv4 := netAddress.IPNet.IP.To4() if ipv4 != nil { return ipv4.String() } - ipv6 = netAddress.Subnet.IP + ipv6 = netAddress.IPNet.IP } } } |