aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2018-11-28 06:18:28 -0800
committerGitHub <noreply@github.com>2018-11-28 06:18:28 -0800
commitd346996e1512ef6efb3800d6cb762d0409d12459 (patch)
treea5f9496bffe3df5a46627f56c0fee08aafdfee55
parent2a496aea30da4bbe4981753c11ed095867202466 (diff)
parent95f22a2ca055d6dec0281cee109375dc4fd9b78b (diff)
downloadpodman-d346996e1512ef6efb3800d6cb762d0409d12459.tar.gz
podman-d346996e1512ef6efb3800d6cb762d0409d12459.tar.bz2
podman-d346996e1512ef6efb3800d6cb762d0409d12459.zip
Merge pull request #1849 from giuseppe/report-rootless-netmode
rootless: add new netmode "slirp4netns"
-rw-r--r--cmd/podman/common.go10
-rw-r--r--docs/podman-create.1.md3
-rw-r--r--docs/podman-run.1.md3
-rw-r--r--libpod/container.go3
-rw-r--r--libpod/container_easyjson.go13
-rw-r--r--libpod/container_internal.go2
-rw-r--r--libpod/oci.go2
-rw-r--r--libpod/options.go4
-rw-r--r--libpod/runtime_pod_infra_linux.go6
-rw-r--r--pkg/namespaces/namespaces.go7
-rw-r--r--pkg/spec/createconfig.go4
-rw-r--r--pkg/spec/spec.go3
-rw-r--r--pkg/varlinkapi/containers_create.go7
-rw-r--r--test/e2e/libpod_suite_test.go6
-rw-r--r--test/e2e/rootless_test.go8
-rw-r--r--test/utils/podmantest_test.go4
-rw-r--r--test/utils/utils.go6
17 files changed, 75 insertions, 16 deletions
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index f9e746b28..c4016698a 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -11,6 +11,7 @@ import (
"github.com/containers/buildah"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/containers/storage"
"github.com/fatih/camelcase"
"github.com/pkg/errors"
@@ -161,6 +162,13 @@ func getContext() context.Context {
return context.TODO()
}
+func getDefaultNetwork() string {
+ if rootless.IsRootless() {
+ return "slirp4netns"
+ }
+ return "bridge"
+}
+
// Common flags shared between commands
var createFlags = []cli.Flag{
cli.StringSliceFlag{
@@ -372,7 +380,7 @@ var createFlags = []cli.Flag{
cli.StringFlag{
Name: "net, network",
Usage: "Connect a container to a network",
- Value: "bridge",
+ Value: getDefaultNetwork(),
},
cli.BoolFlag{
Name: "oom-kill-disable",
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 68c00685b..474796a35 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -426,7 +426,8 @@ Set the Network mode for the container
'container:<name|id>': reuse another container's network stack
'host': use the podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
'<network-name>|<network-id>': connect to a user-defined network
- 'ns:<path>' path to a network namespace to join
+ 'ns:<path>': path to a network namespace to join
+ 'slirp4netns': use slirp4netns to create a user network stack. This is the default for rootless containers
**--network-alias**=[]
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index 912026a55..202091b07 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -408,7 +408,8 @@ Set the Network mode for the container:
- `container:<name|id>`: reuse another container's network stack
- `host`: use the podman host network stack. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.
- `<network-name>|<network-id>`: connect to a user-defined network
-- `ns:<path>` path to a network namespace to join
+- `ns:<path>`: path to a network namespace to join
+- `slirp4netns`: use slirp4netns to create a user network stack. This is the default for rootless containers
**--network-alias**=[]
diff --git a/libpod/container.go b/libpod/container.go
index 16f61d021..a8a58f4d8 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -9,6 +9,7 @@ import (
"github.com/containernetworking/cni/pkg/types"
cnitypes "github.com/containernetworking/cni/pkg/types/current"
+ "github.com/containers/libpod/pkg/namespaces"
"github.com/containers/storage"
"github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -296,6 +297,8 @@ type ContainerConfig struct {
HostAdd []string `json:"hostsAdd,omitempty"`
// Network names (CNI) to add container to. Empty to use default network.
Networks []string `json:"networks,omitempty"`
+ // Network mode specified for the default network.
+ NetMode namespaces.NetworkMode `json:"networkMode,omitempty"`
// Image Config
diff --git a/libpod/container_easyjson.go b/libpod/container_easyjson.go
index 041cc08ac..8bf5cb64f 100644
--- a/libpod/container_easyjson.go
+++ b/libpod/container_easyjson.go
@@ -8,6 +8,7 @@ import (
json "encoding/json"
types "github.com/containernetworking/cni/pkg/types"
current "github.com/containernetworking/cni/pkg/types/current"
+ namespaces "github.com/containers/libpod/pkg/namespaces"
storage "github.com/containers/storage"
idtools "github.com/containers/storage/pkg/idtools"
ocicni "github.com/cri-o/ocicni/pkg/ocicni"
@@ -1550,6 +1551,8 @@ func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, ou
}
in.Delim(']')
}
+ case "networkMode":
+ out.NetMode = namespaces.NetworkMode(in.String())
case "userVolumes":
if in.IsNull() {
in.Skip()
@@ -2177,6 +2180,16 @@ func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer,
out.RawByte(']')
}
}
+ if in.NetMode != "" {
+ const prefix string = ",\"networkMode\":"
+ if first {
+ first = false
+ out.RawString(prefix[1:])
+ } else {
+ out.RawString(prefix)
+ }
+ out.String(string(in.NetMode))
+ }
if len(in.UserVolumes) != 0 {
const prefix string = ",\"userVolumes\":"
if first {
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 051e0aeb7..e44ec76ec 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -586,7 +586,7 @@ func (c *Container) completeNetworkSetup() error {
if err := c.syncContainer(); err != nil {
return err
}
- if rootless.IsRootless() {
+ if c.config.NetMode == "slirp4netns" {
return c.runtime.setupRootlessNetNS(c)
}
return c.runtime.setupNetNS(c)
diff --git a/libpod/oci.go b/libpod/oci.go
index ee1677b67..4460402ed 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -333,7 +333,7 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
cmd.ExtraFiles = append(cmd.ExtraFiles, ports...)
}
- if rootless.IsRootless() {
+ if ctr.config.NetMode.IsSlirp4netns() {
ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe()
if err != nil {
return errors.Wrapf(err, "failed to create rootless network sync pipe")
diff --git a/libpod/options.go b/libpod/options.go
index 507847d65..7f4e3ac6b 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -7,6 +7,7 @@ import (
"regexp"
"syscall"
+ "github.com/containers/libpod/pkg/namespaces"
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
"github.com/cri-o/ocicni/pkg/ocicni"
@@ -817,7 +818,7 @@ func WithDependencyCtrs(ctrs []*Container) CtrCreateOption {
// namespace with a minimal configuration.
// An optional array of port mappings can be provided.
// Conflicts with WithNetNSFrom().
-func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, networks []string) CtrCreateOption {
+func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netmode string, networks []string) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
@@ -831,6 +832,7 @@ func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool, netwo
ctr.config.CreateNetNS = true
ctr.config.PortMappings = portMappings
ctr.config.Networks = networks
+ ctr.config.NetMode = namespaces.NetworkMode(netmode)
return nil
}
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 450a2fb32..8a5dbef56 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -50,7 +50,11 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, imgID
// Since user namespace sharing is not implemented, we only need to check if it's rootless
networks := make([]string, 0)
- options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, isRootless, networks))
+ netmode := "bridge"
+ if isRootless {
+ netmode = "slirp4netns"
+ }
+ options = append(options, WithNetNS(p.config.InfraContainer.PortBindings, isRootless, netmode, networks))
return r.newContainer(ctx, g.Config, options...)
}
diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go
index bee833fa9..832efd554 100644
--- a/pkg/namespaces/namespaces.go
+++ b/pkg/namespaces/namespaces.go
@@ -223,7 +223,12 @@ func (n NetworkMode) IsBridge() bool {
return n == "bridge"
}
+// IsSlirp4netns indicates if we are running a rootless network stack
+func (n NetworkMode) IsSlirp4netns() bool {
+ return n == "slirp4netns"
+}
+
// IsUserDefined indicates user-created network
func (n NetworkMode) IsUserDefined() bool {
- return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()
+ return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer() && !n.IsSlirp4netns()
}
diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go
index 6a0642ee7..a0fd40318 100644
--- a/pkg/spec/createconfig.go
+++ b/pkg/spec/createconfig.go
@@ -391,11 +391,11 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib
options = append(options, libpod.WithNetNSFrom(connectedCtr))
} else if !c.NetMode.IsHost() && !c.NetMode.IsNone() {
isRootless := rootless.IsRootless()
- postConfigureNetNS := isRootless || (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost()
+ postConfigureNetNS := c.NetMode.IsSlirp4netns() || (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost()
if isRootless && len(portBindings) > 0 {
return nil, errors.New("port bindings are not yet supported by rootless containers")
}
- options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, networks))
+ options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(c.NetMode), networks))
}
if c.PidMode.IsContainer() {
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index b1cca2c9e..05be00864 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -453,6 +453,9 @@ func addNetNS(config *CreateConfig, g *generate.Generator) error {
} else if IsPod(string(netMode)) {
logrus.Debug("Using pod netmode, unless pod is not sharing")
return nil
+ } else if netMode.IsSlirp4netns() {
+ logrus.Debug("Using slirp4netns netmode")
+ return nil
} else if netMode.IsUserDefined() {
logrus.Debug("Using user defined netmode")
return nil
diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go
index ca1a57048..f9a2db9c8 100644
--- a/pkg/varlinkapi/containers_create.go
+++ b/pkg/varlinkapi/containers_create.go
@@ -13,6 +13,7 @@ import (
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/inspect"
"github.com/containers/libpod/pkg/namespaces"
+ "github.com/containers/libpod/pkg/rootless"
cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/util"
"github.com/docker/docker/pkg/signal"
@@ -126,7 +127,11 @@ func varlinkCreateToCreateConfig(ctx context.Context, create iopodman.Create, ru
// NETWORK MODE
networkMode := create.Net_mode
if networkMode == "" {
- networkMode = "bridge"
+ if rootless.IsRootless() {
+ networkMode = "slirp4netns"
+ } else {
+ networkMode = "bridge"
+ }
}
// WORKING DIR
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 52507c083..f4f154ef2 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -181,6 +181,12 @@ func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration
return &PodmanSessionIntegration{podmanSession}
}
+// PodmanAsUser is the exec call to podman on the filesystem with the specified uid/gid and environment
+func (p *PodmanTestIntegration) PodmanAsUser(args []string, uid, gid uint32, env []string) *PodmanSessionIntegration {
+ podmanSession := p.PodmanAsUserBase(args, uid, gid, env)
+ return &PodmanSessionIntegration{podmanSession}
+}
+
// PodmanPID execs podman and returns its PID
func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) {
podmanOptions := p.MakeOptions(args)
diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go
index 676459416..c75910296 100644
--- a/test/e2e/rootless_test.go
+++ b/test/e2e/rootless_test.go
@@ -221,6 +221,14 @@ var _ = Describe("Podman rootless", func() {
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
+ if len(args) == 0 {
+ cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l"}, 1000, 1000, env)
+ cmd.WaitWithDefaultTimeout()
+ Expect(cmd.ExitCode()).To(Equal(0))
+ data := cmd.InspectContainerToJSON()
+ Expect(data[0].HostConfig.NetworkMode).To(ContainSubstring("slirp4netns"))
+ }
+
if !canUseExec {
Skip("ioctl(NS_GET_PARENT) not supported.")
}
diff --git a/test/utils/podmantest_test.go b/test/utils/podmantest_test.go
index 87f756920..60e3e2a97 100644
--- a/test/utils/podmantest_test.go
+++ b/test/utils/podmantest_test.go
@@ -19,11 +19,11 @@ var _ = Describe("PodmanTest test", func() {
FakeOutputs = make(map[string][]string)
})
- It("Test PodmanAsUser", func() {
+ It("Test PodmanAsUserBase", func() {
FakeOutputs["check"] = []string{"check"}
os.Setenv("HOOK_OPTION", "hook_option")
env := os.Environ()
- session := podmanTest.PodmanAsUser([]string{"check"}, 1000, 1000, env)
+ session := podmanTest.PodmanAsUserBase([]string{"check"}, 1000, 1000, env)
os.Unsetenv("HOOK_OPTION")
session.WaitWithDefaultTimeout()
Expect(session.Command.Process).ShouldNot(BeNil())
diff --git a/test/utils/utils.go b/test/utils/utils.go
index c9409c9d4..288c768d4 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -56,9 +56,9 @@ func (p *PodmanTest) MakeOptions(args []string) []string {
return p.PodmanMakeOptions(args)
}
-// PodmanAsUser exec podman as user. uid and gid is set for credentials useage. env is used
+// PodmanAsUserBase exec podman as user. uid and gid is set for credentials useage. env is used
// to record the env for debugging
-func (p *PodmanTest) PodmanAsUser(args []string, uid, gid uint32, env []string) *PodmanSession {
+func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, env []string) *PodmanSession {
var command *exec.Cmd
podmanOptions := p.MakeOptions(args)
@@ -86,7 +86,7 @@ func (p *PodmanTest) PodmanAsUser(args []string, uid, gid uint32, env []string)
// PodmanBase exec podman with default env.
func (p *PodmanTest) PodmanBase(args []string) *PodmanSession {
- return p.PodmanAsUser(args, 0, 0, nil)
+ return p.PodmanAsUserBase(args, 0, 0, nil)
}
// WaitForContainer waits on a started container