@@ -3,6 +3,7 @@ package controller
33import (
44 "context"
55 "fmt"
6+ "slices"
67 "strings"
78 "time"
89
@@ -177,7 +178,7 @@ func (c *Controller) handleUpdateEndpointSlice(key string) error {
177178 checkIP = util .MasqueradeCheckIP
178179 }
179180 isGenIPPortMapping := ! ignoreHealthCheck || isPreferLocalBackend
180- ipPortMapping , backends = getIPPortMappingBackend (endpointSlices , port , lbVip , checkIP , isGenIPPortMapping )
181+ ipPortMapping , backends = c . getIPPortMappingBackend (endpointSlices , port , lbVip , checkIP , isGenIPPortMapping )
181182 // for performance reason delete lb with no backends
182183 if len (backends ) != 0 {
183184 vip = util .JoinHostPort (lbVip , port .Port )
@@ -353,7 +354,7 @@ func (c *Controller) getHealthCheckVip(subnetName, lbVip string) (string, error)
353354 return checkIP , nil
354355}
355356
356- func getIPPortMappingBackend (endpointSlices []* discoveryv1.EndpointSlice , servicePort v1.ServicePort , serviceIP , checkVip string , isGenIPPortMapping bool ) (map [string ]string , []string ) {
357+ func ( c * Controller ) getIPPortMappingBackend (endpointSlices []* discoveryv1.EndpointSlice , servicePort v1.ServicePort , serviceIP , checkVip string , isGenIPPortMapping bool ) (map [string ]string , []string ) {
357358 var (
358359 ipPortMapping = map [string ]string {}
359360 backends = []string {}
@@ -374,7 +375,13 @@ func getIPPortMappingBackend(endpointSlices []*discoveryv1.EndpointSlice, servic
374375
375376 for _ , endpoint := range endpointSlice .Endpoints {
376377 if isGenIPPortMapping && endpoint .TargetRef .Name != "" {
377- lspName := getEndpointTargetLSP (endpoint .TargetRef .Name , endpoint .TargetRef .Namespace , util .OvnProvider )
378+ lspName , err := c .getEndpointTargetLSP (endpoint .TargetRef .Name , endpoint .TargetRef .Namespace , endpoint .Addresses )
379+ if err != nil {
380+ err := fmt .Errorf ("couldn't get LSP for the endpoint's target: %w" , err )
381+ klog .Error (err )
382+ continue
383+ }
384+
378385 for _ , address := range endpoint .Addresses {
379386 ipPortMapping [address ] = fmt .Sprintf (util .HealthCheckNamedVipTemplate , lspName , checkVip )
380387 }
@@ -401,30 +408,75 @@ func endpointReady(endpoint discoveryv1.Endpoint) bool {
401408 return endpoint .Conditions .Ready == nil || * endpoint .Conditions .Ready
402409}
403410
404- // getEndpointTargetLSP returns the name of the LSP for a given target/namespace.
411+ // getMatchingProviderForAddress returns the provider linked to a subnet in which a particular address is present
412+ func getMatchingProviderForAddress (pod * v1.Pod , providers []string , address string ) string {
413+ if pod .Annotations == nil {
414+ return ""
415+ }
416+
417+ // Find which provider is linked to this address
418+ for _ , provider := range providers {
419+ ipsForProvider , exists := pod .Annotations [fmt .Sprintf (util .IPAddressAnnotationTemplate , provider )]
420+ if ! exists {
421+ continue
422+ }
423+
424+ ips := strings .Split (ipsForProvider , "," )
425+ if slices .Contains (ips , address ) {
426+ return provider
427+ }
428+ }
429+
430+ return ""
431+ }
432+
433+ // getEndpointTargetLSPName returns the name of the LSP for a pod targeted by an endpoint.
405434// A custom provider can be specified if the LSP is within a subnet that doesn't use
406435// the default "ovn" provider.
407- func getEndpointTargetLSP (target , namespace , provider string ) string {
408- // This pod seems to be a VM launcher pod, but we do not use the same syntax for the LSP
409- // of normal pods and for VM pods. We need to retrieve the real name of the VM from
410- // the pod's name to compute the LSP.
411- if strings .HasPrefix (target , util .VMLauncherPrefix ) {
412- target = getVMNameFromLauncherPod (target )
436+ func getEndpointTargetLSPName (pod * v1.Pod , provider string ) string {
437+ // If no provider is specified, use the default one
438+ if provider == "" {
439+ provider = util .OvnProvider
440+ }
441+
442+ target := pod .Name
443+
444+ // If this pod is a VM launcher pod, we need to retrieve the name of the VM. This is necessary
445+ // because we do not use the same syntax for the LSP of normal pods and for VM pods
446+ if vmName , exists := pod .Annotations [fmt .Sprintf (util .VMAnnotationTemplate , provider )]; exists {
447+ target = vmName
413448 }
414449
415- return ovs .PodNameToPortName (target , namespace , provider )
450+ return ovs .PodNameToPortName (target , pod . Namespace , provider )
416451}
417452
418- // getVMNameFromLauncherPod returns the name of a VirtualMachine from the name of its launcher pod (virt-launcher)
419- func getVMNameFromLauncherPod (podName string ) string {
420- // Remove the VM launcher pod prefix
421- vmName := strings .TrimPrefix (podName , util .VMLauncherPrefix )
453+ // getEndpointTargetLSP returns the name of the LSP on which addresses are attached for a specific pod
454+ func (c * Controller ) getEndpointTargetLSP (pod , namespace string , addresses []string ) (string , error ) {
455+ // Retrieve the pod object from its namespace and name
456+ podObj , err := c .podsLister .Pods (namespace ).Get (pod )
457+ if err != nil {
458+ return "" , fmt .Errorf ("failed to get pod %s/%s: %w" , namespace , pod , err )
459+ }
422460
423- // Remove the ID of the pod
424- slice := strings .Split (vmName , "-" )
425- if len (slice ) > 0 {
426- vmName = strings .Join (slice [:len (slice )- 1 ], "-" )
461+ // Get all the networks to which the pod is attached
462+ podNetworks , err := c .getPodKubeovnNets (podObj )
463+ if err != nil {
464+ return "" , fmt .Errorf ("failed to get pod networks: %w" , err )
465+ }
466+
467+ // Retrieve all the providers
468+ var providers []string
469+ for _ , podNetwork := range podNetworks {
470+ providers = append (providers , podNetwork .ProviderName )
471+ }
472+
473+ // Get the first matching provider for any of the address in the endpoint
474+ var provider string
475+ for _ , address := range addresses {
476+ if provider = getMatchingProviderForAddress (podObj , providers , address ); provider != "" {
477+ break
478+ }
427479 }
428480
429- return vmName
481+ return getEndpointTargetLSPName ( podObj , provider ), nil
430482}
0 commit comments