Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 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
76 changes: 76 additions & 0 deletions images/dvcr-artifact/pkg/datasource/filesystem-datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
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 datasource

import (
"context"
"fmt"
"io"
"os"

"github.com/google/uuid"
)

type FilesystemDataSource struct {
readCloser io.ReadCloser
sourceImageSize int64
sourceImageFilename string
}

func NewFilesystemDataSource(ctx context.Context) (*FilesystemDataSource, error) {
filesystemImagePath := "/tmp/fs/disk.img"

file, err := os.Open(filesystemImagePath)
if err != nil {
return nil, fmt.Errorf("can not get open image %s: %w", filesystemImagePath, err)
}

sourceImageSize, err := file.Seek(0, io.SeekEnd)
if err != nil {
return nil, fmt.Errorf("error seeking to end: %w", err)
}

_, err = file.Seek(0, io.SeekStart)
if err != nil {
return nil, fmt.Errorf("error seeking to start: %w", err)
}

uuid, _ := uuid.NewUUID()
sourceImageFilename := uuid.String() + ".img"

return &FilesystemDataSource{
readCloser: file,
sourceImageSize: int64(sourceImageSize),
sourceImageFilename: sourceImageFilename,
}, nil
}

func (ds *FilesystemDataSource) ReadCloser() (io.ReadCloser, error) {
return ds.readCloser, nil
}

func (ds *FilesystemDataSource) Length() (int, error) {
return int(ds.sourceImageSize), nil
}

func (ds *FilesystemDataSource) Filename() (string, error) {
return ds.sourceImageFilename, nil
}

func (ds *FilesystemDataSource) Close() error {
return ds.readCloser.Close()
}
9 changes: 8 additions & 1 deletion images/dvcr-artifact/pkg/importer/importer.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const (
DockerRegistrySchemePrefix = "docker://"
DVCRSource = "dvcr"
BlockDeviceSource = "blockDevice"
FilesystemSource = "filesystem"
)

func New() *Importer {
Expand Down Expand Up @@ -180,7 +181,7 @@ func (i *Importer) runForDataSource(ctx context.Context) error {
return monitoring.WriteImportCompleteMessage(res.SourceImageSize, res.VirtualSize, res.AvgSpeed, res.Format, durCollector.Collect())
}

func (i *Importer) newDataSource(_ context.Context) (datasource.DataSourceInterface, error) {
func (i *Importer) newDataSource(ctx context.Context) (datasource.DataSourceInterface, error) {
var result datasource.DataSourceInterface
switch i.srcType {
case cc.SourceHTTP:
Expand All @@ -201,6 +202,12 @@ func (i *Importer) newDataSource(_ context.Context) (datasource.DataSourceInterf
if err != nil {
return nil, fmt.Errorf("error creating block device data source: %w", err)
}
case FilesystemSource:
var err error
result, err = datasource.NewFilesystemDataSource(ctx)
if err != nil {
return nil, fmt.Errorf("error creating filesystem data source: %w", err)
}
default:
return nil, fmt.Errorf("unknown source type: %s", i.srcType)
}
Expand Down
6 changes: 6 additions & 0 deletions images/virtualization-artifact/pkg/common/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ const (
ImportProxyNoProxy = "no_proxy"
// ImporterProxyCertDirVar provides a constant to capture our env variable "IMPORTER_PROXY_CERT_DIR"
ImporterProxyCertDirVar = "IMPORTER_PROXY_CERT_DIR"
// ImporterFilesystemVar provides a constant to capture our env variable "IMPORTER_FILESYSTEM"
ImporterFilesystemVar = "IMPORTER_FILESYSTEM"
// ImporterFilesystemDir provides a constant to capture our env variable "IMPORTER_FILESYSTEM_DIR"
ImporterFilesystemDir = "/tmp/fs"
// ImporterBlockDeviceDir provides a constant to capture our directory for block device
ImporterBlockDeviceDir = "/dev/xvda"

// ImporterDestinationAuthConfigDir is a mount directory for auth Secret.
ImporterDestinationAuthConfigDir = "/dvcr-auth"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func (imp *Bounder) addVolumes(pod *corev1.Pod, container *corev1.Container) {
},
corev1.VolumeDevice{
Name: "volume",
DevicePath: "/dev/xvda",
DevicePath: common.ImporterBlockDeviceDir,
},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

Expand Down Expand Up @@ -111,7 +112,18 @@ func (ds ObjectRefVirtualDisk) Sync(ctx context.Context, cvi *v1alpha2.ClusterVi
cvi.Status.Progress = ds.statService.GetProgress(cvi.GetUID(), pod, cvi.Status.Progress)
cvi.Status.Target.RegistryURL = ds.statService.GetDVCRImageName(pod)

envSettings := ds.getEnvSettings(cvi, supgen)
pvc := &corev1.PersistentVolumeClaim{}
err := ds.client.Get(ctx, types.NamespacedName{Name: vdRef.Status.Target.PersistentVolumeClaim, Namespace: vdRef.Namespace}, pvc)
if err != nil {
return reconcile.Result{}, err
}

var envSettings *importer.Settings
if pvc.Spec.VolumeMode != nil {
envSettings = ds.getEnvSettings(cvi, supgen, pvc.Spec.VolumeMode)
} else {
envSettings = ds.getEnvSettings(cvi, supgen, ptr.To(corev1.PersistentVolumeBlock))
}

ownerRef := metav1.NewControllerRef(cvi, cvi.GroupVersionKind())
podSettings := ds.importerService.GetPodSettingsWithPVC(ownerRef, supgen, vdRef.Status.Target.PersistentVolumeClaim, vdRef.Namespace)
Expand Down Expand Up @@ -216,9 +228,15 @@ func (ds ObjectRefVirtualDisk) CleanUp(ctx context.Context, cvi *v1alpha2.Cluste
return ds.importerService.DeletePod(ctx, cvi, controllerName, supgen)
}

func (ds ObjectRefVirtualDisk) getEnvSettings(cvi *v1alpha2.ClusterVirtualImage, sup supplements.Generator) *importer.Settings {
func (ds ObjectRefVirtualDisk) getEnvSettings(cvi *v1alpha2.ClusterVirtualImage, sup supplements.Generator, volumeMode *corev1.PersistentVolumeMode) *importer.Settings {
var settings importer.Settings
importer.ApplyBlockDeviceSourceSettings(&settings)

if volumeMode != nil && *volumeMode == corev1.PersistentVolumeFilesystem {
importer.ApplyFilesystemSourceSettings(&settings)
} else {
importer.ApplyBlockDeviceSourceSettings(&settings)
}

importer.ApplyDVCRDestinationSettings(
&settings,
ds.dvcrSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func (ds ObjectRefVirtualDiskSnapshot) Sync(ctx context.Context, cvi *v1alpha2.C
cvi.Status.Progress = ds.statService.GetProgress(cvi.GetUID(), pod, cvi.Status.Progress)
cvi.Status.Target.RegistryURL = ds.statService.GetDVCRImageName(pod)

envSettings := ds.getEnvSettings(cvi, supgen)
envSettings := ds.getEnvSettings(cvi, supgen, pvc.Spec.VolumeMode)

ownerRef := metav1.NewControllerRef(cvi, cvi.GroupVersionKind())
podSettings := ds.importerService.GetPodSettingsWithPVC(ownerRef, supgen, pvc.Name, pvc.Namespace)
Expand Down Expand Up @@ -358,9 +358,15 @@ func (ds ObjectRefVirtualDiskSnapshot) CleanUp(ctx context.Context, cvi *v1alpha
return importerRequeue || diskRequeue, nil
}

func (ds ObjectRefVirtualDiskSnapshot) getEnvSettings(cvi *v1alpha2.ClusterVirtualImage, sup supplements.Generator) *importer.Settings {
func (ds ObjectRefVirtualDiskSnapshot) getEnvSettings(cvi *v1alpha2.ClusterVirtualImage, sup supplements.Generator, volumeMode *corev1.PersistentVolumeMode) *importer.Settings {
var settings importer.Settings
importer.ApplyBlockDeviceSourceSettings(&settings)

if volumeMode != nil && *volumeMode == corev1.PersistentVolumeFilesystem {
importer.ApplyFilesystemSourceSettings(&settings)
} else {
importer.ApplyBlockDeviceSourceSettings(&settings)
}

importer.ApplyDVCRDestinationSettings(
&settings,
ds.dvcrSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ func (imp *Importer) makeImporterPodSpec() (*corev1.Pod, error) {
}
}

annotations.SetRecommendedLabels(&pod, imp.PodSettings.InstallerLabels, imp.PodSettings.ControllerName)
podutil.SetRestrictedSecurityContext(&pod.Spec)

container := imp.makeImporterContainerSpec()
imp.addVolumes(&pod, container)
pod.Spec.Containers = append(pod.Spec.Containers, *container)

annotations.SetRecommendedLabels(&pod, imp.PodSettings.InstallerLabels, imp.PodSettings.ControllerName)
podutil.SetRestrictedSecurityContext(&pod.Spec)

return &pod, nil
}

Expand Down Expand Up @@ -365,21 +365,19 @@ func (imp *Importer) addVolumes(pod *corev1.Pod, container *corev1.Container) {
}

if imp.PodSettings.PVCName != "" {
podutil.AddVolumeDevice(
pod,
container,
corev1.Volume{
Name: "volume",
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: imp.PodSettings.PVCName,
},
volume := corev1.Volume{
Name: "volume",
VolumeSource: corev1.VolumeSource{
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
ClaimName: imp.PodSettings.PVCName,
},
},
corev1.VolumeDevice{
Name: "volume",
DevicePath: "/dev/xvda",
},
)
}

if imp.EnvSettings.Source == SourceFilesystem {
podutil.AddVolume(pod, container, volume, corev1.VolumeMount{Name: "volume", MountPath: common.ImporterFilesystemDir}, corev1.EnvVar{Name: common.ImporterFilesystemVar, Value: common.ImporterFilesystemDir})
} else {
podutil.AddVolumeDevice(pod, container, volume, corev1.VolumeDevice{Name: "volume", DevicePath: common.ImporterBlockDeviceDir})
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const (
SourceDVCR = "dvcr"
// SourceBlockDevice is the source type of block device
SourceBlockDevice = "blockDevice"
// SourceFilesystem is the source type of filesystem
SourceFilesystem = "filesystem"
)

// Settings stores all possible settings for dvcr-importer binary.
Expand Down Expand Up @@ -132,3 +134,8 @@ func ApplyDVCRSourceSettings(podEnvVars *Settings, dvcrImageName string) {
func ApplyBlockDeviceSourceSettings(podEnvVars *Settings) {
podEnvVars.Source = SourceBlockDevice
}

// ApplyFilesystemSourceSettings updates importer Pod settings to use filesystem as source.
func ApplyFilesystemSourceSettings(podEnvVars *Settings) {
podEnvVars.Source = SourceFilesystem
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"
cdiv1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
Expand Down Expand Up @@ -113,7 +114,18 @@ func (ds ObjectRefVirtualDisk) StoreToDVCR(ctx context.Context, vi *v1alpha2.Vir
vi.Status.Progress = ds.statService.GetProgress(vi.GetUID(), pod, vi.Status.Progress)
vi.Status.Target.RegistryURL = ds.statService.GetDVCRImageName(pod)

envSettings := ds.getEnvSettings(vi, supgen)
pvc := &corev1.PersistentVolumeClaim{}
err := ds.client.Get(ctx, types.NamespacedName{Name: vdRef.Status.Target.PersistentVolumeClaim, Namespace: vdRef.Namespace}, pvc)
if err != nil {
return reconcile.Result{}, err
}

var envSettings *importer.Settings
if pvc.Spec.VolumeMode != nil {
envSettings = ds.getEnvSettings(vi, supgen, pvc.Spec.VolumeMode)
} else {
envSettings = ds.getEnvSettings(vi, supgen, ptr.To(corev1.PersistentVolumeBlock))
}

ownerRef := metav1.NewControllerRef(vi, vi.GroupVersionKind())
podSettings := ds.importerService.GetPodSettingsWithPVC(ownerRef, supgen, vdRef.Status.Target.PersistentVolumeClaim, vdRef.Namespace)
Expand Down Expand Up @@ -411,9 +423,15 @@ func (ds ObjectRefVirtualDisk) CleanUp(ctx context.Context, vi *v1alpha2.Virtual
return importerRequeue || diskRequeue, nil
}

func (ds ObjectRefVirtualDisk) getEnvSettings(vi *v1alpha2.VirtualImage, sup supplements.Generator) *importer.Settings {
func (ds ObjectRefVirtualDisk) getEnvSettings(vi *v1alpha2.VirtualImage, sup supplements.Generator, volumeMode *corev1.PersistentVolumeMode) *importer.Settings {
var settings importer.Settings
importer.ApplyBlockDeviceSourceSettings(&settings)

if volumeMode != nil && *volumeMode == corev1.PersistentVolumeFilesystem {
importer.ApplyFilesystemSourceSettings(&settings)
} else {
importer.ApplyBlockDeviceSourceSettings(&settings)
}

importer.ApplyDVCRDestinationSettings(
&settings,
ds.dvcrSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func (ds ObjectRefVirtualDiskSnapshotCR) Sync(ctx context.Context, vi *v1alpha2.
step.NewReadyContainerRegistryStep(pod, ds.importer, ds.diskService, ds.stat, ds.recorder, cb),
step.NewTerminatingStep(pvc),
step.NewCreatePersistentVolumeClaimStep(pvc, ds.recorder, ds.client, cb),
step.NewCreatePodStep(pod, ds.dvcrSettings, ds.recorder, ds.importer, ds.stat, cb),
step.NewCreatePodStep(pod, ds.client, ds.dvcrSettings, ds.recorder, ds.importer, ds.stat, cb),
step.NewWaitForPodStep(pod, pvc, ds.stat, cb),
).Run(ctx, vi)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var _ = Describe("ObjectRef VirtualImageSnapshot ContainerRegistry", func() {
ctx context.Context
scheme *runtime.Scheme
vi *v1alpha2.VirtualImage
vd *v1alpha2.VirtualDisk
vs *vsv1.VolumeSnapshot
sc *storagev1.StorageClass
vdSnapshot *v1alpha2.VirtualDiskSnapshot
Expand Down Expand Up @@ -142,7 +143,7 @@ var _ = Describe("ObjectRef VirtualImageSnapshot ContainerRegistry", func() {
Name: "vd-snapshot",
UID: "11111111-1111-1111-1111-111111111111",
},
Spec: v1alpha2.VirtualDiskSnapshotSpec{},
Spec: v1alpha2.VirtualDiskSnapshotSpec{VirtualDiskName: "vd"},
Status: v1alpha2.VirtualDiskSnapshotStatus{
Phase: v1alpha2.VirtualDiskSnapshotPhaseReady,
VolumeSnapshotName: vs.Name,
Expand Down Expand Up @@ -185,6 +186,18 @@ var _ = Describe("ObjectRef VirtualImageSnapshot ContainerRegistry", func() {
Name: supgen.ImporterPod().Name,
},
}

vd = &v1alpha2.VirtualDisk{
ObjectMeta: metav1.ObjectMeta{
Name: "vd",
UID: "11111111-1111-1111-1111-111111111111",
},
Status: v1alpha2.VirtualDiskStatus{
Target: v1alpha2.DiskTarget{
PersistentVolumeClaim: pvc.Name,
},
},
}
})

Context("VirtualImage has just been created", func() {
Expand All @@ -208,7 +221,7 @@ var _ = Describe("ObjectRef VirtualImageSnapshot ContainerRegistry", func() {
}

vi.Status = v1alpha2.VirtualImageStatus{}
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(vdSnapshot, vs).
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(vdSnapshot, vs, vd, pvc).
WithInterceptorFuncs(interceptor.Funcs{
Create: func(_ context.Context, _ client.WithWatch, obj client.Object, _ ...client.CreateOption) error {
switch obj.(type) {
Expand Down
Loading
Loading