https://github.com/containernetworking/cni
func main() {
netdir := os.Getenv(EnvNetDir)
if netdir == "" {
netdir = DefaultNetDir
}
netconf, err := libcni.LoadConfList(netdir, os.Args[2])
var capabilityArgs map[string]interface{}
capabilityArgsValue := os.Getenv(EnvCapabilityArgs)
var cniArgs [][2]string
args := os.Getenv(EnvCNIArgs)
if len(args) > 0 {
cniArgs, err = parseArgs(args)
if err != nil {
exit(err)
}
}
netns := os.Args[3]
cninet := &libcni.CNIConfig{
Path: filepath.SplitList(os.Getenv(EnvCNIPath)),
}
rt := &libcni.RuntimeConf{
ContainerID: "cni",
NetNS: netns,
IfName: "eth0",
Args: cniArgs,
CapabilityArgs: capabilityArgs,
}
switch os.Args[1] {
case CmdAdd:
result, err := cninet.AddNetworkList(netconf, rt)
exit(err)
case CmdDel:
exit(cninet.DelNetworkList(netconf, rt))
}
}
func LoadConfList(dir, name string) (*NetworkConfigList, error) {
files, err := ConfFiles(dir, []string{".conflist"})
if err != nil {
return nil, err
}
sort.Strings(files)
for _, confFile := range files {
conf, err := ConfListFromFile(confFile)
if err != nil {
return nil, err
}
if conf.Name == name {
return conf, nil
}
}
// Try and load a network configuration file (instead of list)
// from the same name, then upconvert.
singleConf, err := LoadConf(dir, name)
if err != nil {
// A little extra logic so the error makes sense
if _, ok := err.(NoConfigsFoundError); len(files) != 0 && ok {
// Config lists found but no config files found
return nil, NotFoundError{dir, name}
}
return nil, err
}
return ConfListFromConf(singleConf)
}
type NetworkConfig struct {
Network *types.NetConf
Bytes []byte
}
type NetworkConfigList struct {
Name string
CNIVersion string
Plugins []*NetworkConfig
Bytes []byte
}
// NetConf describes a network.
type NetConf struct {
CNIVersion string `json:"cniVersion,omitempty"`
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Capabilities map[string]bool `json:"capabilities,omitempty"`
IPAM struct {
Type string `json:"type,omitempty"`
} `json:"ipam,omitempty"`
DNS DNS `json:"dns"`
}
容器运行时信息的数据结构
type RuntimeConf struct {
ContainerID string
NetNS string
IfName string
Args [][2]string
// A dictionary of capability-specific data passed by the runtime
// to plugins as top-level keys in the 'runtimeConfig' dictionary
// of the plugin's stdin data. libcni will ensure that only keys
// in this map which match the capabilities of the plugin are passed
// to the plugin
CapabilityArgs map[string]interface{}
}
// AddNetworkList executes a sequence of plugins with the ADD command
func (c *CNIConfig) AddNetworkList(list *NetworkConfigList, rt *RuntimeConf) (types.Result, error) {
var prevResult types.Result
for _, net := range list.Plugins {
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
if err != nil {
return nil, err
}
newConf, err := buildOneConfig(list, net, prevResult, rt)
if err != nil {
return nil, err
}
prevResult, err = invoke.ExecPluginWithResult(pluginPath, newConf.Bytes, c.args("ADD", rt))
if err != nil {
return nil, err
}
}
return prevResult, nil
}
cni项目提供了一个library,定义了集成cni插件的接口libcni。Interface定义如下:
type CNI interface {
AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (types.Result, error)
DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (types.Result, error)
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
}