Skip to content

Commit

Permalink
feat(cvi): snapshot objectRef (#640)
Browse files Browse the repository at this point in the history
Add the ability to create a ClusterVirtualImage from a VirtualDiskSnapshot.

Signed-off-by: Daniil Antoshin <[email protected]>
  • Loading branch information
danilrwx authored Jan 29, 2025
1 parent 7992aef commit fdca2fe
Show file tree
Hide file tree
Showing 8 changed files with 574 additions and 153 deletions.
13 changes: 7 additions & 6 deletions api/core/v1alpha2/cluster_virtual_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,15 @@ type ClusterVirtualImageContainerImage struct {
CABundle []byte `json:"caBundle,omitempty"`
}

// Use an existing VirtualImage, ClusterVirtualImage, or VirtualDisk resource to create an image.
// Use an existing VirtualImage, ClusterVirtualImage, VirtualDisk or VirtualDiskSnapshot resource to create an image.
//
// +kubebuilder:validation:XValidation:rule="self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' ? has(self.__namespace__) && size(self.__namespace__) > 0 : true",message="The namespace is required for VirtualDisk and VirtualImage."
// +kubebuilder:validation:XValidation:rule="self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' ? has(self.__namespace__) && size(self.__namespace__) < 64 : true",message="The namespace must be no longer than 63 characters."
// +kubebuilder:validation:XValidation:rule="self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' || self.kind == 'VirtualDiskSnapshot' ? has(self.__namespace__) && size(self.__namespace__) > 0 : true",message="The namespace is required for VirtualDisk, VirtualImage and VirtualDiskSnapshot"
// +kubebuilder:validation:XValidation:rule="self.kind == 'VirtualImage' || self.kind == 'VirtualDisk' || self.kind == 'VirtualDiskSnapshot' ? has(self.__namespace__) && size(self.__namespace__) < 64 : true",message="The namespace must be no longer than 63 characters."
type ClusterVirtualImageObjectRef struct {
Kind ClusterVirtualImageObjectRefKind `json:"kind"`
// Name of the existing VirtualImage, ClusterVirtualImage, or VirtualDisk resource.
// Name of the existing VirtualImage, ClusterVirtualImage, VirtualDisk or VirtualDiskSnapshot resource.
Name string `json:"name"`
// Namespace where the VirtualImage or VirtualDisk resource is located.
// Namespace where the VirtualImage, VirtualDisk or VirtualDiskSnapshot resource is located.
Namespace string `json:"namespace,omitempty"`
}

Expand All @@ -115,6 +115,7 @@ const (
ClusterVirtualImageObjectRefKindVirtualImage ClusterVirtualImageObjectRefKind = "VirtualImage"
ClusterVirtualImageObjectRefKindClusterVirtualImage ClusterVirtualImageObjectRefKind = "ClusterVirtualImage"
ClusterVirtualImageObjectRefKindVirtualDisk ClusterVirtualImageObjectRefKind = "VirtualDisk"
ClusterVirtualImageObjectRefKindVirtualDiskSnapshot ClusterVirtualImageObjectRefKind = "VirtualDiskSnapshot"
)

type ClusterVirtualImageStatus struct {
Expand All @@ -137,7 +138,7 @@ type ClusterVirtualImageStatus struct {
Phase ImagePhase `json:"phase,omitempty"`
// Progress of copying an image from the source to DVCR. Appears only during the `Provisioning' phase.
Progress string `json:"progress,omitempty"`
// UID of the source (VirtualImage, ClusterVirtualImage, or VirtualDisk) used when creating the cluster virtual image.
// UID of the source (VirtualImage, ClusterVirtualImage, VirtualDisk or VirtualDiskSnapshot) used when creating the cluster virtual image.
SourceUID *types.UID `json:"sourceUID,omitempty"`
// The latest available observations of an object's current state.
Conditions []metav1.Condition `json:"conditions,omitempty"`
Expand Down
252 changes: 126 additions & 126 deletions api/pkg/apiserver/api/generated/openapi/zz_generated.openapi.go

Large diffs are not rendered by default.

25 changes: 14 additions & 11 deletions crds/clustervirtualimages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ spec:
objectRef:
description:
Use an existing VirtualImage, ClusterVirtualImage,
or VirtualDisk resource to create an image.
VirtualDisk or VirtualDiskSnapshot resource to create an image.
properties:
kind:
description:
Expand All @@ -180,28 +180,30 @@ spec:
name:
description:
Name of the existing VirtualImage, ClusterVirtualImage,
or VirtualDisk resource.
VirtualDisk or VirtualDiskSnapshot resource.
type: string
namespace:
description:
Namespace where the VirtualImage or VirtualDisk
resource is located.
Namespace where the VirtualImage, VirtualDisk
or VirtualDiskSnapshot resource is located.
type: string
required:
- kind
- name
type: object
x-kubernetes-validations:
- message: The namespace is required for VirtualDisk and VirtualImage.
- message:
The namespace is required for VirtualDisk, VirtualImage
and VirtualDiskSnapshot
rule:
"self.kind == 'VirtualImage' || self.kind == 'VirtualDisk'
? has(self.__namespace__) && size(self.__namespace__) > 0
: true"
|| self.kind == 'VirtualDiskSnapshot' ? has(self.__namespace__)
&& size(self.__namespace__) > 0 : true"
- message: The namespace must be no longer than 63 characters.
rule:
"self.kind == 'VirtualImage' || self.kind == 'VirtualDisk'
? has(self.__namespace__) && size(self.__namespace__) < 64
: true"
"self.kind == 'VirtualImage' || self.kind == 'VirtualDisk'
|| self.kind == 'VirtualDiskSnapshot' ? has(self.__namespace__)
&& size(self.__namespace__) < 64 : true"
type:
description: |-
The following image sources are available for creating an image:
Expand Down Expand Up @@ -391,7 +393,8 @@ spec:
sourceUID:
description:
UID of the source (VirtualImage, ClusterVirtualImage,
or VirtualDisk) used when creating the cluster virtual image.
VirtualDisk or VirtualDiskSnapshot) used when creating the cluster
virtual image.
type: string
target:
properties:
Expand Down
10 changes: 5 additions & 5 deletions crds/doc-ru-clustervirtualimages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,17 +71,17 @@ spec:
* xz.
objectRef:
description: |
Использование существующего ресурса VirtualImage, ClusterVirtualImage или VirtualDisk для создания образа.
Использование существующего ресурса VirtualImage, ClusterVirtualImage, VirtualDisk или VirtualDiskSnapshot для создания образа.
properties:
kind:
description: |
Ссылка на существующий ресурс VirtualImage, ClusterVirtualImage или VirtualDisk.
Ссылка на существующий ресурс VirtualImage, ClusterVirtualImage, VirtualDisk или VirtualDiskSnapshot.
name:
description: |
Имя существующего ресурса VirtualImage, ClusterVirtualImage или VirtualDisk.
Имя существующего ресурса VirtualImage, ClusterVirtualImage, VirtualDisk или VirtualDiskSnapshot.
namespace:
description: |
Пространство имён, в котором расположен ресурс VirtualImage или VirtualDisk.
Пространство имён, в котором расположен ресурс VirtualImage, VirtualDisk или VirtualDiskSnapshot.
type:
description: |
Доступные типы источников для создания образа:
Expand Down Expand Up @@ -182,7 +182,7 @@ spec:
Команда для загрузки образа с использованием `Service` внутри кластера.
sourceUID:
description: |
UID источника (VirtualImage, ClusterVirtualImage или VirtualDisk), использованного при создании кластерного виртуального образа.
UID источника (VirtualImage, ClusterVirtualImage, VirtualDisk или VirtualDiskSnapshot), использованного при создании кластерного виртуального образа.
observedGeneration:
description: |
Поколение ресурса, которое в последний раз обрабатывалось контроллером.
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ func NewController(
protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerCVIProtection)
importer := service.NewImporterService(dvcr, mgr.GetClient(), importerImage, requirements, PodPullPolicy, PodVerbose, ControllerName, protection)
uploader := service.NewUploaderService(dvcr, mgr.GetClient(), uploaderImage, requirements, PodPullPolicy, PodVerbose, ControllerName, protection)
disk := service.NewDiskService(mgr.GetClient(), dvcr, protection)
recorder := eventrecord.NewEventRecorderLogger(mgr, ControllerName)

sources := source.NewSources()
sources.Set(virtv2.DataSourceTypeHTTP, source.NewHTTPDataSource(recorder, stat, importer, dvcr, ns))
sources.Set(virtv2.DataSourceTypeContainerImage, source.NewRegistryDataSource(recorder, stat, importer, dvcr, mgr.GetClient(), ns))
sources.Set(virtv2.DataSourceTypeObjectRef, source.NewObjectRefDataSource(recorder, stat, importer, dvcr, mgr.GetClient(), ns))
sources.Set(virtv2.DataSourceTypeObjectRef, source.NewObjectRefDataSource(recorder, stat, importer, disk, dvcr, mgr.GetClient(), ns))
sources.Set(virtv2.DataSourceTypeUpload, source.NewUploadDataSource(recorder, stat, uploader, dvcr, ns))

reconciler := NewReconciler(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,17 @@ func NewVirtualDiskNotAllowedForUseError(name string) error {
name: name,
}
}

type VirtualDiskSnapshotNotReadyError struct {
name string
}

func (e VirtualDiskSnapshotNotReadyError) Error() string {
return fmt.Sprintf("VirtualDiskSnapshot %s not ready", e.name)
}

func NewVirtualDiskSnapshotNotReadyError(name string) error {
return VirtualDiskSnapshotNotReadyError{
name: name,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,33 +47,38 @@ import (
type ObjectRefDataSource struct {
statService Stat
importerService Importer
diskService *service.DiskService
dvcrSettings *dvcr.Settings
client client.Client
controllerNamespace string
recorder eventrecord.EventRecorderLogger

viOnPvcSyncer *ObjectRefVirtualImageOnPvc
vdSyncer *ObjectRefVirtualDisk
viOnPvcSyncer *ObjectRefVirtualImageOnPvc
vdSyncer *ObjectRefVirtualDisk
vdSnapshotSyncer *ObjectRefVirtualDiskSnapshot
}

func NewObjectRefDataSource(
recorder eventrecord.EventRecorderLogger,
statService Stat,
importerService Importer,
diskService *service.DiskService,
dvcrSettings *dvcr.Settings,
client client.Client,
controllerNamespace string,
) *ObjectRefDataSource {
return &ObjectRefDataSource{
statService: statService,
importerService: importerService,
diskService: diskService,
dvcrSettings: dvcrSettings,
client: client,
controllerNamespace: controllerNamespace,
recorder: recorder,

viOnPvcSyncer: NewObjectRefVirtualImageOnPvc(recorder, importerService, dvcrSettings, statService),
vdSyncer: NewObjectRefVirtualDisk(recorder, importerService, client, controllerNamespace, dvcrSettings, statService),
viOnPvcSyncer: NewObjectRefVirtualImageOnPvc(recorder, importerService, dvcrSettings, statService),
vdSyncer: NewObjectRefVirtualDisk(recorder, importerService, client, controllerNamespace, dvcrSettings, statService),
vdSnapshotSyncer: NewObjectRefVirtualDiskSnapshot(recorder, importerService, diskService, client, controllerNamespace, dvcrSettings, statService),
}
}

Expand Down Expand Up @@ -116,6 +121,19 @@ func (ds ObjectRefDataSource) Sync(ctx context.Context, cvi *virtv2.ClusterVirtu
}

return ds.vdSyncer.Sync(ctx, cvi, vd, cb)

case virtv2.VirtualDiskSnapshotKind:
vdSnapshotKey := types.NamespacedName{Name: cvi.Spec.DataSource.ObjectRef.Name, Namespace: cvi.Spec.DataSource.ObjectRef.Namespace}
vdSnapshot, err := object.FetchObject(ctx, vdSnapshotKey, ds.client, &virtv2.VirtualDiskSnapshot{})
if err != nil {
return reconcile.Result{}, fmt.Errorf("unable to get VDSnapshot %s: %w", vdSnapshotKey, err)
}

if vdSnapshot == nil {
return reconcile.Result{}, fmt.Errorf("VDSnapshot object ref %s is nil", vdSnapshotKey)
}

return ds.vdSnapshotSyncer.Sync(ctx, cvi, vdSnapshot, cb)
}

supgen := supplements.NewGenerator(annotations.CVIShortName, cvi.Name, ds.controllerNamespace, cvi.UID)
Expand Down Expand Up @@ -336,6 +354,18 @@ func (ds ObjectRefDataSource) Validate(ctx context.Context, cvi *virtv2.ClusterV
}

return NewClusterImageNotReadyError(cvi.Spec.DataSource.ObjectRef.Name)
case virtv2.VirtualDiskSnapshotKind:
vdSnapshotKey := types.NamespacedName{Name: cvi.Spec.DataSource.ObjectRef.Name, Namespace: cvi.Spec.DataSource.ObjectRef.Namespace}
vdSnapshot, err := object.FetchObject(ctx, vdSnapshotKey, ds.client, &virtv2.VirtualDiskSnapshot{})
if err != nil {
return fmt.Errorf("unable to get VDSnapshot %s: %w", vdSnapshotKey, err)
}

if vdSnapshot == nil {
return fmt.Errorf("VDSnapshot object ref %s is nil", vdSnapshotKey)
}

return ds.vdSnapshotSyncer.Validate(ctx, cvi)
case virtv2.ClusterVirtualImageObjectRefKindVirtualDisk:
return ds.vdSyncer.Validate(ctx, cvi)
default:
Expand Down
Loading

0 comments on commit fdca2fe

Please sign in to comment.