diff options
author | Daniel J Walsh <dwalsh@redhat.com> | 2019-02-17 21:55:30 -0500 |
---|---|---|
committer | Daniel J Walsh <dwalsh@redhat.com> | 2019-02-23 05:47:27 -0500 |
commit | b87bdced1fa967846916b47cba5f093f72f3d11f (patch) | |
tree | 27342efd5d84839584260b9e2883e27ed8fbbd22 | |
parent | b223d4e1367463a32eeeb31a4b9d8a351641d83c (diff) | |
download | podman-b87bdced1fa967846916b47cba5f093f72f3d11f.tar.gz podman-b87bdced1fa967846916b47cba5f093f72f3d11f.tar.bz2 podman-b87bdced1fa967846916b47cba5f093f72f3d11f.zip |
Fix up handling of user defined network namespaces
If user specifies network namespace and the /etc/netns/XXX/resolv.conf
exists, we should use this rather then /etc/resolv.conf
Also fail cleaner if the user specifies an invalid Network Namespace.
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
-rw-r--r-- | contrib/cirrus/packer/fedora_setup.sh | 1 | ||||
-rw-r--r-- | contrib/cirrus/packer/ubuntu_setup.sh | 1 | ||||
-rw-r--r-- | docs/podman-run.1.md | 14 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 18 | ||||
-rw-r--r-- | libpod/options.go | 4 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 10 | ||||
-rw-r--r-- | test/e2e/run_networking_test.go | 39 |
7 files changed, 74 insertions, 13 deletions
diff --git a/contrib/cirrus/packer/fedora_setup.sh b/contrib/cirrus/packer/fedora_setup.sh index 01c468901..de7ad4506 100644 --- a/contrib/cirrus/packer/fedora_setup.sh +++ b/contrib/cirrus/packer/fedora_setup.sh @@ -40,6 +40,7 @@ ooe.sh sudo dnf install -y \ golang-github-cpuguy83-go-md2man \ gpgme-devel \ iptables \ + iproute \ libassuan-devel \ libcap-devel \ libnet \ diff --git a/contrib/cirrus/packer/ubuntu_setup.sh b/contrib/cirrus/packer/ubuntu_setup.sh index 7d49c5dc7..5b7e1d714 100644 --- a/contrib/cirrus/packer/ubuntu_setup.sh +++ b/contrib/cirrus/packer/ubuntu_setup.sh @@ -48,6 +48,7 @@ ooe.sh sudo -E apt-get -qq install \ gettext \ go-md2man \ golang \ + iproute \ iptables \ libaio-dev \ libapparmor-dev \ diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md index b928f61f5..bbf10a2ce 100644 --- a/docs/podman-run.1.md +++ b/docs/podman-run.1.md @@ -28,6 +28,8 @@ servers in the created `resolv.conf`). Additionally, an empty file is created in each container to indicate to programs they are running in a container. This file is located at `/run/.containerenv`. +When running from a user defined network namespace, the /etc/netns/NSNAME/resolv.conf will be used if it exists, otherwise /etc/resolv.conf will be used. + ## OPTIONS **--add-host**=[] @@ -694,21 +696,21 @@ Current supported mount TYPES are bind, and tmpfs. Common Options: - · src, source: mount source spec for bind and volume. Mandatory for bind. + · src, source: mount source spec for bind and volume. Mandatory for bind. - · dst, destination, target: mount destination spec. + · dst, destination, target: mount destination spec. - · ro, read-only: true or false (default). + · ro, read-only: true or false (default). Options specific to bind: - · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2). + · bind-propagation: Z, z, shared, slave, private, rshared, rslave, or rprivate(default). See also mount(2). Options specific to tmpfs: - · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux. + · tmpfs-size: Size of the tmpfs mount in bytes. Unlimited by default in Linux. - · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux. + · tmpfs-mode: File mode of the tmpfs in octal. (e.g. 700 or 0700.) Defaults to 1777 in Linux. **--userns**="" diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 86f94477e..2665dd81d 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -758,8 +758,24 @@ func (c *Container) makeBindMounts() error { // generateResolvConf generates a containers resolv.conf func (c *Container) generateResolvConf() (string, error) { + resolvConf := "/etc/resolv.conf" + for _, ns := range c.config.Spec.Linux.Namespaces { + if ns.Type == spec.NetworkNamespace { + if ns.Path != "" && !strings.HasPrefix(ns.Path, "/proc/") { + definedPath := filepath.Join("/etc/netns", filepath.Base(ns.Path), "resolv.conf") + _, err := os.Stat(definedPath) + if err == nil { + resolvConf = definedPath + } else if !os.IsNotExist(err) { + return "", errors.Wrapf(err, "failed to stat %s", definedPath) + } + } + break + } + } + // Determine the endpoint for resolv.conf in case it is a symlink - resolvPath, err := filepath.EvalSymlinks("/etc/resolv.conf") + resolvPath, err := filepath.EvalSymlinks(resolvConf) if err != nil { return "", err } diff --git a/libpod/options.go b/libpod/options.go index 9aa020b56..e22c81f91 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -904,10 +904,10 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmo } ctr.config.PostConfigureNetNS = postConfigureNetNS - ctr.config.CreateNetNS = true + ctr.config.NetMode = namespaces.NetworkMode(netmode) + ctr.config.CreateNetNS = !ctr.config.NetMode.IsUserDefined() ctr.config.PortMappings = portMappings ctr.config.Networks = networks - ctr.config.NetMode = namespaces.NetworkMode(netmode) return nil } diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 8da44a2f0..50e07ee74 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -446,7 +446,15 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime, pod *l } if IsNS(string(c.NetMode)) { - // pass + split := strings.SplitN(string(c.NetMode), ":", 2) + if len(split[0]) != 2 { + return nil, errors.Errorf("invalid user defined network namespace %q", c.NetMode.UserDefined()) + } + _, err := os.Stat(split[1]) + if err != nil { + return nil, err + } + options = append(options, libpod.WithNetNS(portBindings, false, string(c.NetMode), networks)) } else if c.NetMode.IsContainer() { connectedCtr, err := c.Runtime.LookupContainer(c.NetMode.Container()) if err != nil { diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 1c09a4d0b..a07e4d047 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -36,19 +36,19 @@ var _ = Describe("Podman run networking", func() { }) It("podman run network connection with default bridge", func() { - session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "wget", "www.projectatomic.io"}) + session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "wget", "www.podman.io"}) session.Wait(90) Expect(session.ExitCode()).To(Equal(0)) }) It("podman run network connection with host", func() { - session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.projectatomic.io"}) + session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.podman.io"}) session.Wait(90) Expect(session.ExitCode()).To(Equal(0)) }) It("podman run network connection with loopback", func() { - session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.projectatomic.io"}) + session := podmanTest.Podman([]string{"run", "-dt", "--network", "host", ALPINE, "wget", "www.podman.io"}) session.Wait(90) Expect(session.ExitCode()).To(Equal(0)) }) @@ -178,4 +178,37 @@ var _ = Describe("Podman run networking", func() { Expect(exec4.ExitCode()).To(Equal(0)) Expect(exec4.OutputToString()).To(ContainSubstring("192.0.2.2 test1")) }) + + It("podman run network in user created network namespace", func() { + if Containerized() { + Skip("Can not be run within a container.") + } + SystemExec("ip", []string{"netns", "add", "xxx"}) + session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxx", ALPINE, "wget", "www.podman.io"}) + session.Wait(90) + Expect(session.ExitCode()).To(Equal(0)) + SystemExec("ip", []string{"netns", "delete", "xxx"}) + }) + + It("podman run n user created network namespace with resolv.conf", func() { + if Containerized() { + Skip("Can not be run within a container.") + } + SystemExec("ip", []string{"netns", "add", "xxx"}) + SystemExec("mkdir", []string{"-p", "/etc/netns/xxx"}) + SystemExec("bash", []string{"-c", "echo nameserver 11.11.11.11 > /etc/netns/xxx/resolv.conf"}) + session := podmanTest.Podman([]string{"run", "--net", "ns:/run/netns/xxx", ALPINE, "cat", "/etc/resolv.conf"}) + session.Wait(90) + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("11.11.11.11")) + SystemExec("ip", []string{"netns", "delete", "xxx"}) + SystemExec("rm", []string{"-rf", "/etc/netns/xxx"}) + }) + + It("podman run network in bogus user created network namespace", func() { + session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxy", ALPINE, "wget", "www.podman.io"}) + session.Wait(90) + Expect(session.ExitCode()).To(Not(Equal(0))) + Expect(session.ErrorToString()).To(ContainSubstring("stat /run/netns/xxy: no such file or directory")) + }) }) |