*: abstract out netns for multiple platforms
Signed-off-by: Vincent Batts <vbatts@hashbangbash.com>
This commit is contained in:
parent
ebdec2ea5b
commit
fb87c2f68b
7 changed files with 218 additions and 128 deletions
151
lib/sandbox/sandbox_linux.go
Normal file
151
lib/sandbox/sandbox_linux.go
Normal file
|
@ -0,0 +1,151 @@
|
|||
// +build linux
|
||||
|
||||
package sandbox
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/containernetworking/plugins/pkg/ns"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/symlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func isNSorErr(nspath string) error {
|
||||
return ns.IsNSorErr(nspath)
|
||||
}
|
||||
|
||||
func newNetNs() (*NetNs, error) {
|
||||
netNS, err := ns.NewNS()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &NetNs{nn: netNS, closed: false}, nil
|
||||
}
|
||||
|
||||
func getNetNs(path string) (*NetNs, error) {
|
||||
return &NetNs{}, nil
|
||||
netNS, err := ns.GetNS(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &NetNs{nn: netNS, closed: false, restored: true}, nil
|
||||
}
|
||||
|
||||
// NetNs handles data pertaining a network namespace
|
||||
type NetNs struct {
|
||||
sync.Mutex
|
||||
nn ns.NetNS
|
||||
symlink *os.File
|
||||
closed bool
|
||||
restored bool
|
||||
}
|
||||
|
||||
func (nns *NetNs) Path() string {
|
||||
return nns.nn.Path()
|
||||
}
|
||||
|
||||
func (nns *NetNs) Close() error {
|
||||
return nns.nn.Close()
|
||||
}
|
||||
|
||||
func (nns *NetNs) Remove() error {
|
||||
nns.Lock()
|
||||
defer nns.Unlock()
|
||||
|
||||
if nns.closed {
|
||||
// netNsRemove() can be called multiple
|
||||
// times without returning an error.
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := nns.symlinkRemove(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := nns.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nns.closed = true
|
||||
|
||||
if nns.restored {
|
||||
// we got namespaces in the form of
|
||||
// /var/run/netns/cni-0d08effa-06eb-a963-f51a-e2b0eceffc5d
|
||||
// but /var/run on most system is symlinked to /run so we first resolve
|
||||
// the symlink and then try and see if it's mounted
|
||||
fp, err := symlink.FollowSymlinkInScope(nns.Path(), "/")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if mounted, err := mount.Mounted(fp); err == nil && mounted {
|
||||
if err := unix.Unmount(fp, unix.MNT_DETACH); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if nns.Path() != "" {
|
||||
if err := os.RemoveAll(nns.Path()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nns *NetNs) symlinkCreate(name string) error {
|
||||
b := make([]byte, 4)
|
||||
_, randErr := rand.Reader.Read(b)
|
||||
if randErr != nil {
|
||||
return randErr
|
||||
}
|
||||
|
||||
nsName := fmt.Sprintf("%s-%x", name, b)
|
||||
symlinkPath := filepath.Join(NsRunDir, nsName)
|
||||
|
||||
if err := os.Symlink(nns.nn.Path(), symlinkPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fd, err := os.Open(symlinkPath)
|
||||
if err != nil {
|
||||
if removeErr := os.RemoveAll(symlinkPath); removeErr != nil {
|
||||
return removeErr
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
nns.symlink = fd
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nns *NetNs) symlinkRemove() error {
|
||||
if err := nns.symlink.Close(); err != nil {
|
||||
return fmt.Errorf("failed to close net ns symlink: %v", err)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(nns.symlink.Name()); err != nil {
|
||||
return fmt.Errorf("failed to remove net ns symlink: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func hostNetNsPath() (string, error) {
|
||||
netNS, err := ns.GetCurrentNS()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
defer netNS.Close()
|
||||
return netNS.Path(), nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue