Add check support for: bridge, ipvlan, macvlan, p2p, vlan and host-device main plugins

host-local and static ipam plugins
  tuning, bandwidth and portmap meta plugins

  Utility functions created for common PrevResult checking

  Fix windows build
This commit is contained in:
Michael Cambria
2018-12-06 15:42:37 -05:00
parent 82a0651d0a
commit 74a2596573
28 changed files with 3759 additions and 167 deletions

View File

@@ -36,12 +36,10 @@ import (
// TuningConf represents the network tuning configuration.
type TuningConf struct {
types.NetConf
SysCtl map[string]string `json:"sysctl"`
RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
PrevResult *current.Result `json:"-"`
Mac string `json:"mac,omitempty"`
Promisc bool `json:"promisc,omitempty"`
Mtu int `json:"mtu,omitempty"`
SysCtl map[string]string `json:"sysctl"`
Mac string `json:"mac,omitempty"`
Promisc bool `json:"promisc,omitempty"`
Mtu int `json:"mtu,omitempty"`
}
type MACEnvArgs struct {
@@ -68,23 +66,6 @@ func parseConf(data []byte, envArgs string) (*TuningConf, error) {
}
}
// Parse previous result.
if conf.RawPrevResult != nil {
resultBytes, err := json.Marshal(conf.RawPrevResult)
if err != nil {
return nil, fmt.Errorf("could not serialize prevResult: %v", err)
}
res, err := version.NewResult(conf.CNIVersion, resultBytes)
if err != nil {
return nil, fmt.Errorf("could not parse prevResult: %v", err)
}
conf.RawPrevResult = nil
conf.PrevResult, err = current.NewResultFromResult(res)
if err != nil {
return nil, fmt.Errorf("could not convert result to current version: %v", err)
}
}
return &conf, nil
}
@@ -111,7 +92,15 @@ func changeMacAddr(ifName string, newMacAddr string) error {
}
func updateResultsMacAddr(config TuningConf, ifName string, newMacAddr string) {
for _, i := range config.PrevResult.Interfaces {
// Parse previous result.
if config.PrevResult == nil {
return
}
version.ParsePrevResult(&config.NetConf)
result, _ := current.NewResultFromResult(config.PrevResult)
for _, i := range result.Interfaces {
if i.Name == ifName {
i.Mac = newMacAddr
}
@@ -144,6 +133,20 @@ func cmdAdd(args *skel.CmdArgs) error {
return err
}
// Parse previous result.
if tuningConf.RawPrevResult == nil {
return fmt.Errorf("Required prevResult missing")
}
if err := version.ParsePrevResult(&tuningConf.NetConf); err != nil {
return err
}
_, err = current.NewResultFromResult(tuningConf.PrevResult)
if err != nil {
return err
}
// The directory /proc/sys/net is per network namespace. Enter in the
// network namespace before writing on it.
@@ -200,10 +203,80 @@ func cmdDel(args *skel.CmdArgs) error {
func main() {
// TODO: implement plugin version
skel.PluginMain(cmdAdd, cmdGet, cmdDel, version.All, "TODO")
skel.PluginMain(cmdAdd, cmdCheck, cmdDel, version.All, "TODO")
}
func cmdGet(args *skel.CmdArgs) error {
// TODO: implement
return fmt.Errorf("not implemented")
func cmdCheck(args *skel.CmdArgs) error {
tuningConf, err := parseConf(args.StdinData, args.Args)
if err != nil {
return err
}
// Parse previous result.
if tuningConf.RawPrevResult == nil {
return fmt.Errorf("Required prevResult missing")
}
if err := version.ParsePrevResult(&tuningConf.NetConf); err != nil {
return err
}
_, err = current.NewResultFromResult(tuningConf.PrevResult)
if err != nil {
return err
}
err = ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
// Check each configured value vs what's currently in the container
for key, conf_value := range tuningConf.SysCtl {
fileName := filepath.Join("/proc/sys", strings.Replace(key, ".", "/", -1))
fileName = filepath.Clean(fileName)
contents, err := ioutil.ReadFile(fileName)
if err != nil {
return err
}
cur_value := strings.TrimSuffix(string(contents), "\n")
if conf_value != cur_value {
return fmt.Errorf("Error: Tuning configured value of %s is %s, current value is %s", fileName, conf_value, cur_value)
}
}
link, err := netlink.LinkByName(args.IfName)
if err != nil {
return fmt.Errorf("Cannot find container link %v", args.IfName)
}
if tuningConf.Mac != "" {
if tuningConf.Mac != link.Attrs().HardwareAddr.String() {
return fmt.Errorf("Error: Tuning configured Ethernet of %s is %s, current value is %s",
args.IfName, tuningConf.Mac, link.Attrs().HardwareAddr)
}
}
if tuningConf.Promisc {
if link.Attrs().Promisc == 0 {
return fmt.Errorf("Error: Tuning link %s configured promisc is %v, current value is %d",
args.IfName, tuningConf.Promisc, link.Attrs().Promisc)
}
} else {
if link.Attrs().Promisc != 0 {
return fmt.Errorf("Error: Tuning link %s configured promisc is %v, current value is %d",
args.IfName, tuningConf.Promisc, link.Attrs().Promisc)
}
}
if tuningConf.Mtu != 0 {
if tuningConf.Mtu != link.Attrs().MTU {
return fmt.Errorf("Error: Tuning configured MTU of %s is %d, current value is %d",
args.IfName, tuningConf.Mtu, link.Attrs().MTU)
}
}
return nil
})
if err != nil {
return err
}
return nil
}

View File

@@ -15,7 +15,11 @@
package main
import (
"encoding/json"
"fmt"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containernetworking/plugins/pkg/testutils"
@@ -27,6 +31,49 @@ import (
. "github.com/onsi/gomega"
)
func buildOneConfig(name, cniVersion string, orig *TuningConf, prevResult types.Result) (*TuningConf, []byte, error) {
var err error
inject := map[string]interface{}{
"name": name,
"cniVersion": cniVersion,
}
// Add previous plugin result
if prevResult != nil {
inject["prevResult"] = prevResult
}
// Ensure every config uses the same name and version
config := make(map[string]interface{})
confBytes, err := json.Marshal(orig)
if err != nil {
return nil, nil, err
}
err = json.Unmarshal(confBytes, &config)
if err != nil {
return nil, nil, fmt.Errorf("unmarshal existing network bytes: %s", err)
}
for key, value := range inject {
config[key] = value
}
newBytes, err := json.Marshal(config)
if err != nil {
return nil, nil, err
}
conf := &TuningConf{}
if err := json.Unmarshal(newBytes, &conf); err != nil {
return nil, nil, fmt.Errorf("error parsing configuration: %s", err)
}
return conf, newBytes, nil
}
var _ = Describe("tuning plugin", func() {
var originalNS ns.NetNS
const IFNAME string = "dummy0"
@@ -342,4 +389,296 @@ var _ = Describe("tuning plugin", func() {
})
Expect(err).NotTo(HaveOccurred())
})
It("configures and deconfigures promiscuous mode with CNI 0.4.0 ADD/DEL", func() {
conf := []byte(`{
"name": "test",
"type": "iplink",
"cniVersion": "0.4.0",
"promisc": true,
"prevResult": {
"interfaces": [
{"name": "dummy0", "sandbox":"netns"}
],
"ips": [
{
"version": "4",
"address": "10.0.0.2/24",
"gateway": "10.0.0.1",
"interface": 0
}
]
}
}`)
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: originalNS.Path(),
IfName: IFNAME,
StdinData: conf,
}
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
r, _, err := testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
result, err := current.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(result.Interfaces)).To(Equal(1))
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
Expect(len(result.IPs)).To(Equal(1))
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
link, err := netlink.LinkByName(IFNAME)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().Promisc).To(Equal(1))
n := &TuningConf{}
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
cniVersion := "0.4.0"
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
Expect(err).NotTo(HaveOccurred())
args.StdinData = confString
err = testutils.CmdCheckWithArgs(args, func() error {
return cmdCheck(args)
})
Expect(err).NotTo(HaveOccurred())
err = testutils.CmdDel(originalNS.Path(),
args.ContainerID, "", func() error { return cmdDel(args) })
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
It("configures and deconfigures mtu with CNI 0.4.0 ADD/DEL", func() {
conf := []byte(`{
"name": "test",
"type": "iplink",
"cniVersion": "0.4.0",
"mtu": 1454,
"prevResult": {
"interfaces": [
{"name": "dummy0", "sandbox":"netns"}
],
"ips": [
{
"version": "4",
"address": "10.0.0.2/24",
"gateway": "10.0.0.1",
"interface": 0
}
]
}
}`)
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: originalNS.Path(),
IfName: IFNAME,
StdinData: conf,
}
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
r, _, err := testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
result, err := current.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(result.Interfaces)).To(Equal(1))
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
Expect(len(result.IPs)).To(Equal(1))
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
link, err := netlink.LinkByName(IFNAME)
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().MTU).To(Equal(1454))
n := &TuningConf{}
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
cniVersion := "0.4.0"
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
Expect(err).NotTo(HaveOccurred())
args.StdinData = confString
err = testutils.CmdCheckWithArgs(args, func() error {
return cmdCheck(args)
})
Expect(err).NotTo(HaveOccurred())
err = testutils.CmdDel(originalNS.Path(),
args.ContainerID, "", func() error { return cmdDel(args) })
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
It("configures and deconfigures mac address (from conf file) with CNI v4.0 ADD/DEL", func() {
conf := []byte(`{
"name": "test",
"type": "iplink",
"cniVersion": "0.4.0",
"mac": "c2:11:22:33:44:55",
"prevResult": {
"interfaces": [
{"name": "dummy0", "sandbox":"netns"}
],
"ips": [
{
"version": "4",
"address": "10.0.0.2/24",
"gateway": "10.0.0.1",
"interface": 0
}
]
}
}`)
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: originalNS.Path(),
IfName: IFNAME,
StdinData: conf,
}
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
r, _, err := testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
result, err := current.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(result.Interfaces)).To(Equal(1))
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
Expect(len(result.IPs)).To(Equal(1))
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
link, err := netlink.LinkByName(IFNAME)
Expect(err).NotTo(HaveOccurred())
hw, err := net.ParseMAC("c2:11:22:33:44:55")
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
n := &TuningConf{}
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
cniVersion := "0.4.0"
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
Expect(err).NotTo(HaveOccurred())
args.StdinData = confString
err = testutils.CmdCheckWithArgs(args, func() error {
return cmdCheck(args)
})
Expect(err).NotTo(HaveOccurred())
err = testutils.CmdDel(originalNS.Path(),
args.ContainerID, "", func() error { return cmdDel(args) })
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
It("configures and deconfigures mac address (from CNI_ARGS) with CNI v4 ADD/DEL", func() {
conf := []byte(`{
"name": "test",
"type": "iplink",
"cniVersion": "0.4.0",
"prevResult": {
"interfaces": [
{"name": "dummy0", "sandbox":"netns"}
],
"ips": [
{
"version": "4",
"address": "10.0.0.2/24",
"gateway": "10.0.0.1",
"interface": 0
}
]
}
}`)
args := &skel.CmdArgs{
ContainerID: "dummy",
Netns: originalNS.Path(),
IfName: IFNAME,
StdinData: conf,
Args: "IgnoreUnknown=true;MAC=c2:11:22:33:44:66",
}
err := originalNS.Do(func(ns.NetNS) error {
defer GinkgoRecover()
r, _, err := testutils.CmdAddWithArgs(args, func() error {
return cmdAdd(args)
})
Expect(err).NotTo(HaveOccurred())
result, err := current.GetResult(r)
Expect(err).NotTo(HaveOccurred())
Expect(len(result.Interfaces)).To(Equal(1))
Expect(result.Interfaces[0].Name).To(Equal(IFNAME))
Expect(len(result.IPs)).To(Equal(1))
Expect(result.IPs[0].Address.String()).To(Equal("10.0.0.2/24"))
link, err := netlink.LinkByName(IFNAME)
Expect(err).NotTo(HaveOccurred())
hw, err := net.ParseMAC("c2:11:22:33:44:66")
Expect(err).NotTo(HaveOccurred())
Expect(link.Attrs().HardwareAddr).To(Equal(hw))
n := &TuningConf{}
err = json.Unmarshal([]byte(conf), &n)
Expect(err).NotTo(HaveOccurred())
cniVersion := "0.4.0"
_, confString, err := buildOneConfig("testConfig", cniVersion, n, r)
Expect(err).NotTo(HaveOccurred())
args.StdinData = confString
err = testutils.CmdCheckWithArgs(args, func() error {
return cmdCheck(args)
})
Expect(err).NotTo(HaveOccurred())
err = testutils.CmdDel(originalNS.Path(),
args.ContainerID, "", func() error { return cmdDel(args) })
Expect(err).NotTo(HaveOccurred())
return nil
})
Expect(err).NotTo(HaveOccurred())
})
})