aboutsummaryrefslogtreecommitdiffstats
path: root/internal/pkg
diff options
context:
space:
mode:
authorRitu Sood <ritu.sood@intel.com>2019-08-09 11:24:26 -0700
committerRitu Sood <Ritu.Sood@intel.com>2019-08-16 13:06:16 +0000
commita6c37bf8c9c1e9f5072bfc3e43b6ec0061ee2108 (patch)
treeed3530b053600017c5ce5d7a07a04e531c6a98fe /internal/pkg
parent8fe5ed0f2cc522d22d0ca556f48f2e5922c67d3e (diff)
Add CRD Controller for Network
Add CRD controller functionality for Network creation and deletion. Related generated code is uploaded in patch: https://gerrit.opnfv.org/gerrit/#/c/ovn4nfv-k8s-plugin/+/68324/ Change-Id: Ibd3e652edc56aa1084f684438597e1b978977bbf Signed-off-by: Ritu Sood <ritu.sood@intel.com>
Diffstat (limited to 'internal/pkg')
-rw-r--r--internal/pkg/ovn/common.go17
-rw-r--r--internal/pkg/ovn/ovn.go139
-rw-r--r--internal/pkg/ovn/utils.go8
3 files changed, 133 insertions, 31 deletions
diff --git a/internal/pkg/ovn/common.go b/internal/pkg/ovn/common.go
index 60cd202..09d770b 100644
--- a/internal/pkg/ovn/common.go
+++ b/internal/pkg/ovn/common.go
@@ -7,7 +7,6 @@ import (
"math/rand"
"net"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
- "strings"
"time"
)
@@ -65,22 +64,6 @@ func setupDistributedRouter(name string) error {
return nil
}
-// Find if switch exists
-func findLogicalSwitch(name string) bool {
- // get logical switch from OVN
- output, stderr, err := RunOVNNbctl("--data=bare", "--no-heading",
- "--columns=name", "find", "logical_switch", "name="+name)
- if err != nil {
- log.Error(err, "Error in obtaining list of logical switch", "stderr", stderr)
- return false
- }
-
- if strings.Compare(name, output) == 0 {
- return true
- }
- return false
-}
-
// generateMac generates mac address.
func generateMac() string {
prefix := "00:00:00"
diff --git a/internal/pkg/ovn/ovn.go b/internal/pkg/ovn/ovn.go
index dad4641..82fe837 100644
--- a/internal/pkg/ovn/ovn.go
+++ b/internal/pkg/ovn/ovn.go
@@ -5,6 +5,9 @@ import (
"github.com/mitchellh/mapstructure"
kapi "k8s.io/api/core/v1"
kexec "k8s.io/utils/exec"
+ "math/rand"
+ "net"
+ k8sv1alpha1 "ovn4nfv-k8s-plugin/pkg/apis/k8s/v1alpha1"
"strings"
"time"
)
@@ -14,7 +17,8 @@ type Controller struct {
}
const (
- ovn4nfvRouterName = "ovn4nfv-master"
+ ovn4nfvRouterName = "ovn4nfv-master"
+ // Ovn4nfvAnnotationTag tag on already processed Pods
Ovn4nfvAnnotationTag = "k8s.plugin.opnfv.org/ovnInterfaces"
)
@@ -35,12 +39,10 @@ func NewOvnController(exec kexec.Interface) (*Controller, error) {
if exec == nil {
exec = kexec.New()
}
-
if err := SetExec(exec); err != nil {
log.Error(err, "Failed to initialize exec helper")
return nil, err
}
-
if err := SetupOvnUtils(); err != nil {
log.Error(err, "Failed to initialize OVN State")
return nil, err
@@ -71,7 +73,7 @@ func (oc *Controller) AddLogicalPorts(pod *kapi.Pod, ovnNetObjs []map[string]int
}
if _, ok := pod.Annotations[Ovn4nfvAnnotationTag]; ok {
- log.Info("AddLogicalPorts : Pod annotation found")
+ log.V(1).Info("AddLogicalPorts : Pod annotation found")
return
}
@@ -86,7 +88,7 @@ func (oc *Controller) AddLogicalPorts(pod *kapi.Pod, ovnNetObjs []map[string]int
return
}
- if !findLogicalSwitch(ns.Name) {
+ if !oc.FindLogicalSwitch(ns.Name) {
log.Info("Logical Switch not found")
return
}
@@ -111,7 +113,6 @@ func (oc *Controller) AddLogicalPorts(pod *kapi.Pod, ovnNetObjs []map[string]int
}
}
-
outStr = oc.addLogicalPortWithSwitch(pod, ns.Name, ns.IPAddress, ns.MacAddress, ns.Interface, ns.NetType)
if outStr == "" {
return
@@ -131,9 +132,9 @@ func (oc *Controller) AddLogicalPorts(pod *kapi.Pod, ovnNetObjs []map[string]int
return key, value
}
+// DeleteLogicalPorts deletes the OVN ports for the pod
func (oc *Controller) DeleteLogicalPorts(name, namespace string) {
- log.Info("Deleting pod", "name", name)
logicalPort := fmt.Sprintf("%s_%s", namespace, name)
// get the list of logical ports from OVN
@@ -143,12 +144,11 @@ func (oc *Controller) DeleteLogicalPorts(name, namespace string) {
log.Error(err, "Error in obtaining list of logical ports ", "stdout", stdout, "stderr", stderr)
return
}
- log.Info("Deleting", "Existing Ports", stdout)
existingLogicalPorts := strings.Fields(stdout)
for _, existingPort := range existingLogicalPorts {
if strings.Contains(existingPort, logicalPort) {
// found, delete this logical port
- log.Info("Deleting", "existingPort", existingPort)
+ log.V(1).Info("Deleting", "Port", existingPort)
stdout, stderr, err := RunOVNNbctl("--if-exists", "lsp-del",
existingPort)
if err != nil {
@@ -159,11 +159,128 @@ func (oc *Controller) DeleteLogicalPorts(name, namespace string) {
return
}
+// CreateNetwork in OVN controller
+func (oc *Controller) CreateNetwork(cr *k8sv1alpha1.Network) error {
+ var stdout, stderr string
+
+ // Currently only these fields are supported
+ name := cr.Name
+ subnet := cr.Spec.Ipv4Subnets[0].Subnet
+ gatewayIP := cr.Spec.Ipv4Subnets[0].Gateway
+ excludeIps := cr.Spec.Ipv4Subnets[0].ExcludeIps
+
+ output, stderr, err := RunOVNNbctl("--data=bare", "--no-heading",
+ "--columns=name", "find", "logical_switch", "name="+name)
+ if err != nil {
+ log.Error(err, "Error in reading logical switch", "stderr", stderr)
+ return nil
+ }
+
+ if strings.Compare(name, output) == 0 {
+ log.V(1).Info("Logical Switch already exists, delete first to update/recreate", "name", name)
+ return nil
+ }
+
+ _, cidr, err := net.ParseCIDR(subnet)
+ if err != nil {
+ log.Error(err, "ovnNetwork '%s' invalid subnet CIDR", "name", name)
+ return err
+
+ }
+ firstIP := NextIP(cidr.IP)
+ n, _ := cidr.Mask.Size()
+
+ var gatewayIPMask string
+ var gwIP net.IP
+ if gatewayIP != "" {
+ gwIP, _, err = net.ParseCIDR(gatewayIP)
+ if err != nil {
+ // Check if this is a valid IP address
+ gwIP = net.ParseIP(gatewayIP)
+ }
+ }
+ // If no valid Gateway use the first IP address for GatewayIP
+ if gwIP == nil {
+ gatewayIPMask = fmt.Sprintf("%s/%d", firstIP.String(), n)
+ } else {
+ gatewayIPMask = fmt.Sprintf("%s/%d", gwIP.String(), n)
+ }
+
+ // Create a logical switch and set its subnet.
+ if excludeIps != "" {
+ stdout, stderr, err = RunOVNNbctl("--wait=hv", "--", "--may-exist", "ls-add", name, "--", "set", "logical_switch", name, "other-config:subnet="+subnet, "external-ids:gateway_ip="+gatewayIPMask, "other-config:exclude_ips="+excludeIps)
+ } else {
+ stdout, stderr, err = RunOVNNbctl("--wait=hv", "--", "--may-exist", "ls-add", name, "--", "set", "logical_switch", name, "other-config:subnet="+subnet, "external-ids:gateway_ip="+gatewayIPMask)
+ }
+ if err != nil {
+ log.Error(err, "Failed to create a logical switch", "name", name, "stdout", stdout, "stderr", stderr)
+ return err
+ }
+
+ routerMac, stderr, err := RunOVNNbctl("--if-exist", "get", "logical_router_port", "rtos-"+name, "mac")
+ if err != nil {
+ log.Error(err, "Failed to get logical router port", "stderr", stderr)
+ return err
+ }
+ if routerMac == "" {
+ prefix := "00:00:00"
+ newRand := rand.New(rand.NewSource(time.Now().UnixNano()))
+ routerMac = fmt.Sprintf("%s:%02x:%02x:%02x", prefix, newRand.Intn(255), newRand.Intn(255), newRand.Intn(255))
+ }
+
+ _, stderr, err = RunOVNNbctl("--wait=hv", "--may-exist", "lrp-add", ovn4nfvRouterName, "rtos-"+name, routerMac, gatewayIPMask)
+ if err != nil {
+ log.Error(err, "Failed to add logical port to router", "stderr", stderr)
+ return err
+ }
+
+ // Connect the switch to the router.
+ stdout, stderr, err = RunOVNNbctl("--wait=hv", "--", "--may-exist", "lsp-add", name, "stor-"+name, "--", "set", "logical_switch_port", "stor-"+name, "type=router", "options:router-port=rtos-"+name, "addresses="+"\""+routerMac+"\"")
+ if err != nil {
+ log.Error(err, "Failed to add logical port to switch", "stderr", stderr, "stdout", stdout)
+ return err
+ }
+
+ return nil
+}
+
+// DeleteNetwork in OVN controller
+func (oc *Controller) DeleteNetwork(cr *k8sv1alpha1.Network) error {
+
+ name := cr.Name
+ stdout, stderr, err := RunOVNNbctl("--if-exist", "--wait=hv", "lrp-del", "rtos-"+name)
+ if err != nil {
+ log.Error(err, "Failed to delete router port", "name", name, "stdout", stdout, "stderr", stderr)
+ return err
+ }
+ stdout, stderr, err = RunOVNNbctl("--if-exist", "--wait=hv", "ls-del", name)
+ if err != nil {
+ log.Error(err, "Failed to delete switch", "name", name, "stdout", stdout, "stderr", stderr)
+ return err
+ }
+ return nil
+}
+
+// FindLogicalSwitch returns true if switch exists
+func (oc *Controller) FindLogicalSwitch(name string) bool {
+ // get logical switch from OVN
+ output, stderr, err := RunOVNNbctl("--data=bare", "--no-heading",
+ "--columns=name", "find", "logical_switch", "name="+name)
+ if err != nil {
+ log.Error(err, "Error in obtaining list of logical switch", "stderr", stderr)
+ return false
+ }
+ if strings.Compare(name, output) == 0 {
+ return true
+ }
+ return false
+}
+
func (oc *Controller) getGatewayFromSwitch(logicalSwitch string) (string, string, error) {
var gatewayIPMaskStr, stderr string
var ok bool
var err error
- log.Info("getGatewayFromSwitch", "logicalSwitch", logicalSwitch)
+ log.V(1).Info("getGatewayFromSwitch", "logicalSwitch", logicalSwitch)
if gatewayIPMaskStr, ok = oc.gatewayCache[logicalSwitch]; !ok {
gatewayIPMaskStr, stderr, err = RunOVNNbctl("--if-exists",
"get", "logical_switch", logicalSwitch,
@@ -203,7 +320,7 @@ func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipA
return
}
- log.Info("Creating logical port for on switch", "portName", portName, "logicalSwitch", logicalSwitch)
+ log.V(1).Info("Creating logical port for on switch", "portName", portName, "logicalSwitch", logicalSwitch)
if ipAddress != "" && macAddress != "" {
isStaticIP = true
diff --git a/internal/pkg/ovn/utils.go b/internal/pkg/ovn/utils.go
index 2478ac2..615c2f9 100644
--- a/internal/pkg/ovn/utils.go
+++ b/internal/pkg/ovn/utils.go
@@ -84,15 +84,17 @@ func run(cmdPath string, args ...string) (*bytes.Buffer, *bytes.Buffer, error) {
cmd := runner.exec.Command(cmdPath, args...)
cmd.SetStdout(stdout)
cmd.SetStderr(stderr)
- log.Info("exec:", "cmdPath", cmdPath, "args", strings.Join(args, " "))
+ log.V(1).Info("exec:", "cmdPath", cmdPath, "args", strings.Join(args, " "))
err := cmd.Run()
if err != nil {
- log.Error(err, "exec:", "cmdPath", cmdPath, "args", strings.Join(args, " "))
+ log.Error(err, "Error:", "cmdPath", cmdPath, "args", strings.Join(args, " "), "stdout", stdout, "stderr", stderr)
+ } else {
+ log.V(1).Info("output:", "stdout", stdout)
}
return stdout, stderr, err
}
-// RunOVNSbctlWithTimeout runs command via ovn-nbctl with a specific timeout
+// RunOVNNbctlWithTimeout runs command via ovn-nbctl with a specific timeout
func RunOVNNbctlWithTimeout(timeout int, args ...string) (string, string, error) {
var cmdArgs []string
if len(runner.hostIP) > 0 {