Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(vd): fix fake pvc resizing #159

Merged
merged 2 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions api/core/v1alpha2/vdcondition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ const (
NotRequested ResizedReason = "NotRequested"
// InProgress indicates that the resize request has been detected and the operation is currently in progress.
InProgress ResizedReason = "InProgress"
// TooSmallDiskSize indicates that the requested disk size is too small for the resize operation.
TooSmallDiskSize ResizedReason = "TooSmallDiskSize"
// Resized indicates that the resize operation has been successfully completed.
Resized ResizedReason = "Resized"
)
1 change: 1 addition & 0 deletions crds/doc-ru-virtualdisk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ spec:
* Provisioning — идет процесс создания ресурса (копирование/загрузка/создание образа).
* WaitForUserUpload — ожидание загрузки образа пользователем. Путь для загрузки образа указывается в `.status.uploadCommand`.
* Ready — ресурс создан и готов к использованию.
* Resizing — идет процесс увеличения размера диска.
* Failed — при создании ресурса возникла проблема.
* PVCLost — дочерний PVC ресурса отсутствует. Ресурс не может быть использован.
* Terminating - Ресурс находится в процессе удаления.
Expand Down
2 changes: 2 additions & 0 deletions crds/virtualdisk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ spec:
* Provisioning - The process of resource creation (copying/downloading/filling the PVC with data/extending PVC) is in progress.
* WaitForUserUpload - Waiting for the user to upload the image. The endpoint to upload the image is specified in `.status.uploadCommand`.
* Ready - The resource is created and ready to use.
* Resizing — The process of resource resizing is in progress.
* Failed - There was a problem when creating a resource, details can be seen in `.status.failureReason` and `.status.failureMessage`.
* PVCLost - The child PVC of the resource is missing. The resource cannot be used.
* Terminating - The process of resource deletion is in progress.
Expand All @@ -274,6 +275,7 @@ spec:
"Provisioning",
"WaitForUserUpload",
"Ready",
"Resizing",
"Failed",
"PVCLost",
"Terminating",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,32 +166,22 @@ func (s DiskService) Unprotect(ctx context.Context, dv *cdiv1.DataVolume) error
return s.protection.RemoveProtection(ctx, dv)
}

func (s DiskService) Resize(ctx context.Context, pvc *corev1.PersistentVolumeClaim, newSize resource.Quantity, sup *supplements.Generator) error {
func (s DiskService) Resize(ctx context.Context, pvc *corev1.PersistentVolumeClaim, newSize resource.Quantity) error {
if pvc == nil {
return errors.New("got nil pvc")
}

curSize := pvc.Spec.Resources.Requests[corev1.ResourceStorage]

if newSize.Cmp(curSize) == -1 {
return ErrTooSmallDiskSize
}

switch newSize.Cmp(curSize) {
case 0:
return nil
case -1:
return ErrTooSmallDiskSize
default:
if newSize.Cmp(curSize) == 1 {
pvc.Spec.Resources.Requests[corev1.ResourceStorage] = newSize

err := s.client.Update(ctx, pvc)
if err != nil {
return fmt.Errorf("failed to increase pvc size: %w", err)
}

return nil
}

return nil
}

func (s DiskService) IsImportDone(dv *cdiv1.DataVolume, pvc *corev1.PersistentVolumeClaim) bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ package service

import "errors"

var ErrTooSmallDiskSize = errors.New("virtual disk size is too small")

var (
ErrStorageClassNotFound = errors.New("storage class not found")
ErrDefaultStorageClassNotFound = errors.New("default storage class not found")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
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 internal

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestHandlers(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Handlers")
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,25 @@ limitations under the License.
package internal

import (
"context"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"

"github.com/deckhouse/virtualization-controller/pkg/controller/supplements"
"github.com/deckhouse/virtualization-controller/pkg/controller/vd/internal/source"
virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2"
)

//go:generate moq -rm -out mock.go . Handler Sources
//go:generate moq -rm -out mock.go . Handler Sources DiskService

type Handler = source.Handler

type Sources interface {
Get(dsType virtv2.DataSourceType) (source.Handler, bool)
}

type DiskService interface {
Resize(ctx context.Context, pvc *corev1.PersistentVolumeClaim, newSize resource.Quantity) error
GetPersistentVolumeClaim(ctx context.Context, sup *supplements.Generator) (*corev1.PersistentVolumeClaim, error)
}
131 changes: 131 additions & 0 deletions images/virtualization-artifact/pkg/controller/vd/internal/mock.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 @@ -19,8 +19,10 @@ package internal
import (
"context"
"errors"
"fmt"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

Expand All @@ -32,10 +34,10 @@ import (
)

type ResizingHandler struct {
diskService *service.DiskService
diskService DiskService
}

func NewResizingHandler(diskService *service.DiskService) *ResizingHandler {
func NewResizingHandler(diskService DiskService) *ResizingHandler {
return &ResizingHandler{
diskService: diskService,
}
Expand All @@ -59,8 +61,8 @@ func (h ResizingHandler) Handle(ctx context.Context, vd *virtv2.VirtualDisk) (re
return reconcile.Result{}, nil
}

newSize := vd.Spec.PersistentVolumeClaim.Size
if newSize == nil {
vdSpecSize := vd.Spec.PersistentVolumeClaim.Size
if vdSpecSize == nil {
condition.Status = metav1.ConditionFalse
condition.Reason = vdcondition.NotRequested
condition.Message = ""
Expand All @@ -85,33 +87,58 @@ func (h ResizingHandler) Handle(ctx context.Context, vd *virtv2.VirtualDisk) (re
return reconcile.Result{}, errors.New("pvc not found for ready virtual disk")
}

if newSize.Equal(pvc.Status.Capacity[corev1.ResourceStorage]) {
if condition.Reason == vdcondition.InProgress {
condition.Status = metav1.ConditionTrue
condition.Reason = vdcondition.Resized
condition.Message = ""
return reconcile.Result{}, nil
pvcSpecSize := pvc.Spec.Resources.Requests[corev1.ResourceStorage]
switch vdSpecSize.Cmp(pvcSpecSize) {
// Expected disk size is LESS THAN expected pvc size: no resize needed as resizing to a smaller size is not possible.
case -1:
condition.Status = metav1.ConditionFalse
condition.Reason = vdcondition.NotRequested
condition.Message = fmt.Sprintf("The virtual disk size is too low: should be >= %s.", pvcSpecSize.String())
return reconcile.Result{}, nil
// Expected disk size is GREATER THAN expected pvc size: resize needed, resizing to a larger size.
case 1:
err = h.diskService.Resize(ctx, pvc, *vdSpecSize)
if err != nil {
return reconcile.Result{}, err
}

vd.Status.Phase = virtv2.DiskResizing

condition.Status = metav1.ConditionFalse
condition.Reason = vdcondition.NotRequested
condition.Message = ""
condition.Reason = vdcondition.InProgress
condition.Message = "The virtual disk resizing has started."
return reconcile.Result{}, nil
// Expected disk size is EQUAL TO expected pvc size: cannot definitively say whether the resize has already happened or was not needed - perform additional checks.
case 0:
}

var vdStatusSize resource.Quantity
vdStatusSize, err = resource.ParseQuantity(vd.Status.Capacity)
if err != nil {
return reconcile.Result{}, err
}

err = h.diskService.Resize(ctx, pvc, *newSize, supgen)
switch {
case err == nil:
pvcStatusSize := pvc.Status.Capacity[corev1.ResourceStorage]

// Expected pvc size is GREATER THAN actual pvc size: resize has been requested and is in progress.
if pvcSpecSize.Cmp(pvcStatusSize) == 1 {
vd.Status.Phase = virtv2.DiskResizing

condition.Status = metav1.ConditionFalse
condition.Reason = vdcondition.InProgress
condition.Message = "The virtual disk is in the process of resizing."
return reconcile.Result{}, nil
case errors.Is(err, service.ErrTooSmallDiskSize):
condition.Status = metav1.ConditionFalse
condition.Reason = vdcondition.TooSmallDiskSize
condition.Message = "The new size of the virtual disk must not be smaller than the current size."
return reconcile.Result{}, nil
default:
return reconcile.Result{}, err
}

// Virtual disk size DOES NOT MATCH pvc size: resize has completed, synchronize the virtual disk size.
if !vdStatusSize.Equal(pvcStatusSize) {
vd.Status.Capacity = pvcStatusSize.String()
condition.Status = metav1.ConditionTrue
condition.Reason = vdcondition.Resized
condition.Message = ""
return reconcile.Result{Requeue: true}, nil
}

// Expected pvc size is NOT GREATER THAN actual PVC size AND virtual disk size MATCHES pvc size: keep previous status.
return reconcile.Result{}, nil
}
Loading