Skip to content

Commit

Permalink
feat(vmbda): apply new design
Browse files Browse the repository at this point in the history
Signed-off-by: Isteb4k <dmitry.rakitin@flant.com>
  • Loading branch information
Isteb4k committed Jun 25, 2024
1 parent 6ad3e77 commit c69f753
Show file tree
Hide file tree
Showing 17 changed files with 927 additions and 750 deletions.
23 changes: 10 additions & 13 deletions api/core/v1alpha2/virtual_machine_block_disk_attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ type VirtualMachineBlockDeviceAttachmentList struct {
}

type VirtualMachineBlockDeviceAttachmentSpec struct {
VirtualMachine string `json:"virtualMachineName"`
BlockDeviceRef VMBDAObjectRef `json:"blockDeviceRef"`
VirtualMachineName string `json:"virtualMachineName"`
BlockDeviceRef VMBDAObjectRef `json:"blockDeviceRef"`
}

type VMBDAObjectRef struct {
Expand All @@ -60,21 +60,18 @@ const (
VMBDAObjectRefKindVirtualDisk VMBDAObjectRefKind = "VirtualDisk"
)

type VirtualMachineBlockDeviceAttachmentObjectRefKind string

const BlockDeviceAttachmentTypeVirtualDisk VirtualMachineBlockDeviceAttachmentObjectRefKind = "VirtualDisk"

type VirtualMachineBlockDeviceAttachmentStatus struct {
VirtualMachine string `json:"virtualMachine,omitempty"`
Phase BlockDeviceAttachmentPhase `json:"phase,omitempty"`
FailureReason string `json:"failureReason,omitempty"`
FailureMessage string `json:"failureMessage,omitempty"`
Phase BlockDeviceAttachmentPhase `json:"phase,omitempty"`
Conditions []metav1.Condition `json:"conditions,omitempty"`
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

type BlockDeviceAttachmentPhase string

const (
BlockDeviceAttachmentPhaseInProgress BlockDeviceAttachmentPhase = "InProgress"
BlockDeviceAttachmentPhaseAttached BlockDeviceAttachmentPhase = "Attached"
BlockDeviceAttachmentPhaseFailed BlockDeviceAttachmentPhase = "Failed"
BlockDeviceAttachmentPhasePending BlockDeviceAttachmentPhase = "Pending"
BlockDeviceAttachmentPhaseInProgress BlockDeviceAttachmentPhase = "InProgress"
BlockDeviceAttachmentPhaseAttached BlockDeviceAttachmentPhase = "Attached"
BlockDeviceAttachmentPhaseFailed BlockDeviceAttachmentPhase = "Failed"
BlockDeviceAttachmentPhaseTerminating BlockDeviceAttachmentPhase = "Terminating"
)
44 changes: 44 additions & 0 deletions api/core/v1alpha2/vmbdacondition/condition.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
Copyright 2024 Flant JSC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package vmbdacondition

type Type = string

const (
BlockDeviceReadyType Type = "BlockDeviceReady"
VirtualMachineReadyType Type = "VirtualMachineReady"
AttachedType Type = "Attached"
)

type (
BlockDeviceReadyReason = string
VirtualMachineReadyReason = string
AttachedReason = string
)

const (
BlockDeviceReady BlockDeviceReadyReason = "BlockDeviceReady"
BlockDeviceNotReady BlockDeviceReadyReason = "BlockDeviceNotReady"

VirtualMachineReady VirtualMachineReadyReason = "VirtualMachineReady"
VirtualMachineNotReady VirtualMachineReadyReason = "VirtualMachineNotReady"

Attached AttachedReason = "Attached"
NotAttached AttachedReason = "NotAttached"
AttachmentRequestSent AttachedReason = "AttachmentRequestSent"
AttachmentFailed AttachedReason = "AttachmentFailed"
)
9 changes: 8 additions & 1 deletion api/core/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ import (

"github.com/deckhouse/virtualization-controller/pkg/common"
appconfig "github.com/deckhouse/virtualization-controller/pkg/config"
"github.com/deckhouse/virtualization-controller/pkg/controller"
"github.com/deckhouse/virtualization-controller/pkg/controller/cpu"
"github.com/deckhouse/virtualization-controller/pkg/controller/cvi"
"github.com/deckhouse/virtualization-controller/pkg/controller/ipam"
"github.com/deckhouse/virtualization-controller/pkg/controller/vd"
"github.com/deckhouse/virtualization-controller/pkg/controller/vi"
"github.com/deckhouse/virtualization-controller/pkg/controller/vm"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmbda"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmop"
virtv2alpha1 "github.com/deckhouse/virtualization/api/core/v1alpha2"
)
Expand Down Expand Up @@ -188,16 +188,16 @@ func main() {
os.Exit(1)
}

if _, err := vi.NewController(ctx, mgr, log, importerImage, uploaderImage, dvcrSettings); err != nil {
if _, err = vi.NewController(ctx, mgr, log, importerImage, uploaderImage, dvcrSettings); err != nil {
log.Error(err, "")
os.Exit(1)
}
if _, err := vm.NewController(ctx, mgr, slog.Default(), dvcrSettings); err != nil {
if _, err = vm.NewController(ctx, mgr, slog.Default(), dvcrSettings); err != nil {
log.Error(err, "")
os.Exit(1)
}

if _, err := controller.NewVMBDAController(ctx, mgr, log, controllerNamespace); err != nil {
if _, err = vmbda.NewController(ctx, mgr, log, controllerNamespace); err != nil {
log.Error(err, "")
os.Exit(1)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
Copyright 2024 Flant JSC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package service

import (
"context"
"errors"
"fmt"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
virtv1 "kubevirt.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/deckhouse/virtualization-controller/pkg/controller/kubevirt"
"github.com/deckhouse/virtualization-controller/pkg/controller/kvapi"
"github.com/deckhouse/virtualization-controller/pkg/controller/kvbuilder"
"github.com/deckhouse/virtualization-controller/pkg/sdk/framework/helper"
virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2"
)

type AttachmentService struct {
client client.Client
controllerNamespace string
}

func NewAttachmentService(client client.Client, controllerNamespace string) *AttachmentService {
return &AttachmentService{
client: client,
controllerNamespace: controllerNamespace,
}
}

func (s AttachmentService) IsHotPlugged(ctx context.Context, vd *virtv2.VirtualDisk, vm *virtv2.VirtualMachine) (bool, error) {
if vd == nil || vm == nil {
return false, errors.New("TODO")
}

// TODO: get errors from xvm/xvmi.
// TODO: kvvmi not found or not ready? Check kvvm instead of kvvmi?
kvvmKey := types.NamespacedName{Namespace: vm.Namespace, Name: vm.Name}
kvvm, err := helper.FetchObject(ctx, kvvmKey, s.client, &virtv1.VirtualMachine{})
if err != nil {
return false, err
}
if kvvm == nil {
return false, fmt.Errorf("kvvm %s not found", kvvmKey.String())
}

if kvvm.Spec.Template == nil {
return false, nil
}

for _, volume := range kvvm.Spec.Template.Spec.Volumes {
if volume.Name == kvbuilder.GenerateVMDDiskName(vd.Name) {
return volume.PersistentVolumeClaim != nil && volume.PersistentVolumeClaim.Hotpluggable, nil
}
}

return false, nil
}

var (
ErrVirtualDiskIsAlreadyAttached = errors.New("virtual disk is already attached to virtual machine")
ErrVirtualMachineWaitsForRestartApproval = errors.New("virtual machine waits for restart approval")
)

func (s AttachmentService) HotPlugDisk(ctx context.Context, vd *virtv2.VirtualDisk, vm *virtv2.VirtualMachine) error {
if vd == nil || vm == nil {
return errors.New("TODO")
}

for _, bdr := range vm.Spec.BlockDeviceRefs {
if bdr.Kind == virtv2.DiskDevice && bdr.Name == vd.Name {
return ErrVirtualDiskIsAlreadyAttached
}
}

if len(vm.Status.RestartAwaitingChanges) > 0 {
return ErrVirtualMachineWaitsForRestartApproval
}

name := kvbuilder.GenerateVMDDiskName(vd.Name)

hotplugRequest := virtv1.AddVolumeOptions{
Name: name,
Disk: &virtv1.Disk{
Name: name,
DiskDevice: virtv1.DiskDevice{
Disk: &virtv1.DiskTarget{
Bus: "scsi",
},
},
Serial: vd.Name,
},
VolumeSource: &virtv1.HotplugVolumeSource{
PersistentVolumeClaim: &virtv1.PersistentVolumeClaimVolumeSource{
PersistentVolumeClaimVolumeSource: corev1.PersistentVolumeClaimVolumeSource{
ClaimName: vd.Status.Target.PersistentVolumeClaim,
},
Hotpluggable: true,
},
},
}

kv, err := kubevirt.New(ctx, s.client, s.controllerNamespace)
if err != nil {
return err
}

err = kvapi.New(s.client, kv).AddVolume(ctx, vm.Namespace, vm.Name, &hotplugRequest)
if err != nil {
return fmt.Errorf("error adding volume, %w", err)
}

return nil
}

func (s AttachmentService) UnplugDisk(ctx context.Context, vd *virtv2.VirtualDisk, vm *virtv2.VirtualMachine) error {
if vd == nil || vm == nil {
return errors.New("TODO")
}

unplugRequest := virtv1.RemoveVolumeOptions{
Name: kvbuilder.GenerateVMDDiskName(vd.Name),
}

kv, err := kubevirt.New(ctx, s.client, s.controllerNamespace)
if err != nil {
return err
}

err = kvapi.New(s.client, kv).RemoveVolume(ctx, vm.Namespace, vm.Name, &unplugRequest)
if err != nil {
return fmt.Errorf("error removing volume, %w", err)
}

return nil
}

func (s AttachmentService) GetVirtualDisk(ctx context.Context, name, namespace string) (*virtv2.VirtualDisk, error) {
return helper.FetchObject(ctx, types.NamespacedName{Namespace: name, Name: namespace}, s.client, &virtv2.VirtualDisk{})
}

func (s AttachmentService) GetVirtualMachine(ctx context.Context, name, namespace string) (*virtv2.VirtualMachine, error) {
return helper.FetchObject(ctx, types.NamespacedName{Namespace: name, Name: namespace}, s.client, &virtv2.VirtualMachine{})
}
Loading

0 comments on commit c69f753

Please sign in to comment.