summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go2
-rw-r--r--libpod/container_internal.go24
-rw-r--r--libpod/networking.go73
-rw-r--r--libpod/options.go3
4 files changed, 83 insertions, 19 deletions
diff --git a/libpod/container.go b/libpod/container.go
index fb1f83c29..5fa27af58 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -285,6 +285,8 @@ type ContainerConfig struct {
// File containing the conmon PID
ConmonPidFile string `json:"conmonPidFile,omitempty"`
// TODO log options for log drivers
+
+ PostConfigureNetNS bool `json:"postConfigureNetNS"`
}
// ContainerStatus returns a string representation for users
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 73095316e..18b56e23c 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -416,6 +416,16 @@ func (c *Container) checkDependenciesRunningLocked(depCtrs map[string]*Container
return notRunning, nil
}
+func (c *Container) completeNetworkSetup() error {
+ if !c.config.PostConfigureNetNS {
+ return nil
+ }
+ if err := c.syncContainer(); err != nil {
+ return err
+ }
+ return c.runtime.setupNetNS(c)
+}
+
// Initialize a container, creating it in the runtime
func (c *Container) init(ctx context.Context) error {
if err := c.makeBindMounts(); err != nil {
@@ -442,7 +452,11 @@ func (c *Container) init(ctx context.Context) error {
c.state.State = ContainerStateCreated
- return c.save()
+ if err := c.save(); err != nil {
+ return err
+ }
+
+ return c.completeNetworkSetup()
}
// Reinitialize a container
@@ -626,7 +640,7 @@ func (c *Container) prepare() (err error) {
}
// Set up network namespace if not already set up
- if c.config.CreateNetNS && c.state.NetNS == nil {
+ if c.config.CreateNetNS && c.state.NetNS == nil && !c.config.PostConfigureNetNS {
if err := c.runtime.createNetNS(c); err != nil {
// Tear down storage before exiting to make sure we
// don't leak mounts
@@ -913,7 +927,11 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
// If network namespace was requested, add it now
if c.config.CreateNetNS {
- g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path())
+ if c.config.PostConfigureNetNS {
+ g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, "")
+ } else {
+ g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path())
+ }
}
// Remove the default /dev/shm mount to ensure we overwrite it
diff --git a/libpod/networking.go b/libpod/networking.go
index cceeb18d6..54a1c78de 100644
--- a/libpod/networking.go
+++ b/libpod/networking.go
@@ -1,7 +1,12 @@
package libpod
import (
+ "crypto/rand"
+ "fmt"
"net"
+ "os"
+ "path/filepath"
+ "strings"
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
@@ -9,7 +14,7 @@ import (
"github.com/pkg/errors"
"github.com/projectatomic/libpod/utils"
"github.com/sirupsen/logrus"
- "strings"
+ "golang.org/x/sys/unix"
)
// Get an OCICNI network config
@@ -24,20 +29,7 @@ func getPodNetwork(id, name, nsPath string, ports []ocicni.PortMapping) ocicni.P
}
// Create and configure a new network namespace for a container
-func (r *Runtime) createNetNS(ctr *Container) (err error) {
- ctrNS, err := ns.NewNS()
- if err != nil {
- return errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID())
- }
- defer func() {
- if err != nil {
- if err2 := ctrNS.Close(); err2 != nil {
- logrus.Errorf("Error closing partially created network namespace for container %s: %v", ctr.ID(), err2)
- }
- }
- }()
-
- logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID())
+func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (err error) {
podNetwork := getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.PortMappings)
result, err := r.netPlugin.SetUpPod(podNetwork)
@@ -74,6 +66,57 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) {
return nil
}
+// Create and configure a new network namespace for a container
+func (r *Runtime) createNetNS(ctr *Container) (err error) {
+ ctrNS, err := ns.NewNS()
+ if err != nil {
+ return errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID())
+ }
+ defer func() {
+ if err != nil {
+ if err2 := ctrNS.Close(); err2 != nil {
+ logrus.Errorf("Error closing partially created network namespace for container %s: %v", ctr.ID(), err2)
+ }
+ }
+ }()
+
+ logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID())
+ return r.configureNetNS(ctr, ctrNS)
+}
+
+// Configure the network namespace using the container process
+func (r *Runtime) setupNetNS(ctr *Container) (err error) {
+ nsProcess := fmt.Sprintf("/proc/%d/ns/net", ctr.state.PID)
+
+ b := make([]byte, 16)
+
+ if _, err := rand.Reader.Read(b); err != nil {
+ return errors.Wrapf(err, "failed to generate random netns name")
+ }
+
+ nsPath := fmt.Sprintf("/var/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
+
+ if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil {
+ return errors.Wrapf(err, "cannot create %s", filepath.Dir(nsPath))
+ }
+
+ mountPointFd, err := os.Create(nsPath)
+ if err != nil {
+ return errors.Wrapf(err, "cannot open %s", nsPath)
+ }
+ mountPointFd.Close()
+
+ if err := unix.Mount(nsProcess, nsPath, "none", unix.MS_BIND, ""); err != nil {
+ return errors.Wrapf(err, "cannot mount %s", nsPath)
+ }
+
+ netNS, err := ns.GetNS(nsPath)
+ if err != nil {
+ return err
+ }
+ return r.configureNetNS(ctr, netNS)
+}
+
// iptablesDNS accepts an arg (-I|-D) and IP address of the container and then
// generates an iptables command to either add or subtract the needed rule
func iptablesDNS(arg, ip string) error {
diff --git a/libpod/options.go b/libpod/options.go
index eaca70afc..2b3ad2eb4 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -707,7 +707,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) CtrCreateOption {
+func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
@@ -717,6 +717,7 @@ func WithNetNS(portMappings []ocicni.PortMapping) CtrCreateOption {
return errors.Wrapf(ErrInvalidArg, "container is already set to join another container's net ns, cannot create a new net ns")
}
+ ctr.config.PostConfigureNetNS = postConfigureNetNS
ctr.config.CreateNetNS = true
ctr.config.PortMappings = portMappings