54
54
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch
55
55
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machinesets,verbs=get;list;watch
56
56
// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=kubeadmcontrolplanes,verbs=get;list;watch
57
+ // +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
57
58
58
59
// CloudStackMachineReconciliationRunner is a ReconciliationRunner with extensions specific to CloudStack machine reconciliation.
59
60
type CloudStackMachineReconciliationRunner struct {
@@ -186,6 +187,7 @@ func (r *CloudStackMachineReconciliationRunner) DeleteMachineIfFailuredomainNotE
186
187
// Implicitly it also fetches its bootstrap secret in order to create said instance.
187
188
func (r * CloudStackMachineReconciliationRunner ) GetOrCreateVMInstance () (retRes ctrl.Result , reterr error ) {
188
189
if r .CAPIMachine .Spec .Bootstrap .DataSecretName == nil {
190
+ r .Recorder .Event (r .ReconciliationSubject , "Normal" , "Creating" , "Bootstrap DataSecretName not yet available." )
189
191
return r .RequeueWithMessage ("Bootstrap DataSecretName not yet available." )
190
192
}
191
193
r .Log .Info ("Got Bootstrap DataSecretName." )
@@ -204,7 +206,11 @@ func (r *CloudStackMachineReconciliationRunner) GetOrCreateVMInstance() (retRes
204
206
userData := processCustomMetadata (data , r )
205
207
err := r .CSUser .GetOrCreateVMInstance (r .ReconciliationSubject , r .CAPIMachine , r .CSCluster , r .FailureDomain , r .AffinityGroup , userData )
206
208
209
+ if err != nil {
210
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , "Creating" , "Creating CloudStack machine failed: %s" , err .Error ())
211
+ }
207
212
if err == nil && ! controllerutil .ContainsFinalizer (r .ReconciliationSubject , infrav1 .MachineFinalizer ) { // Fetched or Created?
213
+ r .Recorder .Eventf (r .ReconciliationSubject , "Normal" , "Created" , "CloudStack instance Created" )
208
214
r .Log .Info ("CloudStack instance Created" , "instanceStatus" , r .ReconciliationSubject .Status )
209
215
}
210
216
// Always add the finalizer regardless. It can't be added twice anyway.
@@ -223,15 +229,18 @@ func processCustomMetadata(data []byte, r *CloudStackMachineReconciliationRunner
223
229
// ConfirmVMStatus checks the Instance's status for running state and requeues otherwise.
224
230
func (r * CloudStackMachineReconciliationRunner ) RequeueIfInstanceNotRunning () (retRes ctrl.Result , reterr error ) {
225
231
if r .ReconciliationSubject .Status .InstanceState == "Running" {
232
+ r .Recorder .Event (r .ReconciliationSubject , "Normal" , "Running" , "Machine instance is Running..." )
226
233
r .Log .Info ("Machine instance is Running..." )
227
234
r .ReconciliationSubject .Status .Ready = true
228
235
} else if r .ReconciliationSubject .Status .InstanceState == "Error" {
236
+ r .Recorder .Event (r .ReconciliationSubject , "Warning" , "Error" , "CloudStackMachine VM in error state. Deleting associated Machine." )
229
237
r .Log .Info ("CloudStackMachine VM in error state. Deleting associated Machine." , "csMachine" , r .ReconciliationSubject .GetName ())
230
238
if err := r .K8sClient .Delete (r .RequestCtx , r .CAPIMachine ); err != nil {
231
239
return ctrl.Result {}, err
232
240
}
233
241
return ctrl.Result {RequeueAfter : utils .RequeueTimeout }, nil
234
242
} else {
243
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , r .ReconciliationSubject .Status .InstanceState , "Instance not ready, is %s." , r .ReconciliationSubject .Status .InstanceState )
235
244
r .Log .Info (fmt .Sprintf ("Instance not ready, is %s." , r .ReconciliationSubject .Status .InstanceState ))
236
245
return ctrl.Result {RequeueAfter : utils .RequeueTimeout }, nil
237
246
}
@@ -263,9 +272,10 @@ func (r *CloudStackMachineReconciliationRunner) GetOrCreateMachineStateChecker()
263
272
}
264
273
265
274
if err := r .K8sClient .Create (r .RequestCtx , csMachineStateChecker ); err != nil && ! utils .ContainsAlreadyExistsSubstring (err ) {
275
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , "Machine State Checker" , "error encountered when creating CloudStackMachineStateChecker: %s" , err .Error ())
266
276
return r .ReturnWrappedError (err , "error encountered when creating CloudStackMachineStateChecker" )
267
277
}
268
-
278
+ r . Recorder . Eventf ( r . ReconciliationSubject , "Normal" , "Machine State Checker" , "CloudStackMachineStateChecker %s created" , * checkerName )
269
279
return r .GetObjectByName (* checkerName , r .StateChecker )()
270
280
}
271
281
@@ -280,9 +290,11 @@ func (r *CloudStackMachineReconciliationRunner) ReconcileDelete() (retRes ctrl.R
280
290
fmt .Sprintf (" If this VM has already been deleted, please remove the finalizer named %s from object %s" ,
281
291
"cloudstackmachine.infrastructure.cluster.x-k8s.io" , r .ReconciliationSubject .Name ))
282
292
// Cloudstack VM may be not found or more than one found by name
293
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , "Deleting" , "Deleting CloudStack Machine %s instanceID not found" , r .ReconciliationSubject .Name )
283
294
return ctrl.Result {}, err
284
295
}
285
296
}
297
+ r .Recorder .Eventf (r .ReconciliationSubject , "Normal" , "Deleting" , "Deleting CloudStack Machine %s" , r .ReconciliationSubject .Name )
286
298
r .Log .Info ("Deleting instance" , "instance-id" , r .ReconciliationSubject .Spec .InstanceID )
287
299
// Use CSClient instead of CSUser here to expunge as admin.
288
300
// The CloudStack-Go API does not return an error, but the VM won't delete with Expunge set if requested by
@@ -364,6 +376,7 @@ func (reconciler *CloudStackMachineReconciler) SetupWithManager(mgr ctrl.Manager
364
376
return err
365
377
}
366
378
379
+ reconciler .Recorder = mgr .GetEventRecorderFor ("capc-machine-controller" )
367
380
// Add a watch on CAPI Cluster objects for unpause and ready events.
368
381
return controller .Watch (
369
382
& source.Kind {Type : & clusterv1.Cluster {}},
0 commit comments