@@ -48,12 +48,26 @@ var (
48
48
failuredomainMatcher = regexp .MustCompile (`ds\.meta_data\.failuredomain` )
49
49
)
50
50
51
+ const (
52
+ BootstrapDataNotReady = "Bootstrap DataSecretName not yet available"
53
+ CSMachineCreationSuccess = "CloudStack instance Created"
54
+ CSMachineCreationFailed = "Creating CloudStack machine failed: %s"
55
+ MachineInstanceRunning = "Machine instance is Running..."
56
+ MachineInErrorMessage = "CloudStackMachine VM in error state. Deleting associated Machine"
57
+ MachineNotReadyMessage = "Instance not ready, is %s"
58
+ CSMachineStateCheckerCreationFailed = "error encountered when creating CloudStackMachineStateChecker"
59
+ CSMachineStateCheckerCreationSuccess = "CloudStackMachineStateChecker created"
60
+ CSMachineDeletionMessage = "Deleting CloudStack Machine %s"
61
+ CSMachineDeletionInstanceIDNotFoundMessage = "Deleting CloudStack Machine %s instanceID not found"
62
+ )
63
+
51
64
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachines,verbs=get;list;watch;create;update;patch;delete
52
65
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachines/status,verbs=get;update;patch
53
66
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=cloudstackmachines/finalizers,verbs=update
54
67
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch
55
68
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machinesets,verbs=get;list;watch
56
69
// +kubebuilder:rbac:groups=controlplane.cluster.x-k8s.io,resources=kubeadmcontrolplanes,verbs=get;list;watch
70
+ // +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
57
71
58
72
// CloudStackMachineReconciliationRunner is a ReconciliationRunner with extensions specific to CloudStack machine reconciliation.
59
73
type CloudStackMachineReconciliationRunner struct {
@@ -186,7 +200,8 @@ func (r *CloudStackMachineReconciliationRunner) DeleteMachineIfFailuredomainNotE
186
200
// Implicitly it also fetches its bootstrap secret in order to create said instance.
187
201
func (r * CloudStackMachineReconciliationRunner ) GetOrCreateVMInstance () (retRes ctrl.Result , reterr error ) {
188
202
if r .CAPIMachine .Spec .Bootstrap .DataSecretName == nil {
189
- return r .RequeueWithMessage ("Bootstrap DataSecretName not yet available." )
203
+ r .Recorder .Event (r .ReconciliationSubject , "Normal" , "Creating" , BootstrapDataNotReady )
204
+ return r .RequeueWithMessage (BootstrapDataNotReady + "." )
190
205
}
191
206
r .Log .Info ("Got Bootstrap DataSecretName." )
192
207
@@ -204,8 +219,12 @@ func (r *CloudStackMachineReconciliationRunner) GetOrCreateVMInstance() (retRes
204
219
userData := processCustomMetadata (data , r )
205
220
err := r .CSUser .GetOrCreateVMInstance (r .ReconciliationSubject , r .CAPIMachine , r .CSCluster , r .FailureDomain , r .AffinityGroup , userData )
206
221
222
+ if err != nil {
223
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , "Creating" , CSMachineCreationFailed , err .Error ())
224
+ }
207
225
if err == nil && ! controllerutil .ContainsFinalizer (r .ReconciliationSubject , infrav1 .MachineFinalizer ) { // Fetched or Created?
208
- r .Log .Info ("CloudStack instance Created" , "instanceStatus" , r .ReconciliationSubject .Status )
226
+ r .Recorder .Eventf (r .ReconciliationSubject , "Normal" , "Created" , CSMachineCreationSuccess )
227
+ r .Log .Info (CSMachineCreationSuccess , "instanceStatus" , r .ReconciliationSubject .Status )
209
228
}
210
229
// Always add the finalizer regardless. It can't be added twice anyway.
211
230
controllerutil .AddFinalizer (r .ReconciliationSubject , infrav1 .MachineFinalizer )
@@ -223,16 +242,19 @@ func processCustomMetadata(data []byte, r *CloudStackMachineReconciliationRunner
223
242
// ConfirmVMStatus checks the Instance's status for running state and requeues otherwise.
224
243
func (r * CloudStackMachineReconciliationRunner ) RequeueIfInstanceNotRunning () (retRes ctrl.Result , reterr error ) {
225
244
if r .ReconciliationSubject .Status .InstanceState == "Running" {
226
- r .Log .Info ("Machine instance is Running..." )
245
+ r .Recorder .Event (r .ReconciliationSubject , "Normal" , "Running" , MachineInstanceRunning )
246
+ r .Log .Info (MachineInstanceRunning )
227
247
r .ReconciliationSubject .Status .Ready = true
228
248
} else if r .ReconciliationSubject .Status .InstanceState == "Error" {
229
- r .Log .Info ("CloudStackMachine VM in error state. Deleting associated Machine." , "csMachine" , r .ReconciliationSubject .GetName ())
249
+ r .Recorder .Event (r .ReconciliationSubject , "Warning" , "Error" , MachineInErrorMessage )
250
+ r .Log .Info (MachineInErrorMessage , "csMachine" , r .ReconciliationSubject .GetName ())
230
251
if err := r .K8sClient .Delete (r .RequestCtx , r .CAPIMachine ); err != nil {
231
252
return ctrl.Result {}, err
232
253
}
233
254
return ctrl.Result {RequeueAfter : utils .RequeueTimeout }, nil
234
255
} else {
235
- r .Log .Info (fmt .Sprintf ("Instance not ready, is %s." , r .ReconciliationSubject .Status .InstanceState ))
256
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , r .ReconciliationSubject .Status .InstanceState , MachineNotReadyMessage , r .ReconciliationSubject .Status .InstanceState )
257
+ r .Log .Info (fmt .Sprintf (MachineNotReadyMessage , r .ReconciliationSubject .Status .InstanceState ))
236
258
return ctrl.Result {RequeueAfter : utils .RequeueTimeout }, nil
237
259
}
238
260
return ctrl.Result {}, nil
@@ -263,9 +285,10 @@ func (r *CloudStackMachineReconciliationRunner) GetOrCreateMachineStateChecker()
263
285
}
264
286
265
287
if err := r .K8sClient .Create (r .RequestCtx , csMachineStateChecker ); err != nil && ! utils .ContainsAlreadyExistsSubstring (err ) {
266
- return r .ReturnWrappedError (err , "error encountered when creating CloudStackMachineStateChecker" )
288
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , "Machine State Checker" , CSMachineStateCheckerCreationFailed )
289
+ return r .ReturnWrappedError (err , CSMachineStateCheckerCreationFailed )
267
290
}
268
-
291
+ r . Recorder . Eventf ( r . ReconciliationSubject , "Normal" , "Machine State Checker" , CSMachineStateCheckerCreationSuccess )
269
292
return r .GetObjectByName (* checkerName , r .StateChecker )()
270
293
}
271
294
@@ -280,9 +303,12 @@ func (r *CloudStackMachineReconciliationRunner) ReconcileDelete() (retRes ctrl.R
280
303
fmt .Sprintf (" If this VM has already been deleted, please remove the finalizer named %s from object %s" ,
281
304
"cloudstackmachine.infrastructure.cluster.x-k8s.io" , r .ReconciliationSubject .Name ))
282
305
// Cloudstack VM may be not found or more than one found by name
306
+ r .Recorder .Eventf (r .ReconciliationSubject , "Warning" , "Deleting" , CSMachineDeletionInstanceIDNotFoundMessage , r .ReconciliationSubject .Name )
307
+ r .Log .Error (err , fmt .Sprintf (CSMachineDeletionInstanceIDNotFoundMessage , r .ReconciliationSubject .Name ))
283
308
return ctrl.Result {}, err
284
309
}
285
310
}
311
+ r .Recorder .Eventf (r .ReconciliationSubject , "Normal" , "Deleting" , CSMachineDeletionMessage , r .ReconciliationSubject .Name )
286
312
r .Log .Info ("Deleting instance" , "instance-id" , r .ReconciliationSubject .Spec .InstanceID )
287
313
// Use CSClient instead of CSUser here to expunge as admin.
288
314
// The CloudStack-Go API does not return an error, but the VM won't delete with Expunge set if requested by
@@ -364,6 +390,7 @@ func (reconciler *CloudStackMachineReconciler) SetupWithManager(mgr ctrl.Manager
364
390
return err
365
391
}
366
392
393
+ reconciler .Recorder = mgr .GetEventRecorderFor ("capc-machine-controller" )
367
394
// Add a watch on CAPI Cluster objects for unpause and ready events.
368
395
return controller .Watch (
369
396
& source.Kind {Type : & clusterv1.Cluster {}},
0 commit comments