@@ -33,6 +33,7 @@ import (
3333 powerVSUtils "github.com/ppc64le-cloud/powervs-utils"
3434 corev1 "k8s.io/api/core/v1"
3535 "k8s.io/apimachinery/pkg/types"
36+ "k8s.io/client-go/tools/cache"
3637 "k8s.io/klog/v2/klogr"
3738 "k8s.io/utils/pointer"
3839 capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -58,6 +59,7 @@ type PowerVSMachineScopeParams struct {
5859 IBMPowerVSCluster * infrav1beta1.IBMPowerVSCluster
5960 IBMPowerVSMachine * infrav1beta1.IBMPowerVSMachine
6061 IBMPowerVSImage * infrav1beta1.IBMPowerVSImage
62+ DHCPIPCacheStore cache.Store
6163}
6264
6365// PowerVSMachineScope defines a scope defined around a Power VS Machine.
@@ -72,6 +74,7 @@ type PowerVSMachineScope struct {
7274 IBMPowerVSCluster * infrav1beta1.IBMPowerVSCluster
7375 IBMPowerVSMachine * infrav1beta1.IBMPowerVSMachine
7476 IBMPowerVSImage * infrav1beta1.IBMPowerVSImage
77+ DHCPIPCacheStore cache.Store
7578}
7679
7780// NewPowerVSMachineScope creates a new PowerVSMachineScope from the supplied parameters.
@@ -152,7 +155,7 @@ func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (scope *PowerVSMac
152155 scope .SetRegion (region )
153156 scope .SetZone (* res .RegionID )
154157
155- options := powervs.ServiceOptions {
158+ serviceOptions := powervs.ServiceOptions {
156159 IBMPIOptions : & ibmpisession.IBMPIOptions {
157160 Debug : params .Logger .V (DEBUGLEVEL ).Enabled (),
158161 UserAccount : account ,
@@ -161,13 +164,13 @@ func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (scope *PowerVSMac
161164 },
162165 CloudInstanceID : m .Spec .ServiceInstanceID ,
163166 }
164- c , err := powervs .NewService (options )
167+ c , err := powervs .NewService (serviceOptions )
165168 if err != nil {
166169 err = fmt .Errorf ("failed to create PowerVS service" )
167170 return
168171 }
169172 scope .IBMPowerVSClient = c
170-
173+ scope . DHCPIPCacheStore = params . DHCPIPCacheStore
171174 return scope , nil
172175}
173176
@@ -417,6 +420,97 @@ func (m *PowerVSMachineScope) SetAddresses(instance *models.PVMInstance) {
417420 }
418421 }
419422 m .IBMPowerVSMachine .Status .Addresses = addresses
423+ if len (addresses ) > 2 {
424+ // If the address length is more than 2 means either NodeInternalIP or NodeExternalIP is updated so return
425+ return
426+ }
427+ // In this case there is no IP found under instance.Networks, So try to fetch the IP from cache or DHCP server
428+ // Look for DHCP IP from the cache
429+ obj , exists , err := m .DHCPIPCacheStore .GetByKey (* instance .ServerName )
430+ if err != nil {
431+ m .Error (err , "failed to fetch the DHCP IP address from cache store" , "VM" , * instance .ServerName )
432+ }
433+ if exists {
434+ m .Info ("found IP for VM from DHCP cache" , "IP" , obj .(powervs.VMip ).IP , "VM" , * instance .ServerName )
435+ addresses = append (addresses , corev1.NodeAddress {
436+ Type : corev1 .NodeInternalIP ,
437+ Address : obj .(powervs.VMip ).IP ,
438+ })
439+ m .IBMPowerVSMachine .Status .Addresses = addresses
440+ return
441+ }
442+ // Fetch the VM network ID
443+ networkID , err := getNetworkID (m .IBMPowerVSMachine .Spec .Network , m )
444+ if err != nil {
445+ m .Error (err , "failed to fetch network id from network resource" , "VM" , * instance .ServerName )
446+ return
447+ }
448+ // Fetch the details of the network attached to the VM
449+ var pvmNetwork * models.PVMInstanceNetwork
450+ for _ , network := range instance .Networks {
451+ if network .NetworkID == * networkID {
452+ pvmNetwork = network
453+ m .Info ("found network attached to VM" , "Network ID" , network .NetworkID , "VM" , * instance .ServerName )
454+ }
455+ }
456+ if pvmNetwork == nil {
457+ m .Info ("failed to get network attached to VM" , "VM" , * instance .ServerName , "Network ID" , * networkID )
458+ return
459+ }
460+ // Get all the DHCP servers
461+ dhcpServer , err := m .IBMPowerVSClient .GetAllDHCPServers ()
462+ if err != nil {
463+ m .Error (err , "failed to get DHCP server" )
464+ return
465+ }
466+ // Get the Details of DHCP server associated with the network
467+ var dhcpServerDetails * models.DHCPServerDetail
468+ for _ , server := range dhcpServer {
469+ if * server .Network .ID == * networkID {
470+ m .Info ("found DHCP server for network" , "DHCP server ID" , * server .ID , "network ID" , * networkID )
471+ dhcpServerDetails , err = m .IBMPowerVSClient .GetDHCPServer (* server .ID )
472+ if err != nil {
473+ m .Error (err , "failed to get DHCP server details" , "DHCP server ID" , * server .ID )
474+ return
475+ }
476+ break
477+ }
478+ }
479+ if dhcpServerDetails == nil {
480+ errStr := fmt .Errorf ("DHCP server details is nil" )
481+ m .Error (errStr , "DHCP server associated with network is nil" , "Network ID" , * networkID )
482+ return
483+ }
484+
485+ // Fetch the VM IP using VM's mac from DHCP server lease
486+ var internalIP * string
487+ for _ , lease := range dhcpServerDetails .Leases {
488+ if * lease .InstanceMacAddress == pvmNetwork .MacAddress {
489+ m .Info ("found internal ip for VM from DHCP lease" , "IP" , * lease .InstanceIP , "VM" , * instance .ServerName )
490+ internalIP = lease .InstanceIP
491+ break
492+ }
493+ }
494+ if internalIP == nil {
495+ errStr := fmt .Errorf ("internal IP is nil" )
496+ m .Error (errStr , "failed to get internal IP, DHCP lease not found for VM with MAC in DHCP network" , "VM" , * instance .ServerName ,
497+ "MAC" , pvmNetwork .MacAddress , "DHCP server ID" , * dhcpServerDetails .ID )
498+ return
499+ }
500+ m .Info ("found internal IP for VM from DHCP lease" , "IP" , * internalIP , "VM" , * instance .ServerName )
501+ addresses = append (addresses , corev1.NodeAddress {
502+ Type : corev1 .NodeInternalIP ,
503+ Address : * internalIP ,
504+ })
505+ // Update the cache with the ip and VM name
506+ err = m .DHCPIPCacheStore .Add (powervs.VMip {
507+ Name : * instance .ServerName ,
508+ IP : * internalIP ,
509+ })
510+ if err != nil {
511+ m .Error (err , "failed to update the DHCP cache store with the IP" , "VM" , * instance .ServerName , "IP" , * internalIP )
512+ }
513+ m .IBMPowerVSMachine .Status .Addresses = addresses
420514}
421515
422516// SetInstanceState will set the state for the machine.
0 commit comments