8 "github.com/sirupsen/logrus"
9 kapi "k8s.io/api/core/v1"
10 "ovn4nfv-k8s-plugin/internal/pkg/util"
13 func (oc *Controller) syncPods(pods []interface{}) {
15 func (oc *Controller) getGatewayFromSwitch(logicalSwitch string) (string, string, error) {
16 var gatewayIPMaskStr, stderr string
19 logrus.Infof("getGatewayFromSwitch: %s", logicalSwitch)
20 if gatewayIPMaskStr, ok = oc.gatewayCache[logicalSwitch]; !ok {
21 gatewayIPMaskStr, stderr, err = util.RunOVNNbctlUnix("--if-exists",
22 "get", "logical_switch", logicalSwitch,
23 "external_ids:gateway_ip")
25 logrus.Errorf("Failed to get gateway IP: %s, stderr: %q, %v",
26 gatewayIPMaskStr, stderr, err)
29 if gatewayIPMaskStr == "" {
30 return "", "", fmt.Errorf("Empty gateway IP in logical switch %s",
33 oc.gatewayCache[logicalSwitch] = gatewayIPMaskStr
35 gatewayIPMask := strings.Split(gatewayIPMaskStr, "/")
36 if len(gatewayIPMask) != 2 {
37 return "", "", fmt.Errorf("Failed to get IP and Mask from gateway CIDR: %s",
40 gatewayIP := gatewayIPMask[0]
41 mask := gatewayIPMask[1]
42 return gatewayIP, mask, nil
45 func (oc *Controller) deleteLogicalPort(pod *kapi.Pod) {
47 if pod.Spec.HostNetwork {
51 logrus.Infof("Deleting pod: %s", pod.Name)
52 logicalPort := fmt.Sprintf("%s_%s", pod.Namespace, pod.Name)
54 // get the list of logical ports from OVN
55 output, stderr, err := util.RunOVNNbctlUnix("--data=bare", "--no-heading",
56 "--columns=name", "find", "logical_switch_port", "external_ids:pod=true")
58 logrus.Errorf("Error in obtaining list of logical ports, "+
59 "stderr: %q, err: %v",
63 logrus.Infof("Exising Ports : %s. ", output)
64 existingLogicalPorts := strings.Fields(output)
65 for _, existingPort := range existingLogicalPorts {
66 if strings.Contains(existingPort, logicalPort) {
67 // found, delete this logical port
68 logrus.Infof("Deleting: %s. ", existingPort)
69 out, stderr, err := util.RunOVNNbctlUnix("--if-exists", "lsp-del",
72 logrus.Errorf("Error in deleting pod's logical port "+
73 "stdout: %q, stderr: %q err: %v",
76 delete(oc.logicalPortCache, existingPort)
83 func (oc *Controller) addLogicalPortWithSwitch(pod *kapi.Pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType string) (annotation string) {
84 var out, stderr string
87 if pod.Spec.HostNetwork {
91 if !oc.logicalSwitchCache[logicalSwitch] {
92 oc.logicalSwitchCache[logicalSwitch] = true
95 if interfaceName != "" {
96 portName = fmt.Sprintf("%s_%s_%s", pod.Namespace, pod.Name, interfaceName)
101 logrus.Infof("Creating logical port for %s on switch %s", portName, logicalSwitch)
103 if ipAddress != "" && macAddress != "" {
106 if ipAddress != "" && macAddress == "" {
107 macAddress = util.GenerateMac()
112 out, stderr, err = util.RunOVNNbctlUnix("--may-exist", "lsp-add",
113 logicalSwitch, portName, "--", "lsp-set-addresses", portName,
114 fmt.Sprintf("%s %s", macAddress, ipAddress), "--", "--if-exists",
115 "clear", "logical_switch_port", portName, "dynamic_addresses")
117 logrus.Errorf("Failed to add logical port to switch "+
118 "stdout: %q, stderr: %q (%v)",
123 out, stderr, err = util.RunOVNNbctlUnix("--wait=sb", "--",
124 "--may-exist", "lsp-add", logicalSwitch, portName,
125 "--", "lsp-set-addresses",
126 portName, "dynamic", "--", "set",
127 "logical_switch_port", portName,
128 "external-ids:namespace="+pod.Namespace,
129 "external-ids:logical_switch="+logicalSwitch,
130 "external-ids:pod=true")
132 logrus.Errorf("Error while creating logical port %s "+
133 "stdout: %q, stderr: %q (%v)",
134 portName, out, stderr, err)
138 oc.logicalPortCache[portName] = logicalSwitch
143 out, stderr, err = util.RunOVNNbctlUnix("get",
144 "logical_switch_port", portName, "addresses")
146 out, stderr, err = util.RunOVNNbctlUnix("get",
147 "logical_switch_port", portName, "dynamic_addresses")
149 if err == nil && out != "[]" {
153 logrus.Errorf("Error while obtaining addresses for %s - %v", portName,
157 time.Sleep(time.Second)
161 logrus.Errorf("Error while obtaining addresses for %s "+
162 "stdout: %q, stderr: %q, (%v)", portName, out, stderr, err)
166 // static addresses have format ["0a:00:00:00:00:01 192.168.1.3"], while
167 // dynamic addresses have format "0a:00:00:00:00:01 192.168.1.3".
168 outStr := strings.TrimLeft(out, `[`)
169 outStr = strings.TrimRight(outStr, `]`)
170 outStr = strings.Trim(outStr, `"`)
171 addresses := strings.Split(outStr, " ")
172 if len(addresses) != 2 {
173 logrus.Errorf("Error while obtaining addresses for %s", portName)
177 if netType == "virtual" {
178 gatewayIP, mask, err := oc.getGatewayFromSwitch(logicalSwitch)
180 logrus.Errorf("Error obtaining gateway address for switch %s: %s", logicalSwitch, err)
183 annotation = fmt.Sprintf(`{\"ip_address\":\"%s/%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], mask, addresses[0], gatewayIP)
185 annotation = fmt.Sprintf(`{\"ip_address\":\"%s\", \"mac_address\":\"%s\", \"gateway_ip\": \"%s\"}`, addresses[1], addresses[0], "")
191 func findLogicalSwitch(name string) bool {
192 // get logical switch from OVN
193 output, stderr, err := util.RunOVNNbctlUnix("--data=bare", "--no-heading",
194 "--columns=name", "find", "logical_switch", "name="+name)
196 logrus.Errorf("Error in obtaining list of logical switch, "+
197 "stderr: %q, err: %v",
202 if strings.Compare(name, output) == 0 {
205 logrus.Errorf("Error finding Switch %v", name)
210 func (oc *Controller) addLogicalPort(pod *kapi.Pod) {
211 var logicalSwitch string
212 var ipAddress, macAddress, interfaceName, defaultGateway, netType string
214 annotation := pod.Annotations["ovnNetwork"]
216 if annotation != "" {
217 ovnNetObjs, err := oc.parseOvnNetworkObject(annotation)
219 logrus.Errorf("addLogicalPort : Error Parsing OvnNetwork List")
222 var ovnString, outStr string
224 for _, net := range ovnNetObjs {
225 logicalSwitch = net["name"].(string)
226 if !findLogicalSwitch(logicalSwitch) {
227 logrus.Errorf("Logical Switch not found")
230 if _, ok := net["interface"]; ok {
231 interfaceName = net["interface"].(string)
233 logrus.Errorf("Interface name must be provided")
236 if _, ok := net["ipAddress"]; ok {
237 ipAddress = net["ipAddress"].(string)
241 if _, ok := net["macAddress"]; ok {
242 macAddress = net["macAddress"].(string)
246 if _, ok := net["defaultGateway"]; ok {
247 defaultGateway = net["defaultGateway"].(string)
249 defaultGateway = "false"
251 if _, ok := net["netType"]; ok {
252 netType = net["netType"].(string)
256 if netType != "provider" && netType != "virtual" {
257 logrus.Errorf("netType is not supported")
260 if netType == "provider" && ipAddress == "" {
261 logrus.Errorf("ipAddress must be provided for netType Provider")
264 if netType == "provider" && defaultGateway == "true" {
265 logrus.Errorf("defaultGateway not supported for provider network - Use ovnNetworkRoutes to add routes")
268 outStr = oc.addLogicalPortWithSwitch(pod, logicalSwitch, ipAddress, macAddress, interfaceName, netType)
272 last := len(outStr) - 1
273 tmpString := outStr[:last]
274 tmpString += "," + "\\\"defaultGateway\\\":" + "\\\"" + defaultGateway + "\\\""
275 tmpString += "," + "\\\"interface\\\":" + "\\\"" + interfaceName + "\\\"}"
276 ovnString += tmpString
279 last := len(ovnString) - 1
280 ovnString = ovnString[:last]
282 logrus.Debugf("ovnIfaceList - %v", ovnString)
283 err = oc.kube.SetAnnotationOnPod(pod, "ovnIfaceList", ovnString)
285 logrus.Errorf("Failed to set annotation on pod %s - %v", pod.Name, err)