golang create netns

2022-12-18  本文已影响0人  cloudFans


# cat operate-netns.go
package main

import (
        "fmt"
        "log"
        "os"
        "path"
        "runtime"

        "github.com/containernetworking/plugins/pkg/ns"
        "golang.org/x/sys/unix"
)

const (
        bindMountPath = "/run/netns" /* Bind mount path for named netns */
)

// NsHandle is a handle to a network namespace. It can be cast directly
// to an int and used as a file descriptor.
type NsHandle int

// None gets an empty (closed) NsHandle.
func ClosedNs() NsHandle {
        return NsHandle(-1)
}

// GetFromPath gets a handle to a network namespace
// identified by the path
func GetNsFromPath(path string) (NsHandle, error) {
        fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0)
        if err != nil {
                return -1, err
        }
        return NsHandle(fd), nil
}

// GetFromThread gets a handle to the network namespace of a given pid and tid.
func GetNsFromThread(pid, tid int) (NsHandle, error) {
        return GetNsFromPath(fmt.Sprintf("/proc/%d/task/%d/ns/net", pid, tid))
}

// Get gets a handle to the current threads network namespace.
func GetNs() (NsHandle, error) {
        return GetNsFromThread(os.Getpid(), unix.Gettid())
}

// New creates a new network namespace, sets it as current and returns
// a handle to it.
func newNs() (ns NsHandle, err error) {
        if err := unix.Unshare(unix.CLONE_NEWNET); err != nil {
                return -1, err
        }
        return GetNs()
}

// NewNamed creates a new named network namespace, sets it as current,
// and returns a handle to it
func NewNamedNs(name string) (NsHandle, error) {
        if _, err := os.Stat(bindMountPath); os.IsNotExist(err) {
                err = os.MkdirAll(bindMountPath, 0755)
                if err != nil {
                        return ClosedNs(), err
                }
        }

        newNs, err := newNs()
        if err != nil {
                return ClosedNs(), err
        }

        namedPath := path.Join(bindMountPath, name)

        f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444)
        if err != nil {
                return ClosedNs(), err
        }
        f.Close()

        nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), unix.Gettid())
        err = unix.Mount(nsPath, namedPath, "bind", unix.MS_BIND, "")
        if err != nil {
                return ClosedNs(), err
        }

        return newNs, nil
}

// DeleteNamed deletes a named network namespace
func DeleteNamedNs(name string) error {
        namedPath := path.Join(bindMountPath, name)

        err := unix.Unmount(namedPath, unix.MNT_DETACH)
        if err != nil {
                return err
        }

        return os.Remove(namedPath)
}

// GetFromName gets a handle to a named network namespace such as one
// created by `ip netns add`.
func GetNsFromName(name string) (NsHandle, error) {
        return GetNsFromPath(fmt.Sprintf("/var/run/netns/%s", name))
}

const (
        NSName = "ovnext0"
        NsPath = "/var/run/netns/ovnext0"
)

func Error(e error) {
        if e != nil {
                log.Fatalln(e)
        }
}

func SetupNetNamespace() *NsHandle {
        runtime.LockOSThread()
        defer runtime.UnlockOSThread()
        log.Println("SetupNetNamespace...running")
        _, err := GetNsFromName(NSName)
        if err == nil {
                log.Printf("%s net ns is exists. Delete netns %s\n", NSName, NSName)
        }
        newns, err := NewNamedNs(NSName)
        Error(err)
        log.Println("SetupNetNamespace...done")

        podNS, err := ns.GetNS(NsPath)
        if err != nil {
                log.Println("SetupNetNamespace...done")
                Error(err)
        }
        log.Println("PodNs: ", podNS)
        return &newns
}

func main() {
        ns := SetupNetNamespace()
        log.Println("added ns: ", ns)
}


上一篇下一篇

猜你喜欢

热点阅读