Skip to content

Commit 79c634a

Browse files
eofffmaxinsky
andauthored
feat(vmsnapshot): add resources info in status (#978)
Signed-off-by: Valeriy Khorunzhin <valeriy.khorunzhin@flant.com> Co-authored-by: Max Chervov <max.chervov@gmail.com>
1 parent c6fb9fe commit 79c634a

8 files changed

Lines changed: 244 additions & 15 deletions

File tree

api/core/v1alpha2/virtual_machine_snapshot.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ type VirtualMachineSnapshotSpec struct {
7272
VolumeSnapshotClasses []VolumeSnapshotClassName `json:"volumeSnapshotClasses,omitempty"`
7373
}
7474

75+
type ResourceRef struct {
76+
// Kind of resource
77+
Kind string `json:"kind,omitempty"`
78+
// Api version of resource
79+
ApiVersion string `json:"apiVersion,omitempty"`
80+
// Resource Name
81+
Name string `json:"name,omitempty"`
82+
}
83+
7584
type VirtualMachineSnapshotStatus struct {
7685
Phase VirtualMachineSnapshotPhase `json:"phase"`
7786
// Whether a virtual machine snapshot is consistent.
@@ -80,6 +89,8 @@ type VirtualMachineSnapshotStatus struct {
8089
VirtualMachineSnapshotSecretName string `json:"virtualMachineSnapshotSecretName,omitempty"`
8190
// List of VirtualDiskSnapshot names for the snapshots taken from the virtual disks of the associated virtual machine.
8291
VirtualDiskSnapshotNames []string `json:"virtualDiskSnapshotNames,omitempty"`
92+
// List of snapshot resources.
93+
Resources []ResourceRef `json:"resources,omitempty"`
8394
// The latest detailed observations of the VirtualMachineSnapshot resource.
8495
Conditions []metav1.Condition `json:"conditions,omitempty"`
8596
// Resource generation last processed by the controller.

api/core/v1alpha2/zz_generated.deepcopy.go

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go

Lines changed: 49 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crds/doc-ru-virtualmachinesnapshots.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ spec:
6969
* `Ready` — создание снимка успешно завершено, и он доступен для использования;
7070
* `Failed` — во время создания снимка виртуальной машины произошла ошибка;
7171
* `Terminating` — ресурс находится в процессе удаления.
72+
resources:
73+
description: Список ресурсов снимка.
7274
virtualDiskSnapshotNames:
7375
description: Имена созданных снимков виртуальных дисков.
7476
virtualMachineSnapshotSecretName:

crds/virtualmachinesnapshots.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,21 @@ spec:
195195
- Failed
196196
- Terminating
197197
type: string
198+
resources:
199+
description: List of snapshot resources.
200+
items:
201+
properties:
202+
apiVersion:
203+
description: API version of the resource.
204+
type: string
205+
kind:
206+
description: Kind of the resource.
207+
type: string
208+
name:
209+
description: Name of the resource.
210+
type: string
211+
type: object
212+
type: array
198213
virtualDiskSnapshotNames:
199214
description:
200215
List of VirtualDiskSnapshot names for the snapshots taken

images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle.go

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
649661
func 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

Comments
 (0)