diff options
-rw-r--r-- | cmd/ovn4nfvk8s/ovn4nfvk8s.go | 5 | ||||
-rw-r--r-- | internal/pkg/ovn/common.go | 117 | ||||
-rw-r--r-- | internal/pkg/ovn/ovn.go | 286 | ||||
-rw-r--r-- | internal/pkg/ovn/ovn_test.go | 5 | ||||
-rw-r--r-- | internal/pkg/ovn/pods.go | 292 | ||||
-rw-r--r-- | internal/pkg/ovn/router.go | 50 | ||||
-rw-r--r-- | internal/pkg/ovn/utils.go (renamed from internal/pkg/util/ovs.go) | 10 | ||||
-rw-r--r-- | internal/pkg/util/net.go | 34 |
8 files changed, 353 insertions, 446 deletions
diff --git a/cmd/ovn4nfvk8s/ovn4nfvk8s.go b/cmd/ovn4nfvk8s/ovn4nfvk8s.go index 0c0cc2e..607b07f 100644 --- a/cmd/ovn4nfvk8s/ovn4nfvk8s.go +++ b/cmd/ovn4nfvk8s/ovn4nfvk8s.go @@ -15,7 +15,6 @@ import ( "ovn4nfv-k8s-plugin/internal/pkg/config" "ovn4nfv-k8s-plugin/internal/pkg/factory" "ovn4nfv-k8s-plugin/internal/pkg/ovn" - "ovn4nfv-k8s-plugin/internal/pkg/util" ) func main() { @@ -95,7 +94,7 @@ func runOvnKube(ctx *cli.Context) error { } } - if err = util.SetExec(exec); err != nil { + if err = ovn.SetExec(exec); err != nil { logrus.Errorf("Failed to initialize exec helper: %v", err) return err } @@ -106,7 +105,7 @@ func runOvnKube(ctx *cli.Context) error { } // Create distributed router and gateway for the deployment - err = ovn.SetupMaster("ovn4nfv-master") + err = ovn.SetupDistributedRouter("ovn4nfv-master") if err != nil { logrus.Errorf(err.Error()) panic(err.Error()) diff --git a/internal/pkg/ovn/common.go b/internal/pkg/ovn/common.go index 16923ea..b504440 100644 --- a/internal/pkg/ovn/common.go +++ b/internal/pkg/ovn/common.go @@ -4,77 +4,57 @@ import ( "encoding/json" "fmt" "github.com/sirupsen/logrus" - "strings" + "math/big" + "math/rand" + "net" + "time" ) -func (oc *Controller) getIPFromOvnAnnotation(ovnAnnotation string) string { - if ovnAnnotation == "" { - return "" - } +func SetupDistributedRouter(name string) error { - var ovnAnnotationMap map[string]string - err := json.Unmarshal([]byte(ovnAnnotation), &ovnAnnotationMap) + // Make sure br-int is created. + stdout, stderr, err := RunOVSVsctlUnix("--", "--may-exist", "add-br", "br-int") if err != nil { - logrus.Errorf("Error in json unmarshaling ovn annotation "+ - "(%v)", err) - return "" + logrus.Errorf("Failed to create br-int, stdout: %q, stderr: %q, error: %v", stdout, stderr, err) + return err } - - ipAddressMask := strings.Split(ovnAnnotationMap["ip_address"], "/") - if len(ipAddressMask) != 2 { - logrus.Errorf("Error in splitting ip address") - return "" + // Create a single common distributed router for the cluster. + stdout, stderr, err = RunOVNNbctlUnix("--", "--may-exist", "lr-add", name, "--", "set", "logical_router", name, "external_ids:ovn4nfv-cluster-router=yes") + if err != nil { + logrus.Errorf("Failed to create a single common distributed router for the cluster, stdout: %q, stderr: %q, error: %v", stdout, stderr, err) + return err } - - return ipAddressMask[0] -} - -func (oc *Controller) getMacFromOvnAnnotation(ovnAnnotation string) string { - if ovnAnnotation == "" { - return "" + // Create a logical switch called "ovn4nfv-join" that will be used to connect gateway routers to the distributed router. + // The "ovn4nfv-join" will be allocated IP addresses in the range 100.64.1.0/24. + stdout, stderr, err = RunOVNNbctlUnix("--may-exist", "ls-add", "ovn4nfv-join") + if err != nil { + logrus.Errorf("Failed to create logical switch called \"ovn4nfv-join\", stdout: %q, stderr: %q, error: %v", stdout, stderr, err) + return err } - - var ovnAnnotationMap map[string]string - err := json.Unmarshal([]byte(ovnAnnotation), &ovnAnnotationMap) + // Connect the distributed router to "ovn4nfv-join". + routerMac, stderr, err := RunOVNNbctlUnix("--if-exist", "get", "logical_router_port", "rtoj-"+name, "mac") if err != nil { - logrus.Errorf("Error in json unmarshaling ovn annotation "+ - "(%v)", err) - return "" + logrus.Errorf("Failed to get logical router port rtoj-%v, stderr: %q, error: %v", name, stderr, err) + return err } - - return ovnAnnotationMap["mac_address"] -} - -func stringSliceMembership(slice []string, key string) bool { - for _, val := range slice { - if val == key { - return true + if routerMac == "" { + routerMac = generateMac() + stdout, stderr, err = RunOVNNbctlUnix("--", "--may-exist", "lrp-add", name, "rtoj-"+name, routerMac, "100.64.1.1/24", "--", "set", "logical_router_port", "rtoj-"+name, "external_ids:connect_to_ovn4nfvjoin=yes") + if err != nil { + logrus.Errorf("Failed to add logical router port rtoj-%v, stdout: %q, stderr: %q, error: %v", name, stdout, stderr, err) + return err } } - return false -} - -func (oc *Controller) getNetworkFromOvnAnnotation(ovnAnnotation string) string { - if ovnAnnotation == "" { - logrus.Errorf("getNetworkFromOvnAnnotation ovnAnnotation: %s", ovnAnnotation) - return "" - } - logrus.Infof("getNetworkFromOvnAnnotation ovnAnnotation: %s", ovnAnnotation) - - var ovnAnnotationMap map[string]string - err := json.Unmarshal([]byte(ovnAnnotation), &ovnAnnotationMap) + // Connect the switch "ovn4nfv-join" to the router. + stdout, stderr, err = RunOVNNbctlUnix("--", "--may-exist", "lsp-add", "ovn4nfv-join", "jtor-"+name, "--", "set", "logical_switch_port", "jtor-"+name, "type=router", "options:router-port=rtoj-"+name, "addresses="+"\""+routerMac+"\"") if err != nil { - logrus.Errorf("Error in json unmarshaling ovn annotation "+ - "(%v)", err) - return "" - } - for key, value := range ovnAnnotationMap { - logrus.Infof("getNetworkFromOvnAnnotation %s: %s", key, value) + logrus.Errorf("Failed to add logical switch port to logical router, stdout: %q, stderr: %q, error: %v", stdout, stderr, err) + return err } - return ovnAnnotationMap["name"] + return nil } -func (oc *Controller) parseOvnNetworkObject(ovnnetwork string) ([]map[string]interface{}, error) { +func parseOvnNetworkObject(ovnnetwork string) ([]map[string]interface{}, error) { var ovnNet []map[string]interface{} if ovnnetwork == "" { @@ -87,3 +67,28 @@ func (oc *Controller) parseOvnNetworkObject(ovnnetwork string) ([]map[string]int return ovnNet, nil } + +// generateMac generates mac address. +func generateMac() string { + prefix := "00:00:00" + newRand := rand.New(rand.NewSource(time.Now().UnixNano())) + mac := fmt.Sprintf("%s:%02x:%02x:%02x", prefix, newRand.Intn(255), newRand.Intn(255), newRand.Intn(255)) + return mac +} + +// NextIP returns IP incremented by 1 +func NextIP(ip net.IP) net.IP { + i := ipToInt(ip) + return intToIP(i.Add(i, big.NewInt(1))) +} + +func ipToInt(ip net.IP) *big.Int { + if v := ip.To4(); v != nil { + return big.NewInt(0).SetBytes(v) + } + return big.NewInt(0).SetBytes(ip.To16()) +} + +func intToIP(i *big.Int) net.IP { + return net.IP(i.Bytes()) +} diff --git a/internal/pkg/ovn/ovn.go b/internal/pkg/ovn/ovn.go index ec2ccbd..470416b 100644 --- a/internal/pkg/ovn/ovn.go +++ b/internal/pkg/ovn/ovn.go @@ -2,6 +2,10 @@ package ovn import ( "fmt" + "strings" + "time" + + "github.com/sirupsen/logrus" kapi "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" "k8s.io/client-go/tools/cache" @@ -69,3 +73,285 @@ func (oc *Controller) WatchPods() error { }, oc.syncPods) return err } + +func (oc *Controller) syncPods(pods []interface{}) { +} + +func (oc *Controller) getGatewayFromSwitch(logicalSwitch string) (string, string, error) { + var gatewayIPMaskStr, stderr string + var ok bool + var err error + logrus.Infof("getGatewayFromSwitch: %s", logicalSwitch) + if gatewayIPMaskStr, ok = oc.gatewayCache[logicalSwitch]; !ok { + gatewayIPMaskStr, stderr, err = RunOVNNbctlUnix("--if-exists", + "get", "logical_switch", logicalSwitch, + "external_ids:gateway_ip") + if err != nil { + logrus.Errorf("Failed to get gateway IP: %s, stderr: %q, %v", + gatewayIPMaskStr, stderr, err) + return "", "", err + } + if gatewayIPMaskStr == "" { + return "", "", fmt.Errorf("Empty gateway IP in logical switch %s", + logicalSwitch) + } + oc.gatewayCache[logicalSwitch] = gatewayIPMaskStr + } + gatewayIPMask := strings.Split(gatewayIPMaskStr, "/") + if len(gatewayIPMask) != 2 { + return "", "", fmt.Errorf("Failed to get IP and Mask from gateway CIDR: %s", + gatewayIPMaskStr) + } + gatewayIP := gatewayIPMask[0] + mask := gatewayIPMask[1] + return gatewayIP, mask, nil +} + +func (oc *Controller) deleteLogicalPort(pod *kapi.Pod) { + + if pod.Spec.HostNetwork { + return + } + + logrus.Infof("Deleting pod: %s", pod.Name) + logicalPort := fmt.Sprintf("%s_%s", pod.Namespace, pod.Name) + + // get the list of logical ports from OVN + output, stderr, err := RunOVNNbctlUnix("--data=bare", "--no-heading", + "--columns=name", "find", "logical_switch_port", "external_ids:pod=true") + if err != nil { + logrus.Errorf("Error in obtaining list of logical ports, "+ + "stderr: %q, err: %v", + stderr, err) + return + } + logrus.Infof("Exising Ports : %s. ", output) + existingLogicalPorts := strings.Fields(output) + for _, existingPort := range existingLogicalPorts { + if strings.Contains(existingPort, logicalPort) { + // found, delete this logical port + logrus.Infof("Deleting: %s. ", existingPort) + out, stderr, err := RunOVNNbctlUnix("--if-exists", "lsp-del", + existingPort) + if err != nil { + logrus.Errorf("Error in deleting pod's logical port "+ + "stdout: %q, stderr: %q err: %v", + out, stderr, err) + } else { + delete(oc.logicalPortCache, existingPort) + } + } + } + return +} + +func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType string) (annotation string) { + var out, stderr string + var err error + var isStaticIP bool + if pod.Spec.HostNetwork { + return + } + + if !oc.logicalSwitchCache[logicalSwitch] { + oc.logicalSwitchCache[logicalSwitch] = true + } + var portName string + if interfaceName != "" { + portName = fmt.Sprintf("%s_%s_%s", pod.Namespace, pod.Name, interfaceName) + } else { + return + } + + logrus.Infof("Creating logical port for %s on switch %s", portName, logicalSwitch) + + if ipAddress != "" && macAddress != "" { + isStaticIP = true + } + if ipAddress != "" && macAddress == "" { + macAddress = generateMac() + isStaticIP = true + } + + if isStaticIP { + out, stderr, err = RunOVNNbctlUnix("--may-exist", "lsp-add", + logicalSwitch, portName, "--", "lsp-set-addresses", portName, + fmt.Sprintf("%s %s", macAddress, ipAddress), "--", "--if-exists", + "clear", "logical_switch_port", portName, "dynamic_addresses", "--", "set", + "logical_switch_port", portName, + "external-ids:namespace="+pod.Namespace, + "external-ids:logical_switch="+logicalSwitch, + "external-ids:pod=true") + if err != nil { + logrus.Errorf("Failed to add logical port to switch "+ + "stdout: %q, stderr: %q (%v)", + out, stderr, err) + return + } + } else { + out, stderr, err = RunOVNNbctlUnix("--wait=sb", "--", + "--may-exist", "lsp-add", logicalSwitch, portName, + "--", "lsp-set-addresses", + portName, "dynamic", "--", "set", + "logical_switch_port", portName, + "external-ids:namespace="+pod.Namespace, + "external-ids:logical_switch="+logicalSwitch, + "external-ids:pod=true") + if err != nil { + logrus.Errorf("Error while creating logical port %s "+ + "stdout: %q, stderr: %q (%v)", + portName, out, stderr, err) + return + } + } + oc.logicalPortCache[portName] = logicalSwitch + + count := 30 + for count > 0 { + if isStaticIP { + out, stderr, err = RunOVNNbctlUnix("get", + "logical_switch_port", portName, "addresses") + } else { + out, stderr, err = RunOVNNbctlUnix("get", + "logical_switch_port", portName, "dynamic_addresses") + } + if err == nil && out != "[]" { + break + } + if err != nil { + logrus.Errorf("Error while obtaining addresses for %s - %v", portName, + err) + return + } + time.Sleep(time.Second) + count-- + } + if count == 0 { + logrus.Errorf("Error while obtaining addresses for %s "+ + "stdout: %q, stderr: %q, (%v)", portName, out, stderr, err) + return + } + + // static addresses have format ["0a:00:00:00:00:01 192.168.1.3"], while + // dynamic addresses have format "0a:00:00:00:00:01 192.168.1.3". + outStr := strings.TrimLeft(out, `[`) + outStr = strings.TrimRight(outStr, `]`) + outStr = strings.Trim(outStr, `"`) + addresses := strings.Split(outStr, " ") + if len(addresses) != 2 { + logrus.Errorf("Error while obtaining addresses for %s", portName) + return + } + + if netType == "virtual" { + gatewayIP, mask, err := oc.getGatewayFromSwitch(logicalSwitch) + if err != nil { + logrus.Errorf("Error obtaining gateway address for switch %s: %s", logicalSwitch, err) + return + } + annotation = fmt.Sprintf(`{\"ip_address\":\"%s/%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], mask, addresses[0], gatewayIP) + } else { + annotation = fmt.Sprintf(`{\"ip_address\":\"%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], addresses[0], "") + } + + return annotation +} + +func (oc *Controller) findLogicalSwitch(name string) bool { + // get logical switch from OVN + output, stderr, err := RunOVNNbctlUnix("--data=bare", "--no-heading", + "--columns=name", "find", "logical_switch", "name="+name) + if err != nil { + logrus.Errorf("Error in obtaining list of logical switch, "+ + "stderr: %q, err: %v", + stderr, err) + return false + } + + if strings.Compare(name, output) == 0 { + return true + } else { + logrus.Errorf("Error finding Switch %v", name) + return false + } +} + +func (oc *Controller) addLogicalPort(pod *kapi.Pod) { + var logicalSwitch string + var ipAddress, macAddress, interfaceName, defaultGateway, netType string + + annotation := pod.Annotations["ovnNetwork"] + + if annotation != "" { + ovnNetObjs, err := parseOvnNetworkObject(annotation) + if err != nil { + logrus.Errorf("addLogicalPort : Error Parsing OvnNetwork List") + return + } + var ovnString, outStr string + ovnString = "[" + for _, net := range ovnNetObjs { + logicalSwitch = net["name"].(string) + if !oc.findLogicalSwitch(logicalSwitch) { + logrus.Errorf("Logical Switch not found") + return + } + if _, ok := net["interface"]; ok { + interfaceName = net["interface"].(string) + } else { + logrus.Errorf("Interface name must be provided") + return + } + if _, ok := net["ipAddress"]; ok { + ipAddress = net["ipAddress"].(string) + } else { + ipAddress = "" + } + if _, ok := net["macAddress"]; ok { + macAddress = net["macAddress"].(string) + } else { + macAddress = "" + } + if _, ok := net["defaultGateway"]; ok { + defaultGateway = net["defaultGateway"].(string) + } else { + defaultGateway = "false" + } + if _, ok := net["netType"]; ok { + netType = net["netType"].(string) + } else { + netType = "virtual" + } + if netType != "provider" && netType != "virtual" { + logrus.Errorf("netType is not supported") + return + } + if netType == "provider" && ipAddress == "" { + logrus.Errorf("ipAddress must be provided for netType Provider") + return + } + if netType == "provider" && defaultGateway == "true" { + logrus.Errorf("defaultGateway not supported for provider network - Use ovnNetworkRoutes to add routes") + return + } + outStr = oc.addLogicalPortWithSwitch(pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType) + if outStr == "" { + return + } + last := len(outStr) - 1 + tmpString := outStr[:last] + tmpString += "," + "\\\"defaultGateway\\\":" + "\\\"" + defaultGateway + "\\\"" + tmpString += "," + "\\\"interface\\\":" + "\\\"" + interfaceName + "\\\"}" + ovnString += tmpString + ovnString += "," + } + last := len(ovnString) - 1 + ovnString = ovnString[:last] + ovnString += "]" + logrus.Debugf("ovnIfaceList - %v", ovnString) + err = oc.kube.SetAnnotationOnPod(pod, "ovnIfaceList", ovnString) + if err != nil { + logrus.Errorf("Failed to set annotation on pod %s - %v", pod.Name, err) + } + } +} diff --git a/internal/pkg/ovn/ovn_test.go b/internal/pkg/ovn/ovn_test.go index f974c30..bc33d35 100644 --- a/internal/pkg/ovn/ovn_test.go +++ b/internal/pkg/ovn/ovn_test.go @@ -13,7 +13,6 @@ import ( "ovn4nfv-k8s-plugin/internal/pkg/config" "ovn4nfv-k8s-plugin/internal/pkg/factory" ovntest "ovn4nfv-k8s-plugin/internal/pkg/testing" - "ovn4nfv-k8s-plugin/internal/pkg/util" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -70,7 +69,7 @@ var _ = Describe("Add logical Port", func() { }, } - err := util.SetExec(fexec) + err := SetExec(fexec) Expect(err).NotTo(HaveOccurred()) fakeClient := &fake.Clientset{} @@ -138,7 +137,7 @@ var _ = Describe("Add logical Port", func() { return fmt.Sprintf("/fake-bin/%s", file), nil }, } - err := util.SetExec(fexec) + err := SetExec(fexec) Expect(err).NotTo(HaveOccurred()) fakeClient := &fake.Clientset{} diff --git a/internal/pkg/ovn/pods.go b/internal/pkg/ovn/pods.go deleted file mode 100644 index 6db6b43..0000000 --- a/internal/pkg/ovn/pods.go +++ /dev/null @@ -1,292 +0,0 @@ -package ovn - -import ( - "fmt" - "strings" - "time" - - "github.com/sirupsen/logrus" - kapi "k8s.io/api/core/v1" - "ovn4nfv-k8s-plugin/internal/pkg/util" -) - -func (oc *Controller) syncPods(pods []interface{}) { -} -func (oc *Controller) getGatewayFromSwitch(logicalSwitch string) (string, string, error) { - var gatewayIPMaskStr, stderr string - var ok bool - var err error - logrus.Infof("getGatewayFromSwitch: %s", logicalSwitch) - if gatewayIPMaskStr, ok = oc.gatewayCache[logicalSwitch]; !ok { - gatewayIPMaskStr, stderr, err = util.RunOVNNbctlUnix("--if-exists", - "get", "logical_switch", logicalSwitch, - "external_ids:gateway_ip") - if err != nil { - logrus.Errorf("Failed to get gateway IP: %s, stderr: %q, %v", - gatewayIPMaskStr, stderr, err) - return "", "", err - } - if gatewayIPMaskStr == "" { - return "", "", fmt.Errorf("Empty gateway IP in logical switch %s", - logicalSwitch) - } - oc.gatewayCache[logicalSwitch] = gatewayIPMaskStr - } - gatewayIPMask := strings.Split(gatewayIPMaskStr, "/") - if len(gatewayIPMask) != 2 { - return "", "", fmt.Errorf("Failed to get IP and Mask from gateway CIDR: %s", - gatewayIPMaskStr) - } - gatewayIP := gatewayIPMask[0] - mask := gatewayIPMask[1] - return gatewayIP, mask, nil -} - -func (oc *Controller) deleteLogicalPort(pod *kapi.Pod) { - - if pod.Spec.HostNetwork { - return - } - - logrus.Infof("Deleting pod: %s", pod.Name) - logicalPort := fmt.Sprintf("%s_%s", pod.Namespace, pod.Name) - - // get the list of logical ports from OVN - output, stderr, err := util.RunOVNNbctlUnix("--data=bare", "--no-heading", - "--columns=name", "find", "logical_switch_port", "external_ids:pod=true") - if err != nil { - logrus.Errorf("Error in obtaining list of logical ports, "+ - "stderr: %q, err: %v", - stderr, err) - return - } - logrus.Infof("Exising Ports : %s. ", output) - existingLogicalPorts := strings.Fields(output) - for _, existingPort := range existingLogicalPorts { - if strings.Contains(existingPort, logicalPort) { - // found, delete this logical port - logrus.Infof("Deleting: %s. ", existingPort) - out, stderr, err := util.RunOVNNbctlUnix("--if-exists", "lsp-del", - existingPort) - if err != nil { - logrus.Errorf("Error in deleting pod's logical port "+ - "stdout: %q, stderr: %q err: %v", - out, stderr, err) - } else { - delete(oc.logicalPortCache, existingPort) - } - } - } - return -} - -func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType string) (annotation string) { - var out, stderr string - var err error - var isStaticIP bool - if pod.Spec.HostNetwork { - return - } - - if !oc.logicalSwitchCache[logicalSwitch] { - oc.logicalSwitchCache[logicalSwitch] = true - } - var portName string - if interfaceName != "" { - portName = fmt.Sprintf("%s_%s_%s", pod.Namespace, pod.Name, interfaceName) - } else { - return - } - - logrus.Infof("Creating logical port for %s on switch %s", portName, logicalSwitch) - - if ipAddress != "" && macAddress != "" { - isStaticIP = true - } - if ipAddress != "" && macAddress == "" { - macAddress = util.GenerateMac() - isStaticIP = true - } - - if isStaticIP { - out, stderr, err = util.RunOVNNbctlUnix("--may-exist", "lsp-add", - logicalSwitch, portName, "--", "lsp-set-addresses", portName, - fmt.Sprintf("%s %s", macAddress, ipAddress), "--", "--if-exists", - "clear", "logical_switch_port", portName, "dynamic_addresses", "--", "set", - "logical_switch_port", portName, - "external-ids:namespace="+pod.Namespace, - "external-ids:logical_switch="+logicalSwitch, - "external-ids:pod=true") - if err != nil { - logrus.Errorf("Failed to add logical port to switch "+ - "stdout: %q, stderr: %q (%v)", - out, stderr, err) - return - } - } else { - out, stderr, err = util.RunOVNNbctlUnix("--wait=sb", "--", - "--may-exist", "lsp-add", logicalSwitch, portName, - "--", "lsp-set-addresses", - portName, "dynamic", "--", "set", - "logical_switch_port", portName, - "external-ids:namespace="+pod.Namespace, - "external-ids:logical_switch="+logicalSwitch, - "external-ids:pod=true") - if err != nil { - logrus.Errorf("Error while creating logical port %s "+ - "stdout: %q, stderr: %q (%v)", - portName, out, stderr, err) - return - } - } - oc.logicalPortCache[portName] = logicalSwitch - - count := 30 - for count > 0 { - if isStaticIP { - out, stderr, err = util.RunOVNNbctlUnix("get", - "logical_switch_port", portName, "addresses") - } else { - out, stderr, err = util.RunOVNNbctlUnix("get", - "logical_switch_port", portName, "dynamic_addresses") - } - if err == nil && out != "[]" { - break - } - if err != nil { - logrus.Errorf("Error while obtaining addresses for %s - %v", portName, - err) - return - } - time.Sleep(time.Second) - count-- - } - if count == 0 { - logrus.Errorf("Error while obtaining addresses for %s "+ - "stdout: %q, stderr: %q, (%v)", portName, out, stderr, err) - return - } - - // static addresses have format ["0a:00:00:00:00:01 192.168.1.3"], while - // dynamic addresses have format "0a:00:00:00:00:01 192.168.1.3". - outStr := strings.TrimLeft(out, `[`) - outStr = strings.TrimRight(outStr, `]`) - outStr = strings.Trim(outStr, `"`) - addresses := strings.Split(outStr, " ") - if len(addresses) != 2 { - logrus.Errorf("Error while obtaining addresses for %s", portName) - return - } - - if netType == "virtual" { - gatewayIP, mask, err := oc.getGatewayFromSwitch(logicalSwitch) - if err != nil { - logrus.Errorf("Error obtaining gateway address for switch %s: %s", logicalSwitch, err) - return - } - annotation = fmt.Sprintf(`{\"ip_address\":\"%s/%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], mask, addresses[0], gatewayIP) - } else { - annotation = fmt.Sprintf(`{\"ip_address\":\"%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], addresses[0], "") - } - - return annotation -} - -func findLogicalSwitch(name string) bool { - // get logical switch from OVN - output, stderr, err := util.RunOVNNbctlUnix("--data=bare", "--no-heading", - "--columns=name", "find", "logical_switch", "name="+name) - if err != nil { - logrus.Errorf("Error in obtaining list of logical switch, "+ - "stderr: %q, err: %v", - stderr, err) - return false - } - - if strings.Compare(name, output) == 0 { - return true - } else { - logrus.Errorf("Error finding Switch %v", name) - return false - } -} - -func (oc *Controller) addLogicalPort(pod *kapi.Pod) { - var logicalSwitch string - var ipAddress, macAddress, interfaceName, defaultGateway, netType string - - annotation := pod.Annotations["ovnNetwork"] - - if annotation != "" { - ovnNetObjs, err := oc.parseOvnNetworkObject(annotation) - if err != nil { - logrus.Errorf("addLogicalPort : Error Parsing OvnNetwork List") - return - } - var ovnString, outStr string - ovnString = "[" - for _, net := range ovnNetObjs { - logicalSwitch = net["name"].(string) - if !findLogicalSwitch(logicalSwitch) { - logrus.Errorf("Logical Switch not found") - return - } - if _, ok := net["interface"]; ok { - interfaceName = net["interface"].(string) - } else { - logrus.Errorf("Interface name must be provided") - return - } - if _, ok := net["ipAddress"]; ok { - ipAddress = net["ipAddress"].(string) - } else { - ipAddress = "" - } - if _, ok := net["macAddress"]; ok { - macAddress = net["macAddress"].(string) - } else { - macAddress = "" - } - if _, ok := net["defaultGateway"]; ok { - defaultGateway = net["defaultGateway"].(string) - } else { - defaultGateway = "false" - } - if _, ok := net["netType"]; ok { - netType = net["netType"].(string) - } else { - netType = "virtual" - } - if netType != "provider" && netType != "virtual" { - logrus.Errorf("netType is not supported") - return - } - if netType == "provider" && ipAddress == "" { - logrus.Errorf("ipAddress must be provided for netType Provider") - return - } - if netType == "provider" && defaultGateway == "true" { - logrus.Errorf("defaultGateway not supported for provider network - Use ovnNetworkRoutes to add routes") - return - } - outStr = oc.addLogicalPortWithSwitch(pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType) - if outStr == "" { - return - } - last := len(outStr) - 1 - tmpString := outStr[:last] - tmpString += "," + "\\\"defaultGateway\\\":" + "\\\"" + defaultGateway + "\\\"" - tmpString += "," + "\\\"interface\\\":" + "\\\"" + interfaceName + "\\\"}" - ovnString += tmpString - ovnString += "," - } - last := len(ovnString) - 1 - ovnString = ovnString[:last] - ovnString += "]" - logrus.Debugf("ovnIfaceList - %v", ovnString) - err = oc.kube.SetAnnotationOnPod(pod, "ovnIfaceList", ovnString) - if err != nil { - logrus.Errorf("Failed to set annotation on pod %s - %v", pod.Name, err) - } - } -} diff --git a/internal/pkg/ovn/router.go b/internal/pkg/ovn/router.go deleted file mode 100644 index d98c463..0000000 --- a/internal/pkg/ovn/router.go +++ /dev/null @@ -1,50 +0,0 @@ -package ovn - -import ( - "github.com/sirupsen/logrus" - "ovn4nfv-k8s-plugin/internal/pkg/util" -) - -func SetupMaster(name string) error { - - // Make sure br-int is created. - stdout, stderr, err := util.RunOVSVsctl("--", "--may-exist", "add-br", "br-int") - if err != nil { - logrus.Errorf("Failed to create br-int, stdout: %q, stderr: %q, error: %v", stdout, stderr, err) - return err - } - // Create a single common distributed router for the cluster. - stdout, stderr, err = util.RunOVNNbctlUnix("--", "--may-exist", "lr-add", name, "--", "set", "logical_router", name, "external_ids:ovn4nfv-cluster-router=yes") - if err != nil { - logrus.Errorf("Failed to create a single common distributed router for the cluster, stdout: %q, stderr: %q, error: %v", stdout, stderr, err) - return err - } - // Create a logical switch called "ovn4nfv-join" that will be used to connect gateway routers to the distributed router. - // The "ovn4nfv-join" will be allocated IP addresses in the range 100.64.1.0/24. - stdout, stderr, err = util.RunOVNNbctlUnix("--may-exist", "ls-add", "ovn4nfv-join") - if err != nil { - logrus.Errorf("Failed to create logical switch called \"ovn4nfv-join\", stdout: %q, stderr: %q, error: %v", stdout, stderr, err) - return err - } - // Connect the distributed router to "ovn4nfv-join". - routerMac, stderr, err := util.RunOVNNbctlUnix("--if-exist", "get", "logical_router_port", "rtoj-"+name, "mac") - if err != nil { - logrus.Errorf("Failed to get logical router port rtoj-%v, stderr: %q, error: %v", name, stderr, err) - return err - } - if routerMac == "" { - routerMac = util.GenerateMac() - stdout, stderr, err = util.RunOVNNbctlUnix("--", "--may-exist", "lrp-add", name, "rtoj-"+name, routerMac, "100.64.1.1/24", "--", "set", "logical_router_port", "rtoj-"+name, "external_ids:connect_to_ovn4nfvjoin=yes") - if err != nil { - logrus.Errorf("Failed to add logical router port rtoj-%v, stdout: %q, stderr: %q, error: %v", name, stdout, stderr, err) - return err - } - } - // Connect the switch "ovn4nfv-join" to the router. - stdout, stderr, err = util.RunOVNNbctlUnix("--", "--may-exist", "lsp-add", "ovn4nfv-join", "jtor-"+name, "--", "set", "logical_switch_port", "jtor-"+name, "type=router", "options:router-port=rtoj-"+name, "addresses="+"\""+routerMac+"\"") - if err != nil { - logrus.Errorf("Failed to add logical switch port to logical router, stdout: %q, stderr: %q, error: %v", stdout, stderr, err) - return err - } - return nil -} diff --git a/internal/pkg/util/ovs.go b/internal/pkg/ovn/utils.go index 22b42b9..1700bf8 100644 --- a/internal/pkg/util/ovs.go +++ b/internal/pkg/ovn/utils.go @@ -1,4 +1,4 @@ -package util +package ovn import ( "bytes" @@ -95,14 +95,8 @@ func run(cmdPath string, args ...string) (*bytes.Buffer, *bytes.Buffer, error) { return stdout, stderr, err } -// RunOVSOfctl runs a command via ovs-ofctl. -func RunOVSOfctl(args ...string) (string, string, error) { - stdout, stderr, err := run(runner.ofctlPath, args...) - return strings.Trim(stdout.String(), "\" \n"), stderr.String(), err -} - // RunOVSVsctl runs a command via ovs-vsctl. -func RunOVSVsctl(args ...string) (string, string, error) { +func RunOVSVsctlUnix(args ...string) (string, string, error) { cmdArgs := []string{fmt.Sprintf("--timeout=%d", ovsCommandTimeout)} cmdArgs = append(cmdArgs, args...) stdout, stderr, err := run(runner.vsctlPath, cmdArgs...) diff --git a/internal/pkg/util/net.go b/internal/pkg/util/net.go deleted file mode 100644 index 1ff7fbb..0000000 --- a/internal/pkg/util/net.go +++ /dev/null @@ -1,34 +0,0 @@ -package util - -import ( - "fmt" - "math/big" - "math/rand" - "net" - "time" -) - -// GenerateMac generates mac address. -func GenerateMac() string { - prefix := "00:00:00" - newRand := rand.New(rand.NewSource(time.Now().UnixNano())) - mac := fmt.Sprintf("%s:%02x:%02x:%02x", prefix, newRand.Intn(255), newRand.Intn(255), newRand.Intn(255)) - return mac -} - -// NextIP returns IP incremented by 1 -func NextIP(ip net.IP) net.IP { - i := ipToInt(ip) - return intToIP(i.Add(i, big.NewInt(1))) -} - -func ipToInt(ip net.IP) *big.Int { - if v := ip.To4(); v != nil { - return big.NewInt(0).SetBytes(v) - } - return big.NewInt(0).SetBytes(ip.To16()) -} - -func intToIP(i *big.Int) net.IP { - return net.IP(i.Bytes()) -} |