Skip to content
Draft
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
23 changes: 23 additions & 0 deletions api/core/v1alpha2/cvicondition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,17 @@ const (
DatasourceReadyType Type = "DatasourceReady"
// ReadyType indicates whether the import process succeeded and the `ClusterVirtualImage` is ready for use.
ReadyType Type = "Ready"
// InUseType indicates that the `ClusterVirtualImage` is used by other resources and cannot be deleted now.
InUseType Type = "InUse"
)

type (
// DatasourceReadyReason represents the various reasons for the DatasourceReady condition type.
DatasourceReadyReason string
// ReadyReason represents the various reasons for the Ready condition type.
ReadyReason string
// InUseReason represents the various reasons for the InUseType condition type.
InUseReason string
)

func (s DatasourceReadyReason) String() string {
Expand All @@ -45,6 +49,10 @@ func (s ReadyReason) String() string {
return string(s)
}

func (s InUseReason) String() string {
return string(s)
}

const (
// DatasourceReady indicates that the datasource is ready for use, allowing the import process to start.
DatasourceReady DatasourceReadyReason = "DatasourceReady"
Expand Down Expand Up @@ -73,4 +81,19 @@ const (
ProvisioningFailed ReadyReason = "ProvisioningFailed"
// Ready indicates that the import process is complete and the `ClusterVirtualImage` is ready for use.
Ready ReadyReason = "Ready"

/*
A ClusterVirtualImage can be considered in use if it meets the following two criteria:
1) Provisioning of the ClusterVirtualImage must be completed. The ReadyCondition must be True.
2) The ClusterVirtualImage must be used in one of the following ways:
- Be attached to one or more VirtualMachines (all VirtualMachine phases except Stopped)
- Be attached via a VirtualMachineBlockDeviceAttachment (any VMBDA phases)
- Be used for provisioning VirtualImage (phases: Pending, Provisioning, Failed)
- Be used for provisioning ClusterVirtualImage (phases: Pending, Provisioning, Failed)
- Be used for provisioning VirtualDisk (phases: Pending, Provisioning, WaitForFirstConsumer, Failed)
*/
// InUse indicates that the `ClusterVirtualImage` is used by other resources and cannot be deleted now.
InUse InUseReason = "InUse"
// NotInUse indicates that the `ClusterVirtualImage` is not used by other resources and can be deleted now.
NotInUse InUseReason = "NotInUse"
)
23 changes: 23 additions & 0 deletions api/core/v1alpha2/vicondition/condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const (
ReadyType Type = "Ready"
// StorageClassReadyType indicates whether the storageClass ready.
StorageClassReadyType Type = "StorageClassReady"
// InUseType indicates that the `VirtualImage` is used by other resources and cannot be deleted now.
InUseType Type = "InUse"
)

type (
Expand All @@ -39,6 +41,8 @@ type (
ReadyReason string
// StorageClassReadyReason represents the various reasons for the StorageClassReady condition type.
StorageClassReadyReason string
// InUseReason represents the various reasons for the InUseType condition type.
InUseReason string
)

func (s DatasourceReadyReason) String() string {
Expand All @@ -53,6 +57,10 @@ func (s StorageClassReadyReason) String() string {
return string(s)
}

func (s InUseReason) String() string {
return string(s)
}

const (
// DatasourceReady indicates that the datasource is ready for use, allowing the import process to start.
DatasourceReady DatasourceReadyReason = "DatasourceReady"
Expand Down Expand Up @@ -99,4 +107,19 @@ const (
StorageClassNotFound StorageClassReadyReason = "StorageClassNotFound"
// DVCRTypeUsed indicates that the DVCR provisioning chosen.
DVCRTypeUsed StorageClassReadyReason = "DVCRTypeUsed"

/*
A VirtualImage can be considered in use if it meets the following two criteria:
1) Provisioning of the VirtualImage must be completed. The ReadyCondition must be True or have the Reason PVCLost.
2) The VirtualImage must be used in one of the following ways:
- Be attached to one or more VirtualMachines (all VirtualMachine phases except Stopped)
- Be attached via a VirtualMachineBlockDeviceAttachment (any VMBDA phases)
- Be used for provisioning VirtualImage (phases: Pending, Provisioning, Failed)
- Be used for provisioning ClusterVirtualImage (phases: Pending, Provisioning, Failed)
- Be used for provisioning VirtualDisk (phases: Pending, Provisioning, WaitForFirstConsumer, Failed)
*/
// InUse indicates that the `VirtualImage` is used by other resources and cannot be deleted now.
InUse InUseReason = "InUse"
// InUse indicates that the `VirtualImage` is not used by other resources and can be deleted now.
NotInUse InUseReason = "NotInUse"
)
20 changes: 17 additions & 3 deletions images/virtualization-artifact/pkg/builder/cvi/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ limitations under the License.
package cvi

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/deckhouse/virtualization-controller/pkg/builder/meta"
"github.com/deckhouse/virtualization/api/core/v1alpha2"
)
Expand All @@ -34,8 +36,20 @@ func WithPhase(phase v1alpha2.ImagePhase) func(vi *v1alpha2.ClusterVirtualImage)
}
}

func WithCDROM(cdrom bool) func(vi *v1alpha2.ClusterVirtualImage) {
return func(vi *v1alpha2.ClusterVirtualImage) {
vi.Status.CDROM = cdrom
func WithCDROM(cdrom bool) func(cvi *v1alpha2.ClusterVirtualImage) {
return func(cvi *v1alpha2.ClusterVirtualImage) {
cvi.Status.CDROM = cdrom
}
}

func WithDatasource(datasource v1alpha2.ClusterVirtualImageDataSource) func(cvi *v1alpha2.ClusterVirtualImage) {
return func(cvi *v1alpha2.ClusterVirtualImage) {
cvi.Spec.DataSource = datasource
}
}

func WithCondition(condition metav1.Condition) func(cvi *v1alpha2.ClusterVirtualImage) {
return func(cvi *v1alpha2.ClusterVirtualImage) {
cvi.Status.Conditions = append(cvi.Status.Conditions, condition)
}
}
14 changes: 14 additions & 0 deletions images/virtualization-artifact/pkg/builder/vd/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ limitations under the License.
package vd

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/deckhouse/virtualization-controller/pkg/builder/meta"
"github.com/deckhouse/virtualization/api/core/v1alpha2"
)
Expand All @@ -28,3 +30,15 @@ var (
WithAnnotation = meta.WithAnnotation[*v1alpha2.VirtualDisk]
WithAnnotations = meta.WithAnnotations[*v1alpha2.VirtualDisk]
)

func WithDatasource(datasource *v1alpha2.VirtualDiskDataSource) func(vd *v1alpha2.VirtualDisk) {
return func(vd *v1alpha2.VirtualDisk) {
vd.Spec.DataSource = datasource
}
}

func WithCondition(condition metav1.Condition) func(vi *v1alpha2.VirtualDisk) {
return func(vd *v1alpha2.VirtualDisk) {
vd.Status.Conditions = append(vd.Status.Conditions, condition)
}
}
14 changes: 14 additions & 0 deletions images/virtualization-artifact/pkg/builder/vi/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ limitations under the License.
package vi

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/deckhouse/virtualization-controller/pkg/builder/meta"
"github.com/deckhouse/virtualization/api/core/v1alpha2"
)
Expand All @@ -40,3 +42,15 @@ func WithCDROM(cdrom bool) func(vi *v1alpha2.VirtualImage) {
vi.Status.CDROM = cdrom
}
}

func WithDatasource(datasource v1alpha2.VirtualImageDataSource) func(vi *v1alpha2.VirtualImage) {
return func(vi *v1alpha2.VirtualImage) {
vi.Spec.DataSource = datasource
}
}

func WithCondition(condition metav1.Condition) func(vi *v1alpha2.VirtualImage) {
return func(vi *v1alpha2.VirtualImage) {
vi.Status.Conditions = append(vi.Status.Conditions, condition)
}
}
45 changes: 45 additions & 0 deletions images/virtualization-artifact/pkg/builder/vmbda/option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright 2025 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 vmbda

import (
"github.com/deckhouse/virtualization-controller/pkg/builder/meta"
"github.com/deckhouse/virtualization/api/core/v1alpha2"
)

type Option func(vd *v1alpha2.VirtualMachineBlockDeviceAttachment)

var (
WithName = meta.WithName[*v1alpha2.VirtualMachineBlockDeviceAttachment]
WithNamespace = meta.WithNamespace[*v1alpha2.VirtualMachineBlockDeviceAttachment]
WithLabel = meta.WithLabel[*v1alpha2.VirtualMachineBlockDeviceAttachment]
WithLabels = meta.WithLabels[*v1alpha2.VirtualMachineBlockDeviceAttachment]
WithAnnotation = meta.WithAnnotation[*v1alpha2.VirtualMachineBlockDeviceAttachment]
WithAnnotations = meta.WithAnnotations[*v1alpha2.VirtualMachineBlockDeviceAttachment]
)

func WithBlockDeviceRef(bdRef v1alpha2.VMBDAObjectRef) func(vmbda *v1alpha2.VirtualMachineBlockDeviceAttachment) {
return func(vmbda *v1alpha2.VirtualMachineBlockDeviceAttachment) {
vmbda.Spec.BlockDeviceRef = bdRef
}
}

func WithVMName(vmName string) func(vmbda *v1alpha2.VirtualMachineBlockDeviceAttachment) {
return func(vmbda *v1alpha2.VirtualMachineBlockDeviceAttachment) {
vmbda.Spec.VirtualMachineName = vmName
}
}
51 changes: 51 additions & 0 deletions images/virtualization-artifact/pkg/builder/vmbda/vmbda.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
Copyright 2025 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 vmbda

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/deckhouse/virtualization/api/core/v1alpha2"
)

func New(options ...Option) *v1alpha2.VirtualMachineBlockDeviceAttachment {
vmbda := NewEmpty("", "")
ApplyOptions(vmbda, options)
return vmbda
}

func ApplyOptions(vmbda *v1alpha2.VirtualMachineBlockDeviceAttachment, opts []Option) {
if vmbda == nil {
return
}
for _, opt := range opts {
opt(vmbda)
}
}

func NewEmpty(name, namespace string) *v1alpha2.VirtualMachineBlockDeviceAttachment {
return &v1alpha2.VirtualMachineBlockDeviceAttachment{
TypeMeta: metav1.TypeMeta{
APIVersion: v1alpha2.SchemeGroupVersion.String(),
Kind: v1alpha2.VirtualMachineBlockDeviceAttachmentKind,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ func NewController(
mgr.GetClient(),
internal.NewDatasourceReadyHandler(sources),
internal.NewLifeCycleHandler(sources, mgr.GetClient()),
internal.NewInUseHandler(mgr.GetClient()),
internal.NewDeletionHandler(sources),
internal.NewAttacheeHandler(mgr.GetClient()),
)

cviController, err := controller.New(ControllerName, mgr, controller.Options{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (

"github.com/deckhouse/virtualization-controller/pkg/controller/cvi/internal/watcher"
"github.com/deckhouse/virtualization-controller/pkg/controller/reconciler"
"github.com/deckhouse/virtualization-controller/pkg/controller/watchers"
virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2"
)

Expand Down Expand Up @@ -109,16 +108,17 @@ func (r *Reconciler) SetupController(_ context.Context, mgr manager.Manager, ctr
}
}

cviFromVIEnqueuer := watchers.NewClusterVirtualImageRequestEnqueuer(mgr.GetClient(), &virtv2.VirtualImage{}, virtv2.ClusterVirtualImageObjectRefKindVirtualImage)
viWatcher := watchers.NewObjectRefWatcher(watchers.NewVirtualImageFilter(), cviFromVIEnqueuer)
if err := viWatcher.Run(mgr, ctr); err != nil {
return fmt.Errorf("error setting watch on VIs: %w", err)
}

cviFromCVIEnqueuer := watchers.NewClusterVirtualImageRequestEnqueuer(mgr.GetClient(), &virtv2.ClusterVirtualImage{}, virtv2.ClusterVirtualImageObjectRefKindClusterVirtualImage)
cviWatcher := watchers.NewObjectRefWatcher(watchers.NewClusterVirtualImageFilter(), cviFromCVIEnqueuer)
if err := cviWatcher.Run(mgr, ctr); err != nil {
return fmt.Errorf("error setting watch on CVIs: %w", err)
for _, w := range []Watcher{
watcher.NewClusterVirtualImageWatcher(mgr.GetClient()),
watcher.NewVirtualImageWatcher(mgr.GetClient()),
watcher.NewVirtualDiskWatcher(mgr.GetClient()),
watcher.NewVirtualDiskSnapshotWatcher(mgr.GetClient()),
watcher.NewVirtualMachineBlockDeviceAttachmentWatcher(mgr.GetClient()),
} {
err := w.Watch(mgr, ctr)
if err != nil {
return fmt.Errorf("error setting watcher: %w", err)
}
}

return nil
Expand Down
Loading
Loading