@@ -24,9 +24,12 @@ import (
2424
2525 corev1 "k8s.io/api/core/v1"
2626 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+ "k8s.io/apimachinery/pkg/types"
2728 "k8s.io/utils/ptr"
29+ "sigs.k8s.io/controller-runtime/pkg/client"
2830 "sigs.k8s.io/controller-runtime/pkg/reconcile"
2931
32+ "github.com/deckhouse/virtualization-controller/pkg/common/object"
3033 "github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
3134 "github.com/deckhouse/virtualization-controller/pkg/controller/service"
3235 "github.com/deckhouse/virtualization-controller/pkg/eventrecord"
@@ -42,13 +45,15 @@ type LifeCycleHandler struct {
4245 recorder eventrecord.EventRecorderLogger
4346 snapshotter Snapshotter
4447 storer Storer
48+ client client.Client
4549}
4650
47- func NewLifeCycleHandler (recorder eventrecord.EventRecorderLogger , snapshotter Snapshotter , storer Storer ) * LifeCycleHandler {
51+ func NewLifeCycleHandler (recorder eventrecord.EventRecorderLogger , snapshotter Snapshotter , storer Storer , client client. Client ) * LifeCycleHandler {
4852 return & LifeCycleHandler {
4953 recorder : recorder ,
5054 snapshotter : snapshotter ,
5155 storer : storer ,
56+ client : client ,
5257 }
5358}
5459
@@ -353,7 +358,14 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
353358 return reconcile.Result {}, err
354359 }
355360
356- // 9. Move to Ready phase.
361+ // 9. Fill status resources.
362+ err = h .fillStatusResources (ctx , vmSnapshot , vm )
363+ if err != nil {
364+ h .setPhaseConditionToFailed (cb , vmSnapshot , err )
365+ return reconcile.Result {}, err
366+ }
367+
368+ // 10. Move to Ready phase.
357369 log .Debug ("The virtual disk snapshots are taken: the virtual machine snapshot is Ready now" , "unfrozen" , unfrozen )
358370
359371 vmSnapshot .Status .Phase = virtv2 .VirtualMachineSnapshotPhaseReady
@@ -649,3 +661,117 @@ func getVDName(vdSnapshotName string, vmSnapshot *virtv2.VirtualMachineSnapshot)
649661func getVDSnapshotName (vdName string , vmSnapshot * virtv2.VirtualMachineSnapshot ) string {
650662 return fmt .Sprintf ("%s-%s" , vdName , vmSnapshot .UID )
651663}
664+
665+ func (h LifeCycleHandler ) fillStatusResources (ctx context.Context , vmSnapshot * virtv2.VirtualMachineSnapshot , vm * virtv2.VirtualMachine ) error {
666+ vmSnapshot .Status .Resources = []virtv2.ResourceRef {}
667+
668+ vmSnapshot .Status .Resources = append (vmSnapshot .Status .Resources , virtv2.ResourceRef {
669+ Kind : vm .Kind ,
670+ ApiVersion : vm .APIVersion ,
671+ Name : vm .Name ,
672+ })
673+
674+ if vmSnapshot .Spec .KeepIPAddress == virtv2 .KeepIPAddressAlways {
675+ vmip , err := object .FetchObject (ctx , types.NamespacedName {
676+ Namespace : vm .Namespace ,
677+ Name : vm .Status .VirtualMachineIPAddress ,
678+ }, h .client , & virtv2.VirtualMachineIPAddress {})
679+ if err != nil {
680+ return err
681+ }
682+
683+ if vmip == nil {
684+ return fmt .Errorf ("the virtual machine ip address %q not found" , vm .Status .VirtualMachineIPAddress )
685+ }
686+
687+ vmSnapshot .Status .Resources = append (vmSnapshot .Status .Resources , virtv2.ResourceRef {
688+ Kind : vmip .Kind ,
689+ ApiVersion : vmip .APIVersion ,
690+ Name : vmip .Name ,
691+ })
692+ }
693+
694+ provisioner , err := h .getProvisionerFromVM (ctx , vm )
695+ if err != nil {
696+ return err
697+ }
698+ if provisioner != nil {
699+ vmSnapshot .Status .Resources = append (vmSnapshot .Status .Resources , virtv2.ResourceRef {
700+ Kind : provisioner .Kind ,
701+ ApiVersion : provisioner .APIVersion ,
702+ Name : provisioner .Name ,
703+ })
704+ }
705+
706+ for _ , bdr := range vm .Status .BlockDeviceRefs {
707+ if bdr .Kind != virtv2 .DiskDevice {
708+ continue
709+ }
710+
711+ vd , err := object .FetchObject (ctx , types.NamespacedName {Name : bdr .Name , Namespace : vm .Namespace }, h .client , & virtv2.VirtualDisk {})
712+ if err != nil {
713+ return err
714+ }
715+ if vd == nil {
716+ continue
717+ }
718+ vmSnapshot .Status .Resources = append (vmSnapshot .Status .Resources , virtv2.ResourceRef {
719+ Kind : vd .Kind ,
720+ ApiVersion : vd .APIVersion ,
721+ Name : vd .Name ,
722+ })
723+
724+ if bdr .VirtualMachineBlockDeviceAttachmentName != "" {
725+ vmbda , err := object .FetchObject (ctx , types.NamespacedName {Name : bdr .VirtualMachineBlockDeviceAttachmentName , Namespace : vm .Namespace }, h .client , & virtv2.VirtualMachineBlockDeviceAttachment {})
726+ if err != nil {
727+ return err
728+ }
729+ if vmbda == nil {
730+ continue
731+ }
732+ vmSnapshot .Status .Resources = append (vmSnapshot .Status .Resources , virtv2.ResourceRef {
733+ Kind : vmbda .Kind ,
734+ ApiVersion : vmbda .APIVersion ,
735+ Name : vmbda .Name ,
736+ })
737+ }
738+ }
739+
740+ return nil
741+ }
742+
743+ func (h LifeCycleHandler ) getProvisionerFromVM (ctx context.Context , vm * virtv2.VirtualMachine ) (* corev1.Secret , error ) {
744+ if vm .Spec .Provisioning != nil {
745+ var provisioningSecretName string
746+
747+ switch vm .Spec .Provisioning .Type {
748+ case virtv2 .ProvisioningTypeSysprepRef :
749+ if vm .Spec .Provisioning .SysprepRef == nil {
750+ return nil , nil
751+ }
752+
753+ if vm .Spec .Provisioning .SysprepRef .Kind == virtv2 .SysprepRefKindSecret {
754+ provisioningSecretName = vm .Spec .Provisioning .SysprepRef .Name
755+ }
756+
757+ case virtv2 .ProvisioningTypeUserDataRef :
758+ if vm .Spec .Provisioning .UserDataRef == nil {
759+ return nil , nil
760+ }
761+
762+ if vm .Spec .Provisioning .UserDataRef .Kind == virtv2 .UserDataRefKindSecret {
763+ provisioningSecretName = vm .Spec .Provisioning .UserDataRef .Name
764+ }
765+ }
766+
767+ if provisioningSecretName != "" {
768+ secretKey := types.NamespacedName {Name : provisioningSecretName , Namespace : vm .Namespace }
769+ provisioner , err := object .FetchObject (ctx , secretKey , h .client , & corev1.Secret {})
770+ return provisioner , err
771+ } else {
772+ return nil , nil
773+ }
774+ } else {
775+ return nil , nil
776+ }
777+ }
0 commit comments