Add Routes to Pod 46/67046/1
authorRitu Sood <ritu.sood@intel.com>
Sun, 17 Feb 2019 13:58:57 +0000 (05:58 -0800)
committerRitu Sood <ritu.sood@intel.com>
Sun, 17 Feb 2019 14:01:05 +0000 (06:01 -0800)
Based on Pod annotations list ovnNetworkRoutes
routes are added to the Pod namespace

Change-Id: If6b8b6375d798dcbd45e51ccd5adae4b24369c5c
Signed-off-by: Ritu Sood <ritu.sood@intel.com>
cmd/ovn4nfvk8s-cni/app/helper_linux.go
cmd/ovn4nfvk8s-cni/ovn4nfvk8s-cni.go
cmd/ovn4nfvk8s-cni/ovn4nfvk8s-cni_test.go

index 1a98a61..fc4fd94 100644 (file)
@@ -143,6 +143,32 @@ var ConfigureInterface = func(args *skel.CmdArgs, namespace, podName, macAddress
        return []*current.Interface{hostIface, contIface}, nil
 }
 
+func setupRoute(netns ns.NetNS, dst, gw, dev string) error {
+        // Add Route to the namespace
+        err := netns.Do(func(_ ns.NetNS) error {
+                dstAddr, dstAddrNet, _ := net.ParseCIDR(dst)
+                ipNet := net.IPNet{IP: dstAddr, Mask: dstAddrNet.Mask}
+                link, err := netlink.LinkByName(dev)
+                err = ip.AddRoute(&ipNet, net.ParseIP(gw), link)
+                if err != nil {
+                        logrus.Errorf("ip.AddRoute failed %v dst %v gw %v", err, dst, gw)
+                }
+                return err
+        })
+        return err
+}
+
+// ConfigureRoute sets up the container routes
+var ConfigureRoute = func(args *skel.CmdArgs, dst, gw, dev string) error {
+        netns, err := ns.GetNS(args.Netns)
+        if err != nil {
+                return fmt.Errorf("failed to open netns %q: %v", args.Netns, err)
+        }
+        defer netns.Close()
+        err = setupRoute(netns, dst, gw, dev)
+        return err
+}
+
 // PlatformSpecificCleanup deletes the OVS port
 func PlatformSpecificCleanup(ifaceName string) (bool, error) {
        done := false
index 923363b..2722eaa 100644 (file)
@@ -196,6 +196,53 @@ func addMultipleInterfaces(args *skel.CmdArgs, ovnAnnotation, namespace, podName
        return dstResult
 }
 
+func addRoutes(args *skel.CmdArgs, ovnAnnotation string, dstResult types.Result) types.Result {
+        logrus.Infof("ovn4nfvk8s-cni: addRoutes ")
+
+        var ovnAnnotatedMap []map[string]string
+        ovnAnnotatedMap, err := parseOvnNetworkObject(ovnAnnotation)
+        if err != nil {
+                logrus.Errorf("addLogicalPort : Error Parsing Ovn Route List %v", err)
+                return nil
+        }
+
+        var result types.Result
+        var routes []*types.Route
+        for _, ovnNet := range ovnAnnotatedMap {
+                dst := ovnNet["dst"]
+                gw := ovnNet["gw"]
+                dev := ovnNet["dev"]
+                if dst == "" || gw == "" || dev == "" {
+                        logrus.Errorf("failed in pod annotation key extract")
+                        return nil
+                }
+                err = app.ConfigureRoute(args, dst, gw, dev)
+                if err != nil {
+                        logrus.Errorf("Failed to configure interface in pod: %v", err)
+                        return nil
+                }
+                dstAddr, dstAddrNet, _ := net.ParseCIDR(dst)
+                routes = append(routes, &types.Route{
+                        Dst: net.IPNet{IP: dstAddr, Mask: dstAddrNet.Mask},
+                        GW:  net.ParseIP(gw),
+                })
+        }
+
+        result = &current.Result{
+                Routes: routes,
+        }
+        // Build the result structure to pass back to the runtime
+        dstResult, err = mergeWithResult(result, dstResult)
+        if err != nil {
+                logrus.Errorf("Failed to merge results: %v", err)
+                return nil
+        }
+        logrus.Infof("addRoutes:  %s", prettyPrint(dstResult))
+        return dstResult
+
+}
+
+
 func cmdAdd(args *skel.CmdArgs) error {
        logrus.Infof("ovn4nfvk8s-cni: cmdAdd ")
        conf := &types.NetConf{}
@@ -243,6 +290,13 @@ func cmdAdd(args *skel.CmdArgs) error {
                return fmt.Errorf("Error while obtaining pod annotations")
        }
        result := addMultipleInterfaces(args, ovnAnnotation, namespace, podName)
+        // Add Routes to the pod if annotation found for routes
+        ovnRouteAnnotation, ok := annotation["ovnNetworkRoutes"]
+        if ok {
+                logrus.Infof("ovn4nfvk8s-cni: ovnNetworkRoutes Annotation Found %+v", ovnRouteAnnotation)
+                result = addRoutes(args, ovnRouteAnnotation, result)
+        }
+
        return result.Print()
 }
 
index d5b7b6b..e1190ca 100644 (file)
@@ -3,9 +3,14 @@
 package main
 
 import (
+        "encoding/json"
+
        "github.com/containernetworking/cni/pkg/skel"
+        "github.com/containernetworking/cni/pkg/types"
        "github.com/containernetworking/cni/pkg/types/current"
+        "net"
        "ovn4nfv-k8s-plugin/cmd/ovn4nfvk8s-cni/app"
+        "reflect"
        "testing"
 )
 
@@ -21,13 +26,19 @@ func TestAddMultipleInterfaces(t *testing.T) {
                                Sandbox: "102103104",
                        }}, nil
        }
-       args := &skel.CmdArgs{"102103104", "default", "eth0", "", "", nil}
+        oldConfigureRoute := app.ConfigureRoute
+        defer func() { app.ConfigureRoute = oldConfigureRoute }()
+        app.ConfigureRoute = func(args *skel.CmdArgs, dst, gw, dev string) error {
+                return nil
+        }
 
+       args := &skel.CmdArgs{"102103104", "default", "eth0", "", "", nil}
        ovnAnnotation := "[{\"ip_address\":\"172.16.24.2/24\", \"mac_address\":\"0a:00:00:00:00:0c\", \"gateway_ip\": \"172.16.24.1\",\"interface\":\"net0\"}] "
        result := addMultipleInterfaces(args, ovnAnnotation, "default", "pod")
        if result == nil {
                t.Errorf("Failed addMultipleInterfaces %+v", ovnAnnotation)
        }
+        resultSave := result
        ovnAnnotation = "[{\"ip_address\":\"172.16.24.2/24\", \"mac_address\":\"0a:00:00:00:00:0c\", \"gateway_ip\": \"172.16.24.1\",\"defaultGateway\":\"true\",\"interface\":\"net0\"}] "
        result = addMultipleInterfaces(args, ovnAnnotation, "default", "pod")
        if result == nil {
@@ -53,4 +64,63 @@ func TestAddMultipleInterfaces(t *testing.T) {
        if result == nil {
                t.Errorf("Failed addMultipleInterfaces %+v", ovnAnnotation)
        }
+       // Test add route feature
+        ovnRoutesAnnotation := "[{ \"dst\": \"172.16.29.0/24\", \"gw\": \"172.16.24.1\", \"dev\": \"eth0\" }]"
+        result = addRoutes(args, ovnRoutesAnnotation, resultSave)
+        if result == nil {
+                t.Errorf("Failed addRoutes %+v", ovnRoutesAnnotation)
+        }
+
+        ovnRoutesAnnotation = "[{ \"dst\": \"172.16.30.0/24\", \"gw\": \"172.16.25.1\", \"dev\": \"eth0\"}, { \"dst\": \"172.16.31.0/24\", \"gw\": \"172.16.26.1\", \"dev\": \"eth1\" }]"
+        result = addRoutes(args, ovnRoutesAnnotation, resultSave)
+        if result == nil {
+                t.Errorf("Failed addRoutes %+v", ovnRoutesAnnotation)
+        }
+        newResult, err := current.NewResultFromResult(result)
+        if err != nil {
+                t.Errorf("Failed addMultipleInterfaces %+v", newResult)
+        }
+        addr1, addrNet1, _ := net.ParseCIDR("172.16.24.2/24")
+        addr2, addrNet2, _ := net.ParseCIDR("172.16.29.0/24")
+        addr3, addrNet3, _ := net.ParseCIDR("172.16.30.0/24")
+        addr4, addrNet4, _ := net.ParseCIDR("172.16.31.0/24")
+        expectedResult := &current.Result{
+                CNIVersion: "0.3.1",
+                Interfaces: []*current.Interface{
+                        {
+                                Name:    "pod",
+                                Mac:     "0a:00:00:00:00:0c",
+                                Sandbox: "102103104",
+                        },
+                },
+                IPs: []*current.IPConfig{
+                        {
+                                Version:   "4",
+                                Interface: current.Int(1),
+                                Address:   net.IPNet{IP: addr1, Mask: addrNet1.Mask},
+                                Gateway:   net.ParseIP("172.16.24.1"),
+                        },
+                },
+                Routes: []*types.Route{
+                        {
+                                Dst: net.IPNet{IP: addr2, Mask: addrNet2.Mask},
+                                GW:  net.ParseIP("172.16.24.1"),
+                        },
+                        {
+                                Dst: net.IPNet{IP: addr3, Mask: addrNet3.Mask},
+                                GW:  net.ParseIP("172.16.25.1"),
+                        },
+                        {
+                                Dst: net.IPNet{IP: addr4, Mask: addrNet4.Mask},
+                                GW:  net.ParseIP("172.16.26.1"),
+                        },
+                },
+                DNS: types.DNS{},
+        }
+        jsonBytes1, err := json.Marshal(newResult.Routes)
+        jsonBytes2, err := json.Marshal(expectedResult.Routes)
+        if !reflect.DeepEqual(jsonBytes1, jsonBytes2) {
+                t.Errorf("Routes are not correct")
+        }
+
 }