@@ -23,6 +23,8 @@ import (
2323 "github.com/go-logr/logr"
2424 infrav1beta1 "github.com/spectrocloud/cluster-api-provider-maas/api/v1beta1"
2525 maint "github.com/spectrocloud/cluster-api-provider-maas/pkg/maas/maintenance"
26+ corev1 "k8s.io/api/core/v1"
27+ "k8s.io/client-go/tools/record"
2628 "sigs.k8s.io/controller-runtime/pkg/client"
2729)
2830
@@ -40,10 +42,11 @@ type HostMaintenanceService struct {
4042 namespace string
4143 tagService maint.TagService
4244 inventoryService maint.InventoryService
45+ recorder record.EventRecorder
4346}
4447
4548// NewHostMaintenanceService creates a new host maintenance service
46- func NewHostMaintenanceService (k8sClient client.Client , namespace string ) (* HostMaintenanceService , error ) {
49+ func NewHostMaintenanceService (k8sClient client.Client , namespace string , recorder record. EventRecorder ) (* HostMaintenanceService , error ) {
4750 maasClient , err := maint .NewMAASClient (k8sClient , namespace )
4851 if err != nil {
4952 return nil , fmt .Errorf ("failed to create MAAS client: %w" , err )
@@ -53,6 +56,7 @@ func NewHostMaintenanceService(k8sClient client.Client, namespace string) (*Host
5356 namespace : namespace ,
5457 tagService : maint .NewTagService (maasClient ),
5558 inventoryService : maint .NewInventoryService (maasClient ),
59+ recorder : recorder ,
5660 }, nil
5761}
5862
@@ -79,13 +83,51 @@ func (s *HostMaintenanceService) CheckEvacuationGates(ctx context.Context, maasM
7983 hostSystemID := * maasMachine .Spec .SystemID
8084
8185 // Gate 1: Check if host is empty (no VMs running)
82- hostEmpty , err := s .isHostEmpty (ctx , hostSystemID , log )
86+ // Get VMs list first so we can include names in event if host is not empty
87+ vms , err := s .inventoryService .ListHostVMs (hostSystemID )
8388 if err != nil {
84- return false , fmt .Errorf ("failed to check if host is empty : %w" , err )
89+ return false , fmt .Errorf ("failed to list host VMs : %w" , err )
8590 }
8691
87- if ! hostEmpty {
88- log .Info ("Host not empty, evacuation blocked" , "host" , hostSystemID )
92+ hostEmpty := len (vms ) == 0
93+ if hostEmpty {
94+ log .Info ("Host is empty (no VMs)" , "host" , hostSystemID )
95+ } else {
96+ // Get host details to use hostname in event
97+ hostDetails , err := s .inventoryService .GetHost (hostSystemID )
98+ hostName := hostSystemID // fallback to systemID
99+ if err == nil {
100+ if hostDetails .FQDN != "" {
101+ hostName = hostDetails .FQDN
102+ } else if hostDetails .Hostname != "" {
103+ hostName = hostDetails .Hostname
104+ }
105+ }
106+
107+ // Build list of VM names/identifiers for the event
108+ vmNames := make ([]string , 0 , len (vms ))
109+ for _ , vm := range vms {
110+ // Prefer FQDN or Hostname, fallback to SystemID
111+ vmName := vm .FQDN
112+ if vmName == "" {
113+ vmName = vm .Hostname
114+ }
115+ if vmName == "" {
116+ vmName = vm .SystemID
117+ }
118+ vmNames = append (vmNames , vmName )
119+ }
120+
121+ log .Info ("Host not empty, evacuation blocked" , "host" , hostSystemID , "vmCount" , len (vms ), "vms" , vmNames )
122+
123+ // Emit Kubernetes event with VM names
124+ if s .recorder != nil {
125+ vmNamesStr := strings .Join (vmNames , ", " )
126+ s .recorder .Eventf (maasMachine , corev1 .EventTypeWarning , "EvacuationBlocked" ,
127+ "Host evacuation blocked: %d VM(s) still present on host %s: %s" ,
128+ len (vms ), hostName , vmNamesStr )
129+ }
130+
89131 return false , nil
90132 }
91133
@@ -96,7 +138,25 @@ func (s *HostMaintenanceService) CheckEvacuationGates(ctx context.Context, maasM
96138 }
97139
98140 if ! wlcReady {
141+ // Get host details to use hostname in event
142+ hostDetails , err := s .inventoryService .GetHost (hostSystemID )
143+ hostName := hostSystemID // fallback to systemID
144+ if err == nil {
145+ if hostDetails .FQDN != "" {
146+ hostName = hostDetails .FQDN
147+ } else if hostDetails .Hostname != "" {
148+ hostName = hostDetails .Hostname
149+ }
150+ }
151+
99152 log .Info ("WLC ready tags not met, evacuation blocked" , "host" , hostSystemID )
153+
154+ // Emit Kubernetes event
155+ if s .recorder != nil {
156+ s .recorder .Eventf (maasMachine , corev1 .EventTypeWarning , "WLCReplacementPending" ,
157+ "WLC evacuation blocked: waiting for replacement VMs on host %s" , hostName )
158+ }
159+
100160 return false , nil
101161 }
102162
0 commit comments