@@ -33,6 +33,7 @@ import (
33
33
powerVSUtils "github.com/ppc64le-cloud/powervs-utils"
34
34
corev1 "k8s.io/api/core/v1"
35
35
"k8s.io/apimachinery/pkg/types"
36
+ "k8s.io/client-go/tools/cache"
36
37
"k8s.io/klog/v2/klogr"
37
38
"k8s.io/utils/pointer"
38
39
capiv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
@@ -60,6 +61,7 @@ type PowerVSMachineScopeParams struct {
60
61
IBMPowerVSMachine * infrav1beta1.IBMPowerVSMachine
61
62
IBMPowerVSImage * infrav1beta1.IBMPowerVSImage
62
63
ServiceEndpoint []endpoints.ServiceEndpoint
64
+ DHCPIPCacheStore cache.Store
63
65
}
64
66
65
67
// PowerVSMachineScope defines a scope defined around a Power VS Machine.
@@ -75,6 +77,7 @@ type PowerVSMachineScope struct {
75
77
IBMPowerVSMachine * infrav1beta1.IBMPowerVSMachine
76
78
IBMPowerVSImage * infrav1beta1.IBMPowerVSImage
77
79
ServiceEndpoint []endpoints.ServiceEndpoint
80
+ DHCPIPCacheStore cache.Store
78
81
}
79
82
80
83
// NewPowerVSMachineScope creates a new PowerVSMachineScope from the supplied parameters.
@@ -163,7 +166,7 @@ func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (scope *PowerVSMac
163
166
scope .SetRegion (region )
164
167
scope .SetZone (* res .RegionID )
165
168
166
- options := powervs.ServiceOptions {
169
+ serviceOptions := powervs.ServiceOptions {
167
170
IBMPIOptions : & ibmpisession.IBMPIOptions {
168
171
Debug : params .Logger .V (DEBUGLEVEL ).Enabled (),
169
172
UserAccount : account ,
@@ -175,17 +178,17 @@ func NewPowerVSMachineScope(params PowerVSMachineScopeParams) (scope *PowerVSMac
175
178
176
179
// Fetch the service endpoint.
177
180
if svcEndpoint := endpoints .FetchPVSEndpoint (region , params .ServiceEndpoint ); svcEndpoint != "" {
178
- options .IBMPIOptions .URL = svcEndpoint
181
+ serviceOptions .IBMPIOptions .URL = svcEndpoint
179
182
scope .Logger .V (3 ).Info ("overriding the default powervs service endpoint" )
180
183
}
181
184
182
- c , err := powervs .NewService (options )
185
+ c , err := powervs .NewService (serviceOptions )
183
186
if err != nil {
184
187
err = fmt .Errorf ("failed to create PowerVS service" )
185
188
return
186
189
}
187
190
scope .IBMPowerVSClient = c
188
-
191
+ scope . DHCPIPCacheStore = params . DHCPIPCacheStore
189
192
return scope , nil
190
193
}
191
194
@@ -435,6 +438,97 @@ func (m *PowerVSMachineScope) SetAddresses(instance *models.PVMInstance) {
435
438
}
436
439
}
437
440
m .IBMPowerVSMachine .Status .Addresses = addresses
441
+ if len (addresses ) > 2 {
442
+ // If the address length is more than 2 means either NodeInternalIP or NodeExternalIP is updated so return
443
+ return
444
+ }
445
+ // In this case there is no IP found under instance.Networks, So try to fetch the IP from cache or DHCP server
446
+ // Look for DHCP IP from the cache
447
+ obj , exists , err := m .DHCPIPCacheStore .GetByKey (* instance .ServerName )
448
+ if err != nil {
449
+ m .Error (err , "failed to fetch the DHCP IP address from cache store" , "VM" , * instance .ServerName )
450
+ }
451
+ if exists {
452
+ m .Info ("found IP for VM from DHCP cache" , "IP" , obj .(powervs.VMip ).IP , "VM" , * instance .ServerName )
453
+ addresses = append (addresses , corev1.NodeAddress {
454
+ Type : corev1 .NodeInternalIP ,
455
+ Address : obj .(powervs.VMip ).IP ,
456
+ })
457
+ m .IBMPowerVSMachine .Status .Addresses = addresses
458
+ return
459
+ }
460
+ // Fetch the VM network ID
461
+ networkID , err := getNetworkID (m .IBMPowerVSMachine .Spec .Network , m )
462
+ if err != nil {
463
+ m .Error (err , "failed to fetch network id from network resource" , "VM" , * instance .ServerName )
464
+ return
465
+ }
466
+ // Fetch the details of the network attached to the VM
467
+ var pvmNetwork * models.PVMInstanceNetwork
468
+ for _ , network := range instance .Networks {
469
+ if network .NetworkID == * networkID {
470
+ pvmNetwork = network
471
+ m .Info ("found network attached to VM" , "Network ID" , network .NetworkID , "VM" , * instance .ServerName )
472
+ }
473
+ }
474
+ if pvmNetwork == nil {
475
+ m .Info ("failed to get network attached to VM" , "VM" , * instance .ServerName , "Network ID" , * networkID )
476
+ return
477
+ }
478
+ // Get all the DHCP servers
479
+ dhcpServer , err := m .IBMPowerVSClient .GetAllDHCPServers ()
480
+ if err != nil {
481
+ m .Error (err , "failed to get DHCP server" )
482
+ return
483
+ }
484
+ // Get the Details of DHCP server associated with the network
485
+ var dhcpServerDetails * models.DHCPServerDetail
486
+ for _ , server := range dhcpServer {
487
+ if * server .Network .ID == * networkID {
488
+ m .Info ("found DHCP server for network" , "DHCP server ID" , * server .ID , "network ID" , * networkID )
489
+ dhcpServerDetails , err = m .IBMPowerVSClient .GetDHCPServer (* server .ID )
490
+ if err != nil {
491
+ m .Error (err , "failed to get DHCP server details" , "DHCP server ID" , * server .ID )
492
+ return
493
+ }
494
+ break
495
+ }
496
+ }
497
+ if dhcpServerDetails == nil {
498
+ errStr := fmt .Errorf ("DHCP server details is nil" )
499
+ m .Error (errStr , "DHCP server associated with network is nil" , "Network ID" , * networkID )
500
+ return
501
+ }
502
+
503
+ // Fetch the VM IP using VM's mac from DHCP server lease
504
+ var internalIP * string
505
+ for _ , lease := range dhcpServerDetails .Leases {
506
+ if * lease .InstanceMacAddress == pvmNetwork .MacAddress {
507
+ m .Info ("found internal ip for VM from DHCP lease" , "IP" , * lease .InstanceIP , "VM" , * instance .ServerName )
508
+ internalIP = lease .InstanceIP
509
+ break
510
+ }
511
+ }
512
+ if internalIP == nil {
513
+ errStr := fmt .Errorf ("internal IP is nil" )
514
+ m .Error (errStr , "failed to get internal IP, DHCP lease not found for VM with MAC in DHCP network" , "VM" , * instance .ServerName ,
515
+ "MAC" , pvmNetwork .MacAddress , "DHCP server ID" , * dhcpServerDetails .ID )
516
+ return
517
+ }
518
+ m .Info ("found internal IP for VM from DHCP lease" , "IP" , * internalIP , "VM" , * instance .ServerName )
519
+ addresses = append (addresses , corev1.NodeAddress {
520
+ Type : corev1 .NodeInternalIP ,
521
+ Address : * internalIP ,
522
+ })
523
+ // Update the cache with the ip and VM name
524
+ err = m .DHCPIPCacheStore .Add (powervs.VMip {
525
+ Name : * instance .ServerName ,
526
+ IP : * internalIP ,
527
+ })
528
+ if err != nil {
529
+ m .Error (err , "failed to update the DHCP cache store with the IP" , "VM" , * instance .ServerName , "IP" , * internalIP )
530
+ }
531
+ m .IBMPowerVSMachine .Status .Addresses = addresses
438
532
}
439
533
440
534
// SetInstanceState will set the state for the machine.
0 commit comments