mirror of
https://github.com/containers/podman.git
synced 2025-05-17 15:18:43 +08:00
libpod: move NetNS into state db instead of extra bucket
This should simplify the db logic. We no longer need a extra db bucket for the netns, it is still supported in read only mode for backwards compat. The old version required us to always open the netns before we could attach it to the container state struct which caused problem in some cases were the netns was no longer valid. Now we use the netns as string throughout the code, this allow us to only open it when needed reducing possible errors. [NO NEW TESTS NEEDED] Existing tests should cover it and it is only a flake so hard to reproduce the error. Fixes #16140 Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -817,7 +816,6 @@ func (s *BoltState) UpdateContainer(ctr *Container) error {
|
||||
}
|
||||
|
||||
newState := new(ContainerState)
|
||||
netNSPath := ""
|
||||
|
||||
ctrID := []byte(ctr.ID())
|
||||
|
||||
@ -848,9 +846,10 @@ func (s *BoltState) UpdateContainer(ctr *Container) error {
|
||||
return fmt.Errorf("unmarshalling container %s state: %w", ctr.ID(), err)
|
||||
}
|
||||
|
||||
// backwards compat, previously we used a extra bucket for the netns so try to get it from there
|
||||
netNSBytes := ctrToUpdate.Get(netNSKey)
|
||||
if netNSBytes != nil {
|
||||
netNSPath = string(netNSBytes)
|
||||
if netNSBytes != nil && newState.NetNS == "" {
|
||||
newState.NetNS = string(netNSBytes)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -859,15 +858,6 @@ func (s *BoltState) UpdateContainer(ctr *Container) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle network namespace.
|
||||
if os.Geteuid() == 0 {
|
||||
// Do it only when root, either on the host or as root in the
|
||||
// user namespace.
|
||||
if err := replaceNetNS(netNSPath, ctr, newState); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// New state compiled successfully, swap it into the current state
|
||||
ctr.state = newState
|
||||
|
||||
@ -892,7 +882,7 @@ func (s *BoltState) SaveContainer(ctr *Container) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshalling container %s state to JSON: %w", ctr.ID(), err)
|
||||
}
|
||||
netNSPath := getNetNSPath(ctr)
|
||||
netNSPath := ctr.state.NetNS
|
||||
|
||||
ctrID := []byte(ctr.ID())
|
||||
|
||||
@ -919,11 +909,7 @@ func (s *BoltState) SaveContainer(ctr *Container) error {
|
||||
return fmt.Errorf("updating container %s state in DB: %w", ctr.ID(), err)
|
||||
}
|
||||
|
||||
if netNSPath != "" {
|
||||
if err := ctrToSave.Put(netNSKey, []byte(netNSPath)); err != nil {
|
||||
return fmt.Errorf("updating network namespace path for container %s in DB: %w", ctr.ID(), err)
|
||||
}
|
||||
} else {
|
||||
if netNSPath == "" {
|
||||
// Delete the existing network namespace
|
||||
if err := ctrToSave.Delete(netNSKey); err != nil {
|
||||
return fmt.Errorf("removing network namespace path for container %s in DB: %w", ctr.ID(), err)
|
||||
|
@ -1,25 +0,0 @@
|
||||
//go:build freebsd
|
||||
// +build freebsd
|
||||
|
||||
package libpod
|
||||
|
||||
// replaceNetNS handle network namespace transitions after updating a
|
||||
// container's state.
|
||||
func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error {
|
||||
if netNSPath != "" {
|
||||
// On FreeBSD, we just record the network jail's name in our state.
|
||||
newState.NetNS = &jailNetNS{Name: netNSPath}
|
||||
} else {
|
||||
newState.NetNS = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getNetNSPath retrieves the netns path to be stored in the database
|
||||
func getNetNSPath(ctr *Container) string {
|
||||
if ctr.state.NetNS != nil {
|
||||
return ctr.state.NetNS.Name
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
@ -590,7 +590,6 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshalling container %s state to JSON: %w", ctr.ID(), err)
|
||||
}
|
||||
netNSPath := getNetNSPath(ctr)
|
||||
dependsCtrs := ctr.Dependencies()
|
||||
|
||||
ctrID := []byte(ctr.ID())
|
||||
@ -741,11 +740,6 @@ func (s *BoltState) addContainer(ctr *Container, pod *Pod) error {
|
||||
return fmt.Errorf("adding container %s pod to DB: %w", ctr.ID(), err)
|
||||
}
|
||||
}
|
||||
if netNSPath != "" {
|
||||
if err := newCtrBkt.Put(netNSKey, []byte(netNSPath)); err != nil {
|
||||
return fmt.Errorf("adding container %s netns path to DB: %w", ctr.ID(), err)
|
||||
}
|
||||
}
|
||||
if len(networks) > 0 {
|
||||
ctrNetworksBkt, err := newCtrBkt.CreateBucket(networksBkt)
|
||||
if err != nil {
|
||||
|
@ -1,57 +0,0 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/podman/v4/libpod/define"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// replaceNetNS handle network namespace transitions after updating a
|
||||
// container's state.
|
||||
func replaceNetNS(netNSPath string, ctr *Container, newState *ContainerState) error {
|
||||
if netNSPath != "" {
|
||||
// Check if the container's old state has a good netns
|
||||
if ctr.state.NetNS != nil && netNSPath == ctr.state.NetNS.Path() {
|
||||
newState.NetNS = ctr.state.NetNS
|
||||
} else {
|
||||
// Close the existing namespace.
|
||||
// Whoever removed it from the database already tore it down.
|
||||
if err := ctr.runtime.closeNetNS(ctr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Open the new network namespace
|
||||
ns, err := joinNetNS(netNSPath)
|
||||
if err == nil {
|
||||
newState.NetNS = ns
|
||||
} else {
|
||||
if ctr.ensureState(define.ContainerStateRunning, define.ContainerStatePaused) {
|
||||
return fmt.Errorf("joining network namespace of container %s: %w", ctr.ID(), err)
|
||||
}
|
||||
|
||||
logrus.Errorf("Joining network namespace for container %s: %v", ctr.ID(), err)
|
||||
ctr.state.NetNS = nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// The container no longer has a network namespace
|
||||
// Close the old one, whoever removed it from the DB should have
|
||||
// cleaned it up already.
|
||||
if err := ctr.runtime.closeNetNS(ctr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// getNetNSPath retrieves the netns path to be stored in the database
|
||||
func getNetNSPath(ctr *Container) string {
|
||||
if ctr.state.NetNS != nil {
|
||||
return ctr.state.NetNS.Path()
|
||||
}
|
||||
return ""
|
||||
}
|
@ -169,6 +169,8 @@ type ContainerState struct {
|
||||
// Podman.
|
||||
// These are DEPRECATED and will be removed in a future release.
|
||||
LegacyExecSessions map[string]*legacyExecSession `json:"execSessions,omitempty"`
|
||||
// NetNS is the path or name of the NetNS
|
||||
NetNS string `json:"netns,omitempty"`
|
||||
// NetworkStatusOld contains the configuration results for all networks
|
||||
// the pod is attached to. Only populated if we created a network
|
||||
// namespace for the container, and the network namespace is currently
|
||||
@ -228,9 +230,6 @@ type ContainerState struct {
|
||||
// `podman-play-kube`.
|
||||
Service Service
|
||||
|
||||
// containerPlatformState holds platform-specific container state.
|
||||
containerPlatformState
|
||||
|
||||
// Following checkpoint/restore related information is displayed
|
||||
// if the container has been checkpointed or restored.
|
||||
CheckpointedTime time.Time `json:"checkpointedTime,omitempty"`
|
||||
|
@ -3,29 +3,12 @@
|
||||
|
||||
package libpod
|
||||
|
||||
type containerPlatformState struct {
|
||||
// NetNS is the name of the container's network VNET
|
||||
// jail. Will only be set if config.CreateNetNS is true, or
|
||||
// the container was told to join another container's network
|
||||
// namespace.
|
||||
NetNS *jailNetNS `json:"-"`
|
||||
}
|
||||
|
||||
type jailNetNS struct {
|
||||
Name string `json:"-"`
|
||||
}
|
||||
|
||||
func (ns *jailNetNS) Path() string {
|
||||
// The jail name approximately corresponds to the Linux netns path
|
||||
return ns.Name
|
||||
}
|
||||
|
||||
func networkDisabled(c *Container) (bool, error) {
|
||||
if c.config.CreateNetNS {
|
||||
return false, nil
|
||||
}
|
||||
if !c.config.PostConfigureNetNS {
|
||||
return c.state.NetNS != nil, nil
|
||||
return c.state.NetNS != "", nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
@ -625,6 +625,9 @@ func resetState(state *ContainerState) {
|
||||
state.StartupHCPassed = false
|
||||
state.StartupHCSuccessCount = 0
|
||||
state.StartupHCFailureCount = 0
|
||||
state.NetNS = ""
|
||||
state.NetworkStatus = nil
|
||||
state.NetworkStatusOld = nil
|
||||
}
|
||||
|
||||
// Refresh refreshes the container's state after a restart.
|
||||
|
@ -36,7 +36,7 @@ func (c *Container) unmountSHM(path string) error {
|
||||
func (c *Container) prepare() error {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
ctrNS *jailNetNS
|
||||
ctrNS string
|
||||
networkStatus map[string]types.StatusBlock
|
||||
createNetNSErr, mountStorageErr error
|
||||
mountPoint string
|
||||
@ -48,7 +48,7 @@ func (c *Container) prepare() error {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
// Set up network namespace if not already set up
|
||||
noNetNS := c.state.NetNS == nil
|
||||
noNetNS := c.state.NetNS == ""
|
||||
if c.config.CreateNetNS && noNetNS && !c.config.PostConfigureNetNS {
|
||||
ctrNS, networkStatus, createNetNSErr = c.runtime.createNetNS(c)
|
||||
if createNetNSErr != nil {
|
||||
@ -168,8 +168,8 @@ func (c *Container) addNetworkContainer(g *generate.Generator, ctr string) error
|
||||
return fmt.Errorf("retrieving dependency %s of container %s from state: %w", ctr, c.ID(), err)
|
||||
}
|
||||
c.runtime.state.UpdateContainer(nsCtr)
|
||||
if nsCtr.state.NetNS != nil {
|
||||
g.AddAnnotation("org.freebsd.parentJail", nsCtr.state.NetNS.Name)
|
||||
if nsCtr.state.NetNS != "" {
|
||||
g.AddAnnotation("org.freebsd.parentJail", nsCtr.state.NetNS)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -193,7 +193,7 @@ func openDirectory(path string) (fd int, err error) {
|
||||
|
||||
func (c *Container) addNetworkNamespace(g *generate.Generator) error {
|
||||
if c.config.CreateNetNS {
|
||||
if c.state.NetNS == nil {
|
||||
if c.state.NetNS == "" {
|
||||
// This should not happen since network setup
|
||||
// errors should be propagated correctly from
|
||||
// (*Runtime).createNetNS. Check for it anyway
|
||||
@ -201,7 +201,7 @@ func (c *Container) addNetworkNamespace(g *generate.Generator) error {
|
||||
// the past (see #16333).
|
||||
return fmt.Errorf("Inconsistent state: c.config.CreateNetNS is set but c.state.NetNS is nil")
|
||||
}
|
||||
g.AddAnnotation("org.freebsd.parentJail", c.state.NetNS.Name)
|
||||
g.AddAnnotation("org.freebsd.parentJail", c.state.NetNS)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -286,7 +286,7 @@ func (c *Container) isSlirp4netnsIPv6() (bool, error) {
|
||||
|
||||
// check for net=none
|
||||
func (c *Container) hasNetNone() bool {
|
||||
return c.state.NetNS == nil
|
||||
return c.state.NetNS == ""
|
||||
}
|
||||
|
||||
func setVolumeAtime(mountPoint string, st os.FileInfo) error {
|
||||
@ -310,8 +310,8 @@ func (c *Container) getConmonPidFd() int {
|
||||
}
|
||||
|
||||
func (c *Container) jailName() string {
|
||||
if c.state.NetNS != nil {
|
||||
return c.state.NetNS.Name + "." + c.ID()
|
||||
if c.state.NetNS != "" {
|
||||
return c.state.NetNS + "." + c.ID()
|
||||
} else {
|
||||
return c.ID()
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/containers/common/libnetwork/types"
|
||||
"github.com/containers/common/pkg/cgroups"
|
||||
"github.com/containers/common/pkg/config"
|
||||
@ -56,7 +55,7 @@ func (c *Container) unmountSHM(mount string) error {
|
||||
func (c *Container) prepare() error {
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
netNS ns.NetNS
|
||||
netNS string
|
||||
networkStatus map[string]types.StatusBlock
|
||||
createNetNSErr, mountStorageErr error
|
||||
mountPoint string
|
||||
@ -68,7 +67,7 @@ func (c *Container) prepare() error {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
// Set up network namespace if not already set up
|
||||
noNetNS := c.state.NetNS == nil
|
||||
noNetNS := c.state.NetNS == ""
|
||||
if c.config.CreateNetNS && noNetNS && !c.config.PostConfigureNetNS {
|
||||
netNS, networkStatus, createNetNSErr = c.runtime.createNetNS(c)
|
||||
if createNetNSErr != nil {
|
||||
@ -159,7 +158,7 @@ func (c *Container) cleanupNetwork() error {
|
||||
if netDisabled {
|
||||
return nil
|
||||
}
|
||||
if c.state.NetNS == nil {
|
||||
if c.state.NetNS == "" {
|
||||
logrus.Debugf("Network is already cleaned up, skipping...")
|
||||
return nil
|
||||
}
|
||||
@ -169,7 +168,7 @@ func (c *Container) cleanupNetwork() error {
|
||||
logrus.Errorf("Unable to clean up network for container %s: %q", c.ID(), err)
|
||||
}
|
||||
|
||||
c.state.NetNS = nil
|
||||
c.state.NetNS = ""
|
||||
c.state.NetworkStatus = nil
|
||||
c.state.NetworkStatusOld = nil
|
||||
|
||||
@ -411,7 +410,7 @@ func (c *Container) setupRootlessNetwork() error {
|
||||
// set up rootlesskit port forwarder again since it dies when conmon exits
|
||||
// we use rootlesskit port forwarder only as rootless and when bridge network is used
|
||||
if rootless.IsRootless() && c.config.NetMode.IsBridge() && len(c.config.PortMappings) > 0 {
|
||||
err := c.runtime.setupRootlessPortMappingViaRLK(c, c.state.NetNS.Path(), c.state.NetworkStatus)
|
||||
err := c.runtime.setupRootlessPortMappingViaRLK(c, c.state.NetNS, c.state.NetworkStatus)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -430,7 +429,7 @@ func (c *Container) addNetworkNamespace(g *generate.Generator) error {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), c.state.NetNS.Path()); err != nil {
|
||||
if err := g.AddOrReplaceLinuxNamespace(string(spec.NetworkNamespace), c.state.NetNS); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -4,17 +4,9 @@
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
type containerPlatformState struct {
|
||||
// NetNSPath is the path of the container's network namespace
|
||||
// Will only be set if config.CreateNetNS is true, or the container was
|
||||
// told to join another container's network namespace
|
||||
NetNS ns.NetNS `json:"-"`
|
||||
}
|
||||
|
||||
func networkDisabled(c *Container) (bool, error) {
|
||||
if c.config.CreateNetNS {
|
||||
return false, nil
|
||||
|
@ -121,12 +121,12 @@ func (r *Runtime) teardownNetworkBackend(ns string, opts types.NetworkOptions) e
|
||||
// Tear down a container's network backend configuration, but do not tear down the
|
||||
// namespace itself.
|
||||
func (r *Runtime) teardownNetwork(ctr *Container) error {
|
||||
if ctr.state.NetNS == nil {
|
||||
if ctr.state.NetNS == "" {
|
||||
// The container has no network namespace, we're set
|
||||
return nil
|
||||
}
|
||||
|
||||
logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS.Path(), ctr.ID())
|
||||
logrus.Debugf("Tearing down network namespace at %s for container %s", ctr.state.NetNS, ctr.ID())
|
||||
|
||||
networks, err := ctr.networks()
|
||||
if err != nil {
|
||||
@ -136,7 +136,7 @@ func (r *Runtime) teardownNetwork(ctr *Container) error {
|
||||
if !ctr.config.NetMode.IsSlirp4netns() &&
|
||||
!ctr.config.NetMode.IsPasta() && len(networks) > 0 {
|
||||
netOpts := ctr.getNetworkOptions(networks)
|
||||
return r.teardownNetworkBackend(ctr.state.NetNS.Path(), netOpts)
|
||||
return r.teardownNetworkBackend(ctr.state.NetNS, netOpts)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -158,7 +158,7 @@ func isBridgeNetMode(n namespaces.NetworkMode) error {
|
||||
// Only works on containers with bridge networking at present, though in the future we could
|
||||
// extend this to stop + restart slirp4netns
|
||||
func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.StatusBlock, error) {
|
||||
if ctr.state.NetNS == nil {
|
||||
if ctr.state.NetNS == "" {
|
||||
return nil, fmt.Errorf("container %s network is not configured, refusing to reload: %w", ctr.ID(), define.ErrCtrStateInvalid)
|
||||
}
|
||||
if err := isBridgeNetMode(ctr.config.NetMode); err != nil {
|
||||
@ -234,7 +234,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.state.NetNS == nil {
|
||||
if c.state.NetNS == "" {
|
||||
if networkNSPath := c.joinedNetworkNSPath(); networkNSPath != "" {
|
||||
if result, err := c.inspectJoinedNetworkNS(networkNSPath); err == nil {
|
||||
// fallback to dummy configuration
|
||||
@ -262,7 +262,7 @@ func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, e
|
||||
}
|
||||
|
||||
// Set network namespace path
|
||||
settings.SandboxKey = c.state.NetNS.Path()
|
||||
settings.SandboxKey = c.state.NetNS
|
||||
|
||||
netStatus := c.getNetworkStatus()
|
||||
// If this is empty, we're probably slirp4netns
|
||||
@ -394,7 +394,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.state.NetNS == nil {
|
||||
if c.state.NetNS == "" {
|
||||
return fmt.Errorf("unable to disconnect %s from %s: %w", nameOrID, netName, define.ErrNoNetwork)
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ func (c *Container) NetworkDisconnect(nameOrID, netName string, force bool) erro
|
||||
netName: networks[netName],
|
||||
}
|
||||
|
||||
if err := c.runtime.teardownNetworkBackend(c.state.NetNS.Path(), opts); err != nil {
|
||||
if err := c.runtime.teardownNetworkBackend(c.state.NetNS, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -517,7 +517,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, netOpts types.PerNe
|
||||
if !c.ensureState(define.ContainerStateRunning, define.ContainerStateCreated) {
|
||||
return nil
|
||||
}
|
||||
if c.state.NetNS == nil {
|
||||
if c.state.NetNS == "" {
|
||||
return fmt.Errorf("unable to connect %s to %s: %w", nameOrID, netName, define.ErrNoNetwork)
|
||||
}
|
||||
|
||||
@ -530,7 +530,7 @@ func (c *Container) NetworkConnect(nameOrID, netName string, netOpts types.PerNe
|
||||
netName: netOpts,
|
||||
}
|
||||
|
||||
results, err := c.runtime.setUpNetwork(c.state.NetNS.Path(), opts)
|
||||
results, err := c.runtime.setUpNetwork(c.state.NetNS, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ func (r *Runtime) setupNetNS(ctr *Container) error {
|
||||
}
|
||||
|
||||
// Create and configure a new network namespace for a container
|
||||
func (r *Runtime) configureNetNS(ctr *Container, ctrNS *jailNetNS) (status map[string]types.StatusBlock, rerr error) {
|
||||
func (r *Runtime) configureNetNS(ctr *Container, ctrNS string) (status map[string]types.StatusBlock, rerr error) {
|
||||
if err := r.exposeMachinePorts(ctr.config.PortMappings); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -139,7 +139,7 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS *jailNetNS) (status map[s
|
||||
}
|
||||
|
||||
netOpts := ctr.getNetworkOptions(networks)
|
||||
netStatus, err := r.setUpNetwork(ctrNS.Name, netOpts)
|
||||
netStatus, err := r.setUpNetwork(ctrNS, netOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -148,16 +148,16 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS *jailNetNS) (status map[s
|
||||
}
|
||||
|
||||
// Create and configure a new network namespace for a container
|
||||
func (r *Runtime) createNetNS(ctr *Container) (n *jailNetNS, q map[string]types.StatusBlock, retErr error) {
|
||||
func (r *Runtime) createNetNS(ctr *Container) (n string, q map[string]types.StatusBlock, retErr error) {
|
||||
b := make([]byte, 16)
|
||||
_, err := rand.Reader.Read(b)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to generate random vnet name: %v", err)
|
||||
return "", nil, fmt.Errorf("failed to generate random vnet name: %v", err)
|
||||
}
|
||||
ctrNS := &jailNetNS{Name: fmt.Sprintf("vnet-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])}
|
||||
netns := fmt.Sprintf("vnet-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||
|
||||
jconf := jail.NewConfig()
|
||||
jconf.Set("name", ctrNS.Name)
|
||||
jconf.Set("name", netns)
|
||||
jconf.Set("vnet", jail.NEW)
|
||||
jconf.Set("children.max", 1)
|
||||
jconf.Set("persist", true)
|
||||
@ -168,22 +168,22 @@ func (r *Runtime) createNetNS(ctr *Container) (n *jailNetNS, q map[string]types.
|
||||
jconf.Set("securelevel", -1)
|
||||
j, err := jail.Create(jconf)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to create vnet jail %s for container %s: %w", ctrNS.Name, ctr.ID(), err)
|
||||
return "", nil, fmt.Errorf("Failed to create vnet jail %s for container %s: %w", netns, ctr.ID(), err)
|
||||
}
|
||||
|
||||
logrus.Debugf("Created vnet jail %s for container %s", ctrNS.Name, ctr.ID())
|
||||
logrus.Debugf("Created vnet jail %s for container %s", netns, ctr.ID())
|
||||
|
||||
var networkStatus map[string]types.StatusBlock
|
||||
networkStatus, err = r.configureNetNS(ctr, ctrNS)
|
||||
networkStatus, err = r.configureNetNS(ctr, netns)
|
||||
if err != nil {
|
||||
jconf := jail.NewConfig()
|
||||
jconf.Set("persist", false)
|
||||
if err := j.Set(jconf); err != nil {
|
||||
// Log this error and return the error from configureNetNS
|
||||
logrus.Errorf("failed to destroy vnet jail %s: %w", ctrNS.Name, err)
|
||||
logrus.Errorf("failed to destroy vnet jail %s: %w", netns, err)
|
||||
}
|
||||
}
|
||||
return ctrNS, networkStatus, err
|
||||
return netns, networkStatus, err
|
||||
}
|
||||
|
||||
// Tear down a network namespace, undoing all state associated with it.
|
||||
@ -196,28 +196,28 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if ctr.state.NetNS != nil {
|
||||
if ctr.state.NetNS != "" {
|
||||
// Rather than destroying the jail immediately, reset the
|
||||
// persist flag so that it will live until the container is
|
||||
// done.
|
||||
netjail, err := jail.FindByName(ctr.state.NetNS.Name)
|
||||
netjail, err := jail.FindByName(ctr.state.NetNS)
|
||||
if err != nil {
|
||||
return fmt.Errorf("finding network jail %s: %w", ctr.state.NetNS.Name, err)
|
||||
return fmt.Errorf("finding network jail %s: %w", ctr.state.NetNS, err)
|
||||
}
|
||||
jconf := jail.NewConfig()
|
||||
jconf.Set("persist", false)
|
||||
if err := netjail.Set(jconf); err != nil {
|
||||
return fmt.Errorf("releasing network jail %s: %w", ctr.state.NetNS.Name, err)
|
||||
return fmt.Errorf("releasing network jail %s: %w", ctr.state.NetNS, err)
|
||||
}
|
||||
|
||||
ctr.state.NetNS = nil
|
||||
ctr.state.NetNS = ""
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getContainerNetIO(ctr *Container) (*LinkStatistics64, error) {
|
||||
if ctr.state.NetNS == nil {
|
||||
if ctr.state.NetNS == "" {
|
||||
// If NetNS is nil, it was set as none, and no netNS
|
||||
// was set up this is a valid state and thus return no
|
||||
// error, nor any statistics
|
||||
@ -225,7 +225,7 @@ func getContainerNetIO(ctr *Container) (*LinkStatistics64, error) {
|
||||
}
|
||||
|
||||
// FIXME get the interface from the container netstatus
|
||||
cmd := exec.Command("jexec", ctr.state.NetNS.Name, "netstat", "-bI", "eth0", "--libxo", "json")
|
||||
cmd := exec.Command("jexec", ctr.state.NetNS, "netstat", "-bI", "eth0", "--libxo", "json")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -255,11 +255,7 @@ func getContainerNetIO(ctr *Container) (*LinkStatistics64, error) {
|
||||
}
|
||||
|
||||
func (c *Container) joinedNetworkNSPath() string {
|
||||
if c.state.NetNS != nil {
|
||||
return c.state.NetNS.Name
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
return c.state.NetNS
|
||||
}
|
||||
|
||||
func (c *Container) inspectJoinedNetworkNS(networkns string) (q types.StatusBlock, retErr error) {
|
||||
|
@ -281,7 +281,7 @@ func (r *RootlessNetNS) Cleanup(runtime *Runtime) error {
|
||||
// only check for an active netns, we cannot use the container state
|
||||
// because not running does not mean that the netns does not need cleanup
|
||||
// only if the netns is empty we know that we do not need cleanup
|
||||
return c.state.NetNS != nil
|
||||
return c.state.NetNS != ""
|
||||
}
|
||||
ctrs, err := runtime.GetContainers(activeNetns)
|
||||
if err != nil {
|
||||
@ -548,7 +548,7 @@ func (r *Runtime) GetRootlessNetNs(new bool) (*RootlessNetNS, error) {
|
||||
}
|
||||
|
||||
// Create and configure a new network namespace for a container
|
||||
func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[string]types.StatusBlock, rerr error) {
|
||||
func (r *Runtime) configureNetNS(ctr *Container, ctrNS string) (status map[string]types.StatusBlock, rerr error) {
|
||||
if err := r.exposeMachinePorts(ctr.config.PortMappings); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -577,7 +577,7 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[str
|
||||
}
|
||||
|
||||
netOpts := ctr.getNetworkOptions(networks)
|
||||
netStatus, err := r.setUpNetwork(ctrNS.Path(), netOpts)
|
||||
netStatus, err := r.setUpNetwork(ctrNS, netOpts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -587,21 +587,20 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (status map[str
|
||||
// not set up port because they are still active
|
||||
if rootless.IsRootless() && len(ctr.config.PortMappings) > 0 && ctr.getNetworkStatus() == nil {
|
||||
// set up port forwarder for rootless netns
|
||||
netnsPath := ctrNS.Path()
|
||||
// TODO: support slirp4netns port forwarder as well
|
||||
// make sure to fix this in container.handleRestartPolicy() as well
|
||||
// Important we have to call this after r.setUpNetwork() so that
|
||||
// we can use the proper netStatus
|
||||
err = r.setupRootlessPortMappingViaRLK(ctr, netnsPath, netStatus)
|
||||
err = r.setupRootlessPortMappingViaRLK(ctr, ctrNS, netStatus)
|
||||
}
|
||||
return netStatus, err
|
||||
}
|
||||
|
||||
// Create and configure a new network namespace for a container
|
||||
func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q map[string]types.StatusBlock, retErr error) {
|
||||
func (r *Runtime) createNetNS(ctr *Container) (n string, q map[string]types.StatusBlock, retErr error) {
|
||||
ctrNS, err := netns.NewNS()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("creating network namespace for container %s: %w", ctr.ID(), err)
|
||||
return "", nil, fmt.Errorf("creating network namespace for container %s: %w", ctr.ID(), err)
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
@ -617,8 +616,8 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q map[string]types.St
|
||||
logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID())
|
||||
|
||||
var networkStatus map[string]types.StatusBlock
|
||||
networkStatus, err = r.configureNetNS(ctr, ctrNS)
|
||||
return ctrNS, networkStatus, err
|
||||
networkStatus, err = r.configureNetNS(ctr, ctrNS.Path())
|
||||
return ctrNS.Path(), networkStatus, err
|
||||
}
|
||||
|
||||
// Configure the network namespace using the container process
|
||||
@ -652,46 +651,14 @@ func (r *Runtime) setupNetNS(ctr *Container) error {
|
||||
return fmt.Errorf("cannot mount %s: %w", nsPath, err)
|
||||
}
|
||||
|
||||
netNS, err := ns.GetNS(nsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
networkStatus, err := r.configureNetNS(ctr, netNS)
|
||||
networkStatus, err := r.configureNetNS(ctr, nsPath)
|
||||
|
||||
// Assign NetNS attributes to container
|
||||
ctr.state.NetNS = netNS
|
||||
ctr.state.NetNS = nsPath
|
||||
ctr.state.NetworkStatus = networkStatus
|
||||
return err
|
||||
}
|
||||
|
||||
// Join an existing network namespace
|
||||
func joinNetNS(path string) (ns.NetNS, error) {
|
||||
netNS, err := ns.GetNS(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("retrieving network namespace at %s: %w", path, err)
|
||||
}
|
||||
|
||||
return netNS, nil
|
||||
}
|
||||
|
||||
// Close a network namespace.
|
||||
// Differs from teardownNetNS() in that it will not attempt to undo the setup of
|
||||
// the namespace, but will instead only close the open file descriptor
|
||||
func (r *Runtime) closeNetNS(ctr *Container) error {
|
||||
if ctr.state.NetNS == nil {
|
||||
// The container has no network namespace, we're set
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := ctr.state.NetNS.Close(); err != nil {
|
||||
return fmt.Errorf("closing network namespace for container %s: %w", ctr.ID(), err)
|
||||
}
|
||||
|
||||
ctr.state.NetNS = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
@ -705,29 +672,21 @@ func (r *Runtime) teardownNetNS(ctr *Container) error {
|
||||
prevErr := r.teardownNetwork(ctr)
|
||||
|
||||
// First unmount the namespace
|
||||
if err := netns.UnmountNS(ctr.state.NetNS.Path()); err != nil {
|
||||
if err := netns.UnmountNS(ctr.state.NetNS); err != nil {
|
||||
if prevErr != nil {
|
||||
logrus.Error(prevErr)
|
||||
}
|
||||
return fmt.Errorf("unmounting network namespace for container %s: %w", ctr.ID(), err)
|
||||
}
|
||||
|
||||
// Now close the open file descriptor
|
||||
if err := ctr.state.NetNS.Close(); err != nil {
|
||||
if prevErr != nil {
|
||||
logrus.Error(prevErr)
|
||||
}
|
||||
return fmt.Errorf("closing network namespace for container %s: %w", ctr.ID(), err)
|
||||
}
|
||||
|
||||
ctr.state.NetNS = nil
|
||||
ctr.state.NetNS = ""
|
||||
|
||||
return prevErr
|
||||
}
|
||||
|
||||
func getContainerNetNS(ctr *Container) (string, *Container, error) {
|
||||
if ctr.state.NetNS != nil {
|
||||
return ctr.state.NetNS.Path(), nil, nil
|
||||
if ctr.state.NetNS != "" {
|
||||
return ctr.state.NetNS, nil, nil
|
||||
}
|
||||
if ctr.config.NetNsCtr != "" {
|
||||
c, err := ctr.runtime.GetContainer(ctr.config.NetNsCtr)
|
||||
|
@ -12,11 +12,10 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (r *Runtime) setupPasta(ctr *Container, netns ns.NetNS) error {
|
||||
func (r *Runtime) setupPasta(ctr *Container, netns string) error {
|
||||
var NoTCPInitPorts = true
|
||||
var NoUDPInitPorts = true
|
||||
var NoTCPNamespacePorts = true
|
||||
@ -93,7 +92,7 @@ func (r *Runtime) setupPasta(ctr *Container, netns ns.NetNS) error {
|
||||
cmdArgs = append(cmdArgs, "--no-map-gw")
|
||||
}
|
||||
|
||||
cmdArgs = append(cmdArgs, "--netns", netns.Path())
|
||||
cmdArgs = append(cmdArgs, "--netns", netns)
|
||||
|
||||
logrus.Debugf("pasta arguments: %s", strings.Join(cmdArgs, " "))
|
||||
|
||||
|
@ -212,7 +212,7 @@ func createBasicSlirp4netnsCmdArgs(options *slirp4netnsNetworkOptions, features
|
||||
}
|
||||
|
||||
// setupSlirp4netns can be called in rootful as well as in rootless
|
||||
func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error {
|
||||
func (r *Runtime) setupSlirp4netns(ctr *Container, netns string) error {
|
||||
path := r.config.Engine.NetworkCmdPath
|
||||
if path == "" {
|
||||
var err error
|
||||
@ -267,7 +267,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create rootless network sync pipe: %w", err)
|
||||
}
|
||||
netnsPath = netns.Path()
|
||||
netnsPath = netns
|
||||
cmdArgs = append(cmdArgs, "--netns-type=path", netnsPath, "tap0")
|
||||
} else {
|
||||
defer errorhandling.CloseQuiet(ctr.rootlessSlirpSyncR)
|
||||
|
Reference in New Issue
Block a user