package glue import ( "fmt" "os" "sort" "strings" "github.com/containernetworking/cni/libcni" "github.com/containernetworking/cni/pkg/types" ) var ( cniDir = "/etc/docker/cni/%s.d" cniPath = []string{ "/var/lib/cni/bin", "/usr/local/sbin", "/usr/sbin", "/sbin", "/usr/local/bin", "/usr/bin", "/bin", } ) type CNIExec struct { confs []*libcni.NetworkConfig runtimeConf libcni.RuntimeConf cninet libcni.CNIConfig } func (c *CNIExec) Add(index int) (*types.Result, error) { return c.cninet.AddNetwork(c.confs[index], &c.runtimeConf) } func (c *CNIExec) Del(index int) error { rt := c.runtimeConf rt.NetNS = "" return c.cninet.DelNetwork(c.confs[index], &rt) } func NewCNIExec(state *DockerPluginState) (*CNIExec, error) { if state.HostConfig.NetworkMode.IsContainer() || state.HostConfig.NetworkMode.IsHost() || state.HostConfig.NetworkMode.IsNone() { return &CNIExec{}, nil } c := &CNIExec{ runtimeConf: libcni.RuntimeConf{ ContainerID: state.ContainerID, NetNS: fmt.Sprintf("/proc/%d/ns/net", state.State.Pid), IfName: "eth0", Args: [][2]string{ {"IgnoreUnknown", "1"}, {"DOCKER", "true"}, }, }, cninet: libcni.CNIConfig{ Path: cniPath, }, } network := state.HostConfig.NetworkMode.NetworkName() if network == "" { network = "default" } dir := fmt.Sprintf(cniDir, network) files, err := libcni.ConfFiles(dir) if err != nil { return nil, err } sort.Strings(files) os.Setenv("PATH", strings.Join(cniPath, ":")) for _, file := range files { netConf, err := libcni.ConfFromFile(file) if err != nil { return nil, err } c.confs = append(c.confs, netConf) } return c, nil } func CNIAdd(state *DockerPluginState) (*types.Result, error) { c, err := NewCNIExec(state) if err != nil { return nil, err } var result *types.Result for i := range c.confs { pluginResult, err := c.Add(i) if err != nil { return nil, err } if pluginResult.IP4 != nil { result = pluginResult } } return result, nil } func CNIDel(state *DockerPluginState) error { c, err := NewCNIExec(state) if err != nil { return err } var lastErr error for i := len(c.confs) - 1; i >= 0; i-- { if err := c.Del(i); err != nil { lastErr = err } } return lastErr }