Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 06eeb56

Browse files
authoredMar 17, 2020
Merge pull request #833 from yastij/fail-deleted-machines
read failureReason and failureMessage from the vsphereVM object to the vspheremachine
2 parents 39568c1 + 2bae906 commit 06eeb56

File tree

7 files changed

+124
-13
lines changed

7 files changed

+124
-13
lines changed
 

‎api/v1alpha3/vspherevm_types.go

+31
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package v1alpha3
1919
import (
2020
corev1 "k8s.io/api/core/v1"
2121
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
"sigs.k8s.io/cluster-api/errors"
2223
)
2324

2425
const (
@@ -82,6 +83,36 @@ type VSphereVMStatus struct {
8283
// network interfaces.
8384
// +optional
8485
Network []NetworkStatus `json:"network,omitempty"`
86+
87+
// FailureReason will be set in the event that there is a terminal problem
88+
// reconciling the vspherevm and will contain a succinct value suitable
89+
// for vm interpretation.
90+
//
91+
// This field should not be set for transitive errors that a controller
92+
// faces that are expected to be fixed automatically over
93+
// time (like service outages), but instead indicate that something is
94+
// fundamentally wrong with the vm.
95+
//
96+
// Any transient errors that occur during the reconciliation of vspherevms
97+
// can be added as events to the vspherevm object and/or logged in the
98+
// controller's output.
99+
// +optional
100+
FailureReason *errors.MachineStatusError `json:"failureReason,omitempty"`
101+
102+
// FailureMessage will be set in the event that there is a terminal problem
103+
// reconciling the vspherevm and will contain a more verbose string suitable
104+
// for logging and human consumption.
105+
//
106+
// This field should not be set for transitive errors that a controller
107+
// faces that are expected to be fixed automatically over
108+
// time (like service outages), but instead indicate that something is
109+
// fundamentally wrong with the vm.
110+
//
111+
// Any transient errors that occur during the reconciliation of vspherevms
112+
// can be added as events to the vspherevm object and/or logged in the
113+
// controller's output.
114+
// +optional
115+
FailureMessage *string `json:"failureMessage,omitempty"`
85116
}
86117

87118
// +kubebuilder:object:root=true

‎api/v1alpha3/zz_generated.deepcopy.go

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎config/crd/bases/infrastructure.cluster.x-k8s.io_vspherevms.yaml

+22
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,28 @@ spec:
286286
to determine the actual type of clone operation used to create this
287287
VM.
288288
type: string
289+
failureMessage:
290+
description: "FailureMessage will be set in the event that there is
291+
a terminal problem reconciling the vspherevm and will contain a
292+
more verbose string suitable for logging and human consumption.
293+
\n This field should not be set for transitive errors that a controller
294+
faces that are expected to be fixed automatically over time (like
295+
service outages), but instead indicate that something is fundamentally
296+
wrong with the vm. \n Any transient errors that occur during the
297+
reconciliation of vspherevms can be added as events to the vspherevm
298+
object and/or logged in the controller's output."
299+
type: string
300+
failureReason:
301+
description: "FailureReason will be set in the event that there is
302+
a terminal problem reconciling the vspherevm and will contain a
303+
succinct value suitable for vm interpretation. \n This field should
304+
not be set for transitive errors that a controller faces that are
305+
expected to be fixed automatically over time (like service outages),
306+
but instead indicate that something is fundamentally wrong with
307+
the vm. \n Any transient errors that occur during the reconciliation
308+
of vspherevms can be added as events to the vspherevm object and/or
309+
logged in the controller's output."
310+
type: string
289311
network:
290312
description: Network returns the network status for each of the machine's
291313
configured network interfaces.

‎controllers/vspheremachine_controller.go

+31-10
Original file line numberDiff line numberDiff line change
@@ -243,21 +243,16 @@ func (r machineReconciler) reconcileDeleteVM(ctx *context.MachineContext) error
243243

244244
func (r machineReconciler) reconcileDeleteVMPre7(ctx *context.MachineContext) error {
245245
// Get ready to find the associated VSphereVM resource.
246-
vm := &infrav1.VSphereVM{}
247246
vmKey := apitypes.NamespacedName{
248247
Namespace: ctx.VSphereMachine.Namespace,
249248
Name: ctx.Machine.Name,
250249
}
251-
250+
vm, err := r.findVMPre7(ctx)
252251
// Attempt to find the associated VSphereVM resource.
253-
if err := ctx.Client.Get(ctx, vmKey, vm); err != nil {
254-
// If an error occurs finding the VSphereVM resource other than
255-
// IsNotFound, then return the error. Otherwise it means the VSphereVM
256-
// is already deleted, and that's okay.
257-
if !apierrors.IsNotFound(err) {
258-
return errors.Wrapf(err, "failed to get VSphereVM %s", vmKey)
259-
}
260-
} else if vm.GetDeletionTimestamp().IsZero() {
252+
if err != nil {
253+
return err
254+
}
255+
if vm.GetDeletionTimestamp().IsZero() {
261256
// If the VSphereVM was found and it's not already enqueued for
262257
// deletion, go ahead and attempt to delete it.
263258
if err := ctx.Client.Delete(ctx, vm); err != nil {
@@ -274,7 +269,33 @@ func (r machineReconciler) reconcileDeleteVMPre7(ctx *context.MachineContext) er
274269
return nil
275270
}
276271

272+
func (r machineReconciler) findVMPre7(ctx *context.MachineContext) (*infrav1.VSphereVM, error) {
273+
// Get ready to find the associated VSphereVM resource.
274+
vm := &infrav1.VSphereVM{}
275+
vmKey := apitypes.NamespacedName{
276+
Namespace: ctx.VSphereMachine.Namespace,
277+
Name: ctx.Machine.Name,
278+
}
279+
// Attempt to find the associated VSphereVM resource.
280+
if err := ctx.Client.Get(ctx, vmKey, vm); err != nil {
281+
return nil, err
282+
}
283+
return vm, nil
284+
}
285+
277286
func (r machineReconciler) reconcileNormal(ctx *context.MachineContext) (reconcile.Result, error) {
287+
vsphereVM, err := r.findVMPre7(ctx)
288+
if err != nil {
289+
if !apierrors.IsNotFound(err) {
290+
return reconcile.Result{}, err
291+
}
292+
}
293+
if vsphereVM != nil {
294+
// Reconcile VSphereMachine's failures
295+
ctx.VSphereMachine.Status.FailureReason = vsphereVM.Status.FailureReason
296+
ctx.VSphereMachine.Status.FailureMessage = vsphereVM.Status.FailureMessage
297+
}
298+
278299
// If the VSphereMachine is in an error state, return early.
279300
if ctx.VSphereMachine.Status.FailureReason != nil || ctx.VSphereMachine.Status.FailureMessage != nil {
280301
ctx.Logger.Info("Error state detected, skipping reconciliation")

‎controllers/vspherevm_controller.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ type vmReconciler struct {
8888
}
8989

9090
// Reconcile ensures the back-end state reflects the Kubernetes resource state intent.
91+
// nolint:gocognit
9192
func (r vmReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, reterr error) {
92-
9393
// Get the VSphereVM resource for this request.
9494
vsphereVM := &infrav1.VSphereVM{}
9595
if err := r.Client.Get(r, req.NamespacedName, vsphereVM); err != nil {
@@ -262,6 +262,11 @@ func (r vmReconciler) reconcileDelete(ctx *context.VMContext) (reconcile.Result,
262262
}
263263

264264
func (r vmReconciler) reconcileNormal(ctx *context.VMContext) (reconcile.Result, error) {
265+
266+
if ctx.VSphereVM.Status.FailureReason != nil || ctx.VSphereVM.Status.FailureMessage != nil {
267+
r.Logger.Info("VM is failed, won't reconcile", "namespace", ctx.VSphereVM.Namespace, "name", ctx.VSphereVM.Name)
268+
return reconcile.Result{}, nil
269+
}
265270
// If the VSphereVM doesn't have our finalizer, add it.
266271
ctrlutil.AddFinalizer(ctx.VSphereVM, infrav1.VMFinalizer)
267272

‎pkg/services/govmomi/errors.go

+12
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,15 @@ func isNotFound(err error) bool {
3939
return false
4040
}
4141
}
42+
43+
func wasNotFoundByBIOSUUID(err error) bool {
44+
switch err.(type) {
45+
case errNotFound, *errNotFound:
46+
if err.(errNotFound).uuid != "" && !err.(errNotFound).instanceUUID {
47+
return true
48+
}
49+
return false
50+
default:
51+
return false
52+
}
53+
}

‎pkg/services/govmomi/service.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package govmomi
1818

1919
import (
2020
"encoding/base64"
21+
"fmt"
2122

2223
"github.com/pkg/errors"
2324

@@ -27,6 +28,8 @@ import (
2728
"github.com/vmware/govmomi/vim25/types"
2829
corev1 "k8s.io/api/core/v1"
2930
apitypes "k8s.io/apimachinery/pkg/types"
31+
"k8s.io/utils/pointer"
32+
capierrors "sigs.k8s.io/cluster-api/errors"
3033

3134
infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/api/v1alpha3"
3235
"sigs.k8s.io/cluster-api-provider-vsphere/pkg/context"
@@ -69,8 +72,15 @@ func (vms *VMService) ReconcileVM(ctx *context.VMContext) (vm infrav1.VirtualMac
6972
if !isNotFound(err) {
7073
return vm, err
7174
}
72-
// If VM's MoRef could not be found then the VM does not exist,
73-
// and the VM should be created.
75+
76+
// If the machine was not found by BIOS UUID it means that it got deleted from vcenter directly
77+
if wasNotFoundByBIOSUUID(err) {
78+
ctx.VSphereVM.Status.FailureReason = capierrors.MachineStatusErrorPtr(capierrors.UpdateMachineError)
79+
ctx.VSphereVM.Status.FailureMessage = pointer.StringPtr(fmt.Sprintf("Unable to find VM by BIOS UUID %s. The vm was removed from infra", ctx.VSphereVM.Spec.BiosUUID))
80+
return vm, err
81+
}
82+
83+
// Otherwise, this is a new machine and the the VM should be created.
7484

7585
// Get the bootstrap data.
7686
bootstrapData, err := vms.getBootstrapData(ctx)

0 commit comments

Comments
 (0)
Please sign in to comment.