From 7016f1cc24c5c5f37862ca94991e97e438559449 Mon Sep 17 00:00:00 2001 From: yaroslavborbat Date: Tue, 14 Jan 2025 12:29:00 +0300 Subject: [PATCH] fix Signed-off-by: yaroslavborbat --- .../pkg/controller/kvapi/kvapi.go | 71 ++++++++++++------- .../pkg/controller/kvapi/types.go | 31 ++++++++ .../controller/service/attachment_service.go | 4 +- .../pkg/controller/vmbda/vmbda_webhook.go | 1 - 4 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 images/virtualization-artifact/pkg/controller/kvapi/types.go diff --git a/images/virtualization-artifact/pkg/controller/kvapi/kvapi.go b/images/virtualization-artifact/pkg/controller/kvapi/kvapi.go index 1ecdb05025..1e8b2a02a4 100644 --- a/images/virtualization-artifact/pkg/controller/kvapi/kvapi.go +++ b/images/virtualization-artifact/pkg/controller/kvapi/kvapi.go @@ -44,7 +44,7 @@ type KvApi struct { kubevirt Kubevirt } -func (api *KvApi) AddVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, opts *virtv1.AddVolumeOptions) error { +func (api *KvApi) AddVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, opts *AddVolumeOptions) error { return api.addVolume(ctx, kvvm, opts) } @@ -52,7 +52,7 @@ func (api *KvApi) RemoveVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, return api.removeVolume(ctx, kvvm, opts) } -func (api *KvApi) addVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, opts *virtv1.AddVolumeOptions) error { +func (api *KvApi) addVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, opts *AddVolumeOptions) error { if kvvm == nil { return nil } @@ -71,7 +71,7 @@ func (api *KvApi) addVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, op opts.Disk.Name = opts.Name - volumeRequest := virtv1.VirtualMachineVolumeRequest{ + volumeRequest := VirtualMachineVolumeRequest{ AddVolumeOptions: opts, } @@ -80,6 +80,8 @@ func (api *KvApi) addVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, op opts.VolumeSource.DataVolume.Hotpluggable = true case opts.VolumeSource.PersistentVolumeClaim != nil: opts.VolumeSource.PersistentVolumeClaim.Hotpluggable = true + case opts.VolumeSource.ContainerDisk != nil: + opts.VolumeSource.ContainerDisk.Hotpluggable = true } return api.vmVolumePatchStatus(ctx, kvvm, &volumeRequest) @@ -97,14 +99,14 @@ func (api *KvApi) removeVolume(ctx context.Context, kvvm *virtv1.VirtualMachine, return fmt.Errorf("RemoveVolumeOptions requires name to be set") } - volumeRequest := virtv1.VirtualMachineVolumeRequest{ + volumeRequest := VirtualMachineVolumeRequest{ RemoveVolumeOptions: opts, } return api.vmVolumePatchStatus(ctx, kvvm, &volumeRequest) } -func (api *KvApi) vmVolumePatchStatus(ctx context.Context, kvvm *virtv1.VirtualMachine, volumeRequest *virtv1.VirtualMachineVolumeRequest) error { +func (api *KvApi) vmVolumePatchStatus(ctx context.Context, kvvm *virtv1.VirtualMachine, volumeRequest *VirtualMachineVolumeRequest) error { if kvvm == nil { return nil } @@ -131,7 +133,7 @@ func (api *KvApi) vmVolumePatchStatus(ctx context.Context, kvvm *virtv1.VirtualM return nil } -func (api *KvApi) getDryRunOption(volumeRequest *virtv1.VirtualMachineVolumeRequest) []string { +func (api *KvApi) getDryRunOption(volumeRequest *VirtualMachineVolumeRequest) []string { var dryRunOption []string if options := volumeRequest.AddVolumeOptions; options != nil && options.DryRun != nil && options.DryRun[0] == metav1.DryRunAll { dryRunOption = volumeRequest.AddVolumeOptions.DryRun @@ -141,7 +143,7 @@ func (api *KvApi) getDryRunOption(volumeRequest *virtv1.VirtualMachineVolumeRequ return dryRunOption } -func verifyVolumeOption(volumes []virtv1.Volume, volumeRequest *virtv1.VirtualMachineVolumeRequest) error { +func verifyVolumeOption(volumes []virtv1.Volume, volumeRequest *VirtualMachineVolumeRequest) error { foundRemoveVol := false for _, volume := range volumes { if volumeRequest.AddVolumeOptions != nil { @@ -168,13 +170,16 @@ func verifyVolumeOption(volumes []virtv1.Volume, volumeRequest *virtv1.VirtualMa return nil } -func volumeSourceName(volumeSource *virtv1.HotplugVolumeSource) string { +func volumeSourceName(volumeSource *HotplugVolumeSource) string { if volumeSource.DataVolume != nil { return volumeSource.DataVolume.Name } if volumeSource.PersistentVolumeClaim != nil { return volumeSource.PersistentVolumeClaim.ClaimName } + if volumeSource.ContainerDisk != nil { + return "" + } return "" } @@ -195,18 +200,37 @@ func volumeHotpluggable(volume virtv1.Volume) bool { return (volume.DataVolume != nil && volume.DataVolume.Hotpluggable) || (volume.PersistentVolumeClaim != nil && volume.PersistentVolumeClaim.Hotpluggable) } -func generateVMVolumeRequestPatch(vm *virtv1.VirtualMachine, volumeRequest *virtv1.VirtualMachineVolumeRequest) (string, error) { - vmCopy := vm.DeepCopy() +func generateVMVolumeRequestPatch(vm *virtv1.VirtualMachine, volumeRequest *VirtualMachineVolumeRequest) (string, error) { + var newVolumeRequests []VirtualMachineVolumeRequest + + for _, req := range vm.Status.VolumeRequests { + newReq := VirtualMachineVolumeRequest{ + RemoveVolumeOptions: req.RemoveVolumeOptions, + } + if req.AddVolumeOptions != nil { + addVolumeOptions := &AddVolumeOptions{ + Name: req.AddVolumeOptions.Name, + DryRun: req.AddVolumeOptions.DryRun, + Disk: req.AddVolumeOptions.Disk, + VolumeSource: &HotplugVolumeSource{ + PersistentVolumeClaim: req.AddVolumeOptions.VolumeSource.PersistentVolumeClaim, + DataVolume: req.AddVolumeOptions.VolumeSource.DataVolume, + }, + } + + newReq.AddVolumeOptions = addVolumeOptions + } + } // We only validate the list against other items in the list at this point. // The VM validation webhook will validate the list against the VMI spec // during the Patch command if volumeRequest.AddVolumeOptions != nil { - if err := addAddVolumeRequests(vmCopy, volumeRequest); err != nil { + if err := addAddVolumeRequests(&newVolumeRequests, volumeRequest); err != nil { return "", err } } else if volumeRequest.RemoveVolumeOptions != nil { - if err := addRemoveVolumeRequests(vmCopy, volumeRequest); err != nil { + if err := addRemoveVolumeRequests(&newVolumeRequests, volumeRequest); err != nil { return "", err } } @@ -215,24 +239,24 @@ func generateVMVolumeRequestPatch(vm *virtv1.VirtualMachine, volumeRequest *virt if len(vm.Status.VolumeRequests) > 0 { verb = patch.PatchReplaceOp } - jop := patch.NewJsonPatchOperation(verb, "/status/volumeRequests", vmCopy.Status.VolumeRequests) + jop := patch.NewJsonPatchOperation(verb, "/status/volumeRequests", newVolumeRequests) jp := patch.NewJsonPatch(jop) return jp.String() } -func addAddVolumeRequests(vm *virtv1.VirtualMachine, volumeRequest *virtv1.VirtualMachineVolumeRequest) error { +func addAddVolumeRequests(requests *[]VirtualMachineVolumeRequest, volumeRequest *VirtualMachineVolumeRequest) error { name := volumeRequest.AddVolumeOptions.Name - for _, request := range vm.Status.VolumeRequests { + for _, request := range *requests { if err := validateAddVolumeRequest(request, name); err != nil { return err } } - vm.Status.VolumeRequests = append(vm.Status.VolumeRequests, *volumeRequest) + *requests = append(*requests, *volumeRequest) return nil } -func validateAddVolumeRequest(request virtv1.VirtualMachineVolumeRequest, name string) error { +func validateAddVolumeRequest(request VirtualMachineVolumeRequest, name string) error { if addVolumeRequestExists(request, name) { return fmt.Errorf("add volume request for volume [%s] already exists", name) } @@ -242,10 +266,9 @@ func validateAddVolumeRequest(request virtv1.VirtualMachineVolumeRequest, name s return nil } -func addRemoveVolumeRequests(vm *virtv1.VirtualMachine, volumeRequest *virtv1.VirtualMachineVolumeRequest) error { +func addRemoveVolumeRequests(requests *[]VirtualMachineVolumeRequest, volumeRequest *VirtualMachineVolumeRequest) error { name := volumeRequest.RemoveVolumeOptions.Name - var volumeRequestsList []virtv1.VirtualMachineVolumeRequest - for _, request := range vm.Status.VolumeRequests { + for _, request := range *requests { if addVolumeRequestExists(request, name) { // Filter matching AddVolume requests from the new list. continue @@ -253,17 +276,15 @@ func addRemoveVolumeRequests(vm *virtv1.VirtualMachine, volumeRequest *virtv1.Vi if removeVolumeRequestExists(request, name) { return fmt.Errorf("a remove volume request for volume [%s] already exists and is still being processed", name) } - volumeRequestsList = append(volumeRequestsList, request) } - volumeRequestsList = append(volumeRequestsList, *volumeRequest) - vm.Status.VolumeRequests = volumeRequestsList + *requests = append(*requests, *volumeRequest) return nil } -func addVolumeRequestExists(request virtv1.VirtualMachineVolumeRequest, name string) bool { +func addVolumeRequestExists(request VirtualMachineVolumeRequest, name string) bool { return request.AddVolumeOptions != nil && request.AddVolumeOptions.Name == name } -func removeVolumeRequestExists(request virtv1.VirtualMachineVolumeRequest, name string) bool { +func removeVolumeRequestExists(request VirtualMachineVolumeRequest, name string) bool { return request.RemoveVolumeOptions != nil && request.RemoveVolumeOptions.Name == name } diff --git a/images/virtualization-artifact/pkg/controller/kvapi/types.go b/images/virtualization-artifact/pkg/controller/kvapi/types.go new file mode 100644 index 0000000000..4bb5ef0559 --- /dev/null +++ b/images/virtualization-artifact/pkg/controller/kvapi/types.go @@ -0,0 +1,31 @@ +package kvapi + +import ( + v1 "k8s.io/api/core/v1" + virtv1 "kubevirt.io/api/core/v1" +) + +type VirtualMachineVolumeRequest struct { + AddVolumeOptions *AddVolumeOptions `json:"addVolumeOptions,omitempty" optional:"true"` + RemoveVolumeOptions *virtv1.RemoveVolumeOptions `json:"removeVolumeOptions,omitempty" optional:"true"` +} +type AddVolumeOptions struct { + Name string `json:"name"` + Disk *virtv1.Disk `json:"disk"` + VolumeSource *HotplugVolumeSource `json:"volumeSource"` + DryRun []string `json:"dryRun,omitempty"` +} + +type HotplugVolumeSource struct { + PersistentVolumeClaim *virtv1.PersistentVolumeClaimVolumeSource `json:"persistentVolumeClaim,omitempty"` + DataVolume *virtv1.DataVolumeSource `json:"dataVolume,omitempty"` + ContainerDisk *ContainerDiskSource `json:"containerDisk,omitempty"` +} + +type ContainerDiskSource struct { + Image string `json:"image"` + ImagePullSecret string `json:"imagePullSecret,omitempty"` + Path string `json:"path,omitempty"` + ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"` + Hotpluggable bool `json:"hotpluggable,omitempty"` +} diff --git a/images/virtualization-artifact/pkg/controller/service/attachment_service.go b/images/virtualization-artifact/pkg/controller/service/attachment_service.go index da823e83ce..4fe0d8b06d 100644 --- a/images/virtualization-artifact/pkg/controller/service/attachment_service.go +++ b/images/virtualization-artifact/pkg/controller/service/attachment_service.go @@ -142,7 +142,7 @@ func (s AttachmentService) HotPlugDisk(ctx context.Context, ad *AttachmentDisk, return errors.New("cannot hot plug a disk into a nil KVVM") } - hotplugRequest := virtv1.AddVolumeOptions{ + hotplugRequest := kvapi.AddVolumeOptions{ Name: ad.GenerateName, Disk: &virtv1.Disk{ Name: ad.GenerateName, @@ -153,7 +153,7 @@ func (s AttachmentService) HotPlugDisk(ctx context.Context, ad *AttachmentDisk, }, Serial: ad.Name, }, - VolumeSource: &virtv1.HotplugVolumeSource{ + VolumeSource: &kvapi.HotplugVolumeSource{ PersistentVolumeClaim: &virtv1.PersistentVolumeClaimVolumeSource{ PersistentVolumeClaimVolumeSource: corev1.PersistentVolumeClaimVolumeSource{ ClaimName: ad.PVCName, diff --git a/images/virtualization-artifact/pkg/controller/vmbda/vmbda_webhook.go b/images/virtualization-artifact/pkg/controller/vmbda/vmbda_webhook.go index 5f098b6a7f..6f8432aa30 100644 --- a/images/virtualization-artifact/pkg/controller/vmbda/vmbda_webhook.go +++ b/images/virtualization-artifact/pkg/controller/vmbda/vmbda_webhook.go @@ -24,7 +24,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" "github.com/deckhouse/deckhouse/pkg/log" - "github.com/deckhouse/virtualization-controller/pkg/controller/service" "github.com/deckhouse/virtualization-controller/pkg/controller/vmbda/internal/validators" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2"