@@ -6,13 +6,20 @@ import (
66
77 "github.com/go-logr/logr"
88 k8serrors "k8s.io/apimachinery/pkg/api/errors"
9+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+ "k8s.io/apimachinery/pkg/runtime/schema"
911 "k8s.io/apimachinery/pkg/types"
1012 virtv1 "kubevirt.io/api/core/v1"
1113 "sigs.k8s.io/controller-runtime/pkg/client"
1214
1315 "github.com/ramendr/ramen/internal/controller/core"
1416)
1517
18+ const (
19+ KindVirtualMachine = "VirtualMachine"
20+ KubeVirtAPIVersion = "kubevirt.io/v1"
21+ )
22+
1623func ListVMsByLabelSelector (
1724 ctx context.Context ,
1825 apiReader client.Reader ,
@@ -89,3 +96,91 @@ func ListVMsByVMNamespace(
8996
9097 return nil , notFoundErr
9198}
99+
100+ func IsVMDeletionInProgress (ctx context.Context ,
101+ k8sclient client.Client ,
102+ vmList []string ,
103+ vmNamespaceList []string ,
104+ log logr.Logger ,
105+ ) bool {
106+ log .Info ("Checking if VirtualMachines are being deleted" ,
107+ "vmCount" , len (vmList ),
108+ "vmNames" , vmList )
109+
110+ foundVM := & virtv1.VirtualMachine {}
111+
112+ for _ , ns := range vmNamespaceList {
113+ for _ , vm := range vmList {
114+ vmLookUp := types.NamespacedName {Namespace : ns , Name : vm }
115+ if err := k8sclient .Get (ctx , vmLookUp , foundVM ); err != nil {
116+ // Continuing with remaining list of VMs as the current one might already have been deleted
117+ continue
118+ }
119+
120+ if ! foundVM .GetDeletionTimestamp ().IsZero () {
121+ // Deletion of vm has been requested
122+ return true
123+ }
124+ }
125+ }
126+
127+ return false
128+ }
129+
130+ func DeleteVMs (
131+ ctx context.Context ,
132+ k8sclient client.Client ,
133+ vmList []string ,
134+ vmNamespaceList []string ,
135+ log logr.Logger ,
136+ ) error {
137+ for _ , ns := range vmNamespaceList {
138+ for _ , vmName := range vmList {
139+ vm := & virtv1.VirtualMachine {}
140+ key := client.ObjectKey {Name : vmName , Namespace : ns }
141+
142+ if err := k8sclient .Get (ctx , key , vm ); err != nil {
143+ log .Error (err , "Failed to get VM" , "namespace" , ns , "name" , vmName )
144+
145+ return fmt .Errorf ("failed to get VM %s/%s: %w" , ns , vmName , err )
146+ }
147+
148+ if err := k8sclient .Delete (ctx , vm ); err != nil {
149+ log .Error (err , "Failed to delete VM" , "namespace" , ns , "name" , vmName )
150+
151+ return fmt .Errorf ("failed to delete VM %s/%s: %w" , ns , vmName , err )
152+ }
153+
154+ log .Info ("Deleted VM successfully" , "namespace" , ns , "name" , vmName )
155+ }
156+ }
157+
158+ return nil
159+ }
160+
161+ // IsOwnedByVM recursively traverses ownerReferences until it finds a VirtualMachine.
162+ func IsOwnedByVM (ctx context.Context , c client.Client , obj client.Object , log logr.Logger ) (string , error ) {
163+ for {
164+ owners := obj .GetOwnerReferences ()
165+ if len (owners ) == 0 {
166+ return "" , fmt .Errorf ("no VM found in ownership chain" )
167+ }
168+
169+ for _ , owner := range owners {
170+ if owner .Kind == KindVirtualMachine && owner .APIVersion == KubeVirtAPIVersion {
171+ return owner .Name , nil // Found VM root
172+ }
173+
174+ // Fetch only metadata of the owner
175+ ownerMeta := & metav1.PartialObjectMetadata {}
176+ ownerMeta .SetGroupVersionKind (schema .FromAPIVersionAndKind (owner .APIVersion , owner .Kind ))
177+
178+ if err := c .Get (ctx , client.ObjectKey {Namespace : obj .GetNamespace (), Name : owner .Name }, ownerMeta ); err != nil {
179+ return "" , err
180+ }
181+
182+ // Continue traversal with the owner
183+ obj = ownerMeta
184+ }
185+ }
186+ }
0 commit comments