Skip to content

Commit

Permalink
feat: introduce k8s events to lvmcluster and vgmanager
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobmoellerdev committed Aug 31, 2023
1 parent dd8b3b7 commit 7f6a0a1
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 53 deletions.
17 changes: 17 additions & 0 deletions bundle/manifests/lvms-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,23 @@ spec:
- get
- patch
- update
- apiGroups:
- lvm.topolvm.io
resources:
- lvmclusters
- lvmclusters/status
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- update
serviceAccountName: vg-manager
strategy: deployment
installModes:
Expand Down
14 changes: 9 additions & 5 deletions cmd/vgmanager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

lvmv1alpha1 "github.com/openshift/lvm-operator/api/v1alpha1"
"github.com/openshift/lvm-operator/pkg/vgmanager"
"k8s.io/klog/v2"

"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
Expand Down Expand Up @@ -55,7 +56,9 @@ func main() {
opts := zap.Options{}
opts.BindFlags(flag.CommandLine)
opts.Development = developmentMode
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
logr := zap.New(zap.UseFlagOptions(&opts))
ctrl.SetLogger(logr)
klog.SetLogger(logr)

setupLog := ctrl.Log.WithName("setup")

Expand All @@ -73,10 +76,11 @@ func main() {
}

if err = (&vgmanager.VGReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
NodeName: os.Getenv("NODE_NAME"),
Namespace: os.Getenv("POD_NAMESPACE"),
Client: mgr.GetClient(),
EventRecorder: mgr.GetEventRecorderFor(vgmanager.ControllerName),
Scheme: mgr.GetScheme(),
NodeName: os.Getenv("NODE_NAME"),
Namespace: os.Getenv("POD_NAMESPACE"),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "VGManager")
os.Exit(1)
Expand Down
17 changes: 17 additions & 0 deletions config/rbac/vg_manager_role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,20 @@ rules:
- get
- patch
- update
- apiGroups:
- lvm.topolvm.io
resources:
- lvmclusters
- lvmclusters/status
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- update
48 changes: 35 additions & 13 deletions controllers/lvmcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
corev1helper "k8s.io/component-helpers/scheduling/corev1"

ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -42,6 +43,13 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

type EventReasonInfo string
type EventReasonError string

const EventReasonErrorDeletionPending EventReasonError = "DeletionPending"
const EventReasonErrorResourceReconciliationFailed EventReasonError = "ResourceReconciliationFailed"
const EventReasonResourceReconciliationSuccess EventReasonInfo = "ResourceReconciliationSuccess"

var lvmClusterFinalizer = "lvmcluster.topolvm.io"

const (
Expand All @@ -64,6 +72,7 @@ type resourceManager interface {
// LVMClusterReconciler reconciles a LVMCluster object
type LVMClusterReconciler struct {
client.Client
record.EventRecorder
Scheme *runtime.Scheme
ClusterType cluster.Type
Namespace string
Expand Down Expand Up @@ -146,15 +155,17 @@ func (r *LVMClusterReconciler) reconcile(ctx context.Context, instance *lvmv1alp
return ctrl.Result{}, fmt.Errorf("failed to check if LogicalVolumes exist: %w", err)
}
if lvsExist {
waitForLVRemoval := time.Second * 10
err := fmt.Errorf("found PVCs provisioned by topolvm, waiting %s for their deletion: %w", waitForLVRemoval, err)
r.WarningEvent(instance, EventReasonErrorDeletionPending, err)
// check every 10 seconds if there are still PVCs present
return ctrl.Result{RequeueAfter: time.Second * 10},
fmt.Errorf("found PVCs provisioned by topolvm, waiting for their deletion: %w", err)
return ctrl.Result{RequeueAfter: waitForLVRemoval}, err
}

logger.Info("processing LVMCluster deletion")
if err := r.processDelete(ctx, instance); err != nil {
// check every 10 seconds if there are still PVCs present or the LogicalVolumes are removed
return ctrl.Result{Requeue: true}, fmt.Errorf("failed to process LVMCluster deletion")
return ctrl.Result{Requeue: true}, fmt.Errorf("failed to process LVMCluster deletion: %w", err)
}
return reconcile.Result{}, nil
}
Expand Down Expand Up @@ -199,11 +210,14 @@ func (r *LVMClusterReconciler) reconcile(ctx context.Context, instance *lvmv1alp

resourceSyncElapsedTime := time.Since(resourceSyncStart)
if len(errs) > 0 {
return ctrl.Result{}, fmt.Errorf("failed to reconcile resources managed by LVMCluster within %v: %w",
resourceSyncElapsedTime, errors.Join(errs...))
err := fmt.Errorf("failed to reconcile resources managed by LVMCluster: %w", errors.Join(errs...))
r.WarningEvent(instance, EventReasonErrorResourceReconciliationFailed, err)
return ctrl.Result{}, err
}

logger.Info("successfully reconciled LVMCluster", "resourceSyncElapsedTime", resourceSyncElapsedTime)
msg := "successfully reconciled LVMCluster"
logger.Info(msg, "resourceSyncElapsedTime", resourceSyncElapsedTime)
r.NormalEvent(instance, EventReasonResourceReconciliationSuccess, msg)

return ctrl.Result{}, nil
}
Expand Down Expand Up @@ -358,15 +372,13 @@ func (r *LVMClusterReconciler) logicalVolumesExist(ctx context.Context) (bool, e
return false, fmt.Errorf("failed to get TopoLVM LogicalVolume list: %w", err)
}
if len(logicalVolumeList.Items) > 0 {

return true, nil
}
return false, nil
}

func (r *LVMClusterReconciler) processDelete(ctx context.Context, instance *lvmv1alpha1.LVMCluster) error {
if controllerutil.ContainsFinalizer(instance, lvmClusterFinalizer) {

resourceDeletionList := []resourceManager{
&topolvmVolumeSnapshotClass{},
&topolvmStorageClass{},
Expand All @@ -383,16 +395,26 @@ func (r *LVMClusterReconciler) processDelete(ctx context.Context, instance *lvmv

for _, unit := range resourceDeletionList {
if err := unit.ensureDeleted(r, ctx, instance); err != nil {
return fmt.Errorf("failed cleaning up: %s %w", unit.getName(), err)
err := fmt.Errorf("failed cleaning up %s: %w", unit.getName(), err)
r.WarningEvent(instance, EventReasonErrorDeletionPending, err)
return err
}
}
}

if update := controllerutil.RemoveFinalizer(instance, lvmClusterFinalizer); update {
if err := r.Client.Update(ctx, instance); err != nil {
return fmt.Errorf("failed to remove finalizer from LVMCluster %s: %w", instance.GetName(), err)
}
if update := controllerutil.RemoveFinalizer(instance, lvmClusterFinalizer); update {
if err := r.Client.Update(ctx, instance); err != nil {
return fmt.Errorf("failed to remove finalizer from LVMCluster %s: %w", instance.GetName(), err)
}
}

return nil
}

func (r *LVMClusterReconciler) WarningEvent(obj client.Object, reason EventReasonError, err error) {
r.Event(obj, corev1.EventTypeWarning, string(reason), err.Error())
}

func (r *LVMClusterReconciler) NormalEvent(obj client.Object, reason EventReasonInfo, message string) {
r.Event(obj, corev1.EventTypeNormal, string(reason), message)
}
11 changes: 6 additions & 5 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,12 @@ var _ = BeforeSuite(func() {
Expect(err).ToNot(HaveOccurred())

err = (&LVMClusterReconciler{
Client: k8sManager.GetClient(),
Scheme: k8sManager.GetScheme(),
ClusterType: clusterType,
Namespace: testLvmClusterNamespace,
ImageName: testImageName,
Client: k8sManager.GetClient(),
EventRecorder: k8sManager.GetEventRecorderFor(ControllerName),
Scheme: k8sManager.GetScheme(),
ClusterType: clusterType,
Namespace: testLvmClusterNamespace,
ImageName: testImageName,
}).SetupWithManager(k8sManager)
Expect(err).ToNot(HaveOccurred())

Expand Down
6 changes: 3 additions & 3 deletions controllers/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ func verifyDeploymentReadiness(dep *appsv1.Deployment) error {
}
for _, condition := range dep.Status.Conditions {
if condition.Type == appsv1.DeploymentAvailable && condition.Status == corev1.ConditionFalse {
return fmt.Errorf("the Deployment is not ready: %s/%s. deployment has not reached minimum availability and thus not ready: %v",
return fmt.Errorf("the Deployment is not ready: %s/%s. deployment has not reached minimum availability and is not ready: %v",
dep.Namespace, dep.Name, condition)
} else if condition.Type == appsv1.DeploymentProgressing && condition.Status == corev1.ConditionFalse {
return fmt.Errorf("the Deployment is not ready: %s/%s. deployment has not progressed and is thus not ready: %v",
return fmt.Errorf("the Deployment is not ready: %s/%s. deployment has not progressed and is not ready: %v",
dep.Namespace, dep.Name, condition)
} else if condition.Type == appsv1.DeploymentReplicaFailure && condition.Status == corev1.ConditionTrue {
return fmt.Errorf("the Deployment is not ready: %s/%s. deployment has a replica failure and is thus not ready: %v",
return fmt.Errorf("the Deployment is not ready: %s/%s. deployment has a replica failure and is not ready: %v",
dep.Namespace, dep.Name, condition)
}
}
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ func main() {
if err = (&controllers.LVMClusterReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
EventRecorder: mgr.GetEventRecorderFor(controllers.ControllerName),
ClusterType: clusterType,
Namespace: operatorNamespace,
TopoLVMLeaderElectionPassthrough: leaderElectionConfig,
Expand Down
16 changes: 10 additions & 6 deletions pkg/vgmanager/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,7 @@ func (r *VGReconciler) setVolumeGroupStatus(ctx context.Context, status *lvmv1al
logger := log.FromContext(ctx)

// Get LVMVolumeGroupNodeStatus and set the relevant VGStatus
nodeStatus := &lvmv1alpha1.LVMVolumeGroupNodeStatus{
ObjectMeta: metav1.ObjectMeta{
Name: r.NodeName,
Namespace: r.Namespace,
},
}
nodeStatus := r.getLVMVolumeGroupNodeStatus()

result, err := ctrl.CreateOrUpdate(ctx, r.Client, nodeStatus, func() error {
exists := false
Expand Down Expand Up @@ -171,3 +166,12 @@ func (r *VGReconciler) setDevices(status *lvmv1alpha1.VGStatus) (bool, error) {

return devicesExist, nil
}

func (r *VGReconciler) getLVMVolumeGroupNodeStatus() *lvmv1alpha1.LVMVolumeGroupNodeStatus {
return &lvmv1alpha1.LVMVolumeGroupNodeStatus{
ObjectMeta: metav1.ObjectMeta{
Name: r.NodeName,
Namespace: r.Namespace,
},
}
}
Loading

0 comments on commit 7f6a0a1

Please sign in to comment.