Skip to content

Commit

Permalink
Merge pull request kubevirt#6557 from jean-edouard/cherry-pick-6482-t…
Browse files Browse the repository at this point in the history
…o-release-0.46

[release-0.46] migration: generate empty isos on target for cloud-inits, configmaps, secrets, ...
  • Loading branch information
kubevirt-bot authored Oct 12, 2021
2 parents 3ebb0a0 + 6318f87 commit 5ed15d7
Show file tree
Hide file tree
Showing 32 changed files with 550 additions and 43 deletions.
5 changes: 5 additions & 0 deletions api/openapi-spec/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -13392,6 +13392,11 @@
"description": "Reason is a brief description of why we are in the current hotplug volume phase",
"type": "string"
},
"size": {
"description": "Represents the size of the volume",
"type": "integer",
"format": "int64"
},
"target": {
"description": "Target is the target name used when adding the volume to the VM, eg: vda",
"type": "string"
Expand Down
57 changes: 57 additions & 0 deletions pkg/cloud-init/cloud-init.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"
Expand Down Expand Up @@ -67,6 +68,7 @@ type CloudInitData struct {
UserData string
NetworkData string
DevicesData *[]DeviceData
VolumeName string
}

type PublicSSHKey struct {
Expand Down Expand Up @@ -117,6 +119,7 @@ func ReadCloudInitVolumeDataSource(vmi *v1.VirtualMachineInstance, secretSourceD

cloudInitData, err = readCloudInitNoCloudSource(volume.CloudInitNoCloud)
cloudInitData.NoCloudMetaData = readCloudInitNoCloudMetaData(vmi.Name, hostname, vmi.Namespace)
cloudInitData.VolumeName = volume.Name
return cloudInitData, err
}
if volume.CloudInitConfigDrive != nil {
Expand All @@ -128,6 +131,7 @@ func ReadCloudInitVolumeDataSource(vmi *v1.VirtualMachineInstance, secretSourceD

cloudInitData, err = readCloudInitConfigDriveSource(volume.CloudInitConfigDrive)
cloudInitData.ConfigDriveMetaData = readCloudInitConfigDriveMetaData(string(vmi.UID), vmi.Name, hostname, vmi.Namespace, keys)
cloudInitData.VolumeName = volume.Name
return cloudInitData, err
}
}
Expand Down Expand Up @@ -465,6 +469,59 @@ func removeLocalData(domain string, namespace string) error {
return err
}

func GenerateEmptyIso(vmiName string, namespace string, data *CloudInitData, size int64) error {
precond.MustNotBeEmpty(vmiName)
precond.MustNotBeNil(data)

var err error
var isoStaging, iso string

switch data.DataSource {
case DataSourceNoCloud, DataSourceConfigDrive:
iso = GetIsoFilePath(data.DataSource, vmiName, namespace)
default:
return fmt.Errorf("invalid cloud-init data source: '%v'", data.DataSource)
}
isoStaging = fmt.Sprintf("%s.staging", iso)

err = diskutils.RemoveFilesIfExist(isoStaging)
if err != nil {
return err
}

err = util.MkdirAllWithNosec(path.Dir(isoStaging))
if err != nil {
log.Log.V(2).Reason(err).Errorf("unable to create cloud-init base path %s", path.Dir(isoStaging))
return err
}

f, err := os.Create(isoStaging)
if err != nil {
return fmt.Errorf("failed to create empty iso: '%s'", isoStaging)
}

err = util.WriteBytes(f, 0, size)
if err != nil {
return err
}
util.CloseIOAndCheckErr(f, &err)
if err != nil {
return err
}

if err := diskutils.DefaultOwnershipManager.SetFileOwnership(isoStaging); err != nil {
return err
}
err = os.Rename(isoStaging, iso)
if err != nil {
log.Log.Reason(err).Errorf("Cloud-init failed to rename file %s to %s", isoStaging, iso)
return err
}

log.Log.V(2).Infof("generated empty iso file %s", iso)
return nil
}

func GenerateLocalData(vmiName string, namespace string, data *CloudInitData) error {
precond.MustNotBeEmpty(vmiName)
precond.MustNotBeNil(data)
Expand Down
2 changes: 1 addition & 1 deletion pkg/cloud-init/cloud-init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ var _ = Describe("CloudInit", func() {
})
})
})

Describe("GenerateLocalData", func() {
It("should cleanly run twice", func() {
namespace := "fake-namespace"
Expand All @@ -517,7 +518,6 @@ var _ = Describe("CloudInit", func() {
err = GenerateLocalData(domain, namespace, cloudInitData)
Expect(err).NotTo(HaveOccurred())
})

})

Describe("PrepareLocalPath", func() {
Expand Down
1 change: 1 addition & 0 deletions pkg/config/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/ephemeral-disk-utils:go_default_library",
"//pkg/util:go_default_library",
"//staging/src/kubevirt.io/client-go/api/v1:go_default_library",
],
)
Expand Down
8 changes: 6 additions & 2 deletions pkg/config/config-map.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func GetConfigMapDiskPath(volumeName string) string {
}

// CreateConfigMapDisks creates ConfigMap iso disks which are attached to vmis
func CreateConfigMapDisks(vmi *v1.VirtualMachineInstance) error {
func CreateConfigMapDisks(vmi *v1.VirtualMachineInstance, emptyIso bool) error {
for _, volume := range vmi.Spec.Volumes {
if volume.ConfigMap != nil {
var filesPath []string
Expand All @@ -47,7 +47,11 @@ func CreateConfigMapDisks(vmi *v1.VirtualMachineInstance) error {
}

disk := GetConfigMapDiskPath(volume.Name)
if err := createIsoConfigImage(disk, volume.ConfigMap.VolumeLabel, filesPath); err != nil {
vmiIsoSize, err := findIsoSize(vmi, &volume, emptyIso)
if err != nil {
return err
}
if err := createIsoConfigImage(disk, volume.ConfigMap.VolumeLabel, filesPath, vmiIsoSize); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config-map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ var _ = Describe("ConfigMap", func() {
},
})

err := CreateConfigMapDisks(vmi)
err := CreateConfigMapDisks(vmi, false)
Expect(err).NotTo(HaveOccurred())
_, err = os.Stat(filepath.Join(ConfigMapDisksDir, "configmap-volume.iso"))
Expect(err).NotTo(HaveOccurred())
Expand Down
50 changes: 46 additions & 4 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,22 @@
package config

import (
"fmt"
"os"
"os/exec"
"path/filepath"

"kubevirt.io/kubevirt/pkg/util"

v1 "kubevirt.io/client-go/api/v1"
)

type (
// Type represents allowed config types like ConfigMap or Secret
Type string

isoCreationFunc func(output string, volID string, files []string) error
isoCreationFunc func(output string, volID string, files []string) error
emptyIsoCreationFunc func(output string, size int64) error
)

const (
Expand Down Expand Up @@ -78,14 +84,20 @@ var (
// ServiceAccountDiskName represents the name of the ServiceAccount iso image
ServiceAccountDiskName = "service-account.iso"

createISOImage = defaultCreateIsoImage
createISOImage = defaultCreateIsoImage
createEmptyISOImage = defaultCreateEmptyIsoImage
)

// The unit test suite uses this function
func setIsoCreationFunction(isoFunc isoCreationFunc) {
createISOImage = isoFunc
}

// The unit test suite uses this function
func setEmptyIsoCreationFunction(emptyIsoFunc emptyIsoCreationFunc) {
createEmptyISOImage = emptyIsoFunc
}

func getFilesLayout(dirPath string) ([]string, error) {
var filesPath []string
files, err := os.ReadDir(dirPath)
Expand Down Expand Up @@ -129,10 +141,40 @@ func defaultCreateIsoImage(output string, volID string, files []string) error {
return nil
}

func createIsoConfigImage(output string, volID string, files []string) error {
err := createISOImage(output, volID, files)
func defaultCreateEmptyIsoImage(output string, size int64) error {
f, err := os.Create(output)
if err != nil {
return fmt.Errorf("failed to create empty iso: '%s'", output)
}
err = util.WriteBytes(f, 0, size)
if err != nil {
return err
}
util.CloseIOAndCheckErr(f, &err)
return err
}

func createIsoConfigImage(output string, volID string, files []string, size int64) error {
var err error
if size == 0 {
err = createISOImage(output, volID, files)
} else {
err = createEmptyISOImage(output, size)
}
if err != nil {
return err
}
return nil
}

func findIsoSize(vmi *v1.VirtualMachineInstance, volume *v1.Volume, emptyIso bool) (int64, error) {
if emptyIso {
for _, vs := range vmi.Status.VolumeStatus {
if vs.Name == volume.Name {
return vs.Size, nil
}
}
return 0, fmt.Errorf("failed to find the status of volume %s", volume.Name)
}
return 0, nil
}
2 changes: 1 addition & 1 deletion pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ var _ = Describe("Creating config images", func() {

It("Should create an iso image", func() {
imgPath := filepath.Join(tempISODir, "volume1.iso")
err := createIsoConfigImage(imgPath, "", expectedLayout)
err := createIsoConfigImage(imgPath, "", expectedLayout, 0)
Expect(err).NotTo(HaveOccurred())
_, err = os.Stat(imgPath)
Expect(err).NotTo(HaveOccurred())
Expand Down
8 changes: 6 additions & 2 deletions pkg/config/downwardapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func GetDownwardAPIDiskPath(volumeName string) string {
}

// CreateDownwardAPIDisks creates DownwardAPI iso disks which are attached to vmis
func CreateDownwardAPIDisks(vmi *v1.VirtualMachineInstance) error {
func CreateDownwardAPIDisks(vmi *v1.VirtualMachineInstance, emptyIso bool) error {
for _, volume := range vmi.Spec.Volumes {
if volume.DownwardAPI != nil {

Expand All @@ -48,7 +48,11 @@ func CreateDownwardAPIDisks(vmi *v1.VirtualMachineInstance) error {
}

disk := GetDownwardAPIDiskPath(volume.Name)
if err := createIsoConfigImage(disk, volume.DownwardAPI.VolumeLabel, filesPath); err != nil {
vmiIsoSize, err := findIsoSize(vmi, &volume, emptyIso)
if err != nil {
return err
}
if err := createIsoConfigImage(disk, volume.DownwardAPI.VolumeLabel, filesPath, vmiIsoSize); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/downwardapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ var _ = Describe("DownwardAPI", func() {
},
})

err := CreateDownwardAPIDisks(vmi)
err := CreateDownwardAPIDisks(vmi, false)
Expect(err).NotTo(HaveOccurred())
_, err = os.Stat(filepath.Join(DownwardAPIDisksDir, "downwardapi-volume.iso"))
Expect(err).NotTo(HaveOccurred())
Expand Down
8 changes: 6 additions & 2 deletions pkg/config/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func GetSecretDiskPath(volumeName string) string {
}

// CreateSecretDisks creates Secret iso disks which are attached to vmis
func CreateSecretDisks(vmi *v1.VirtualMachineInstance) error {
func CreateSecretDisks(vmi *v1.VirtualMachineInstance, emptyIso bool) error {
for _, volume := range vmi.Spec.Volumes {
if volume.Secret != nil {

Expand All @@ -48,7 +48,11 @@ func CreateSecretDisks(vmi *v1.VirtualMachineInstance) error {
}

disk := GetSecretDiskPath(volume.Name)
if err := createIsoConfigImage(disk, volume.Secret.VolumeLabel, filesPath); err != nil {
vmiIsoSize, err := findIsoSize(vmi, &volume, emptyIso)
if err != nil {
return err
}
if err := createIsoConfigImage(disk, volume.Secret.VolumeLabel, filesPath, vmiIsoSize); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/secret_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ var _ = Describe("Secret", func() {
},
})

err := CreateSecretDisks(vmi)
err := CreateSecretDisks(vmi, false)
Expect(err).NotTo(HaveOccurred())
_, err = os.Stat(filepath.Join(SecretDisksDir, "secret-volume.iso"))
Expect(err).NotTo(HaveOccurred())
Expand Down
8 changes: 6 additions & 2 deletions pkg/config/service-account.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func GetServiceAccountDiskPath() string {
}

// CreateServiceAccountDisk creates the ServiceAccount iso disk which is attached to vmis
func CreateServiceAccountDisk(vmi *v1.VirtualMachineInstance) error {
func CreateServiceAccountDisk(vmi *v1.VirtualMachineInstance, emptyIso bool) error {
for _, volume := range vmi.Spec.Volumes {
if volume.ServiceAccount != nil {
var filesPath []string
Expand All @@ -42,7 +42,11 @@ func CreateServiceAccountDisk(vmi *v1.VirtualMachineInstance) error {
}

disk := GetServiceAccountDiskPath()
if err := createIsoConfigImage(disk, "", filesPath); err != nil {
vmiIsoSize, err := findIsoSize(vmi, &volume, emptyIso)
if err != nil {
return err
}
if err := createIsoConfigImage(disk, "", filesPath, vmiIsoSize); err != nil {
return err
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/config/service-account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ var _ = Describe("ServiceAccount", func() {
},
})

err := CreateServiceAccountDisk(vmi)
err := CreateServiceAccountDisk(vmi, false)
Expect(err).NotTo(HaveOccurred())
_, err = os.Stat(filepath.Join(ServiceAccountDiskDir, ServiceAccountDiskName))
Expect(err).NotTo(HaveOccurred())
Expand Down
16 changes: 10 additions & 6 deletions pkg/config/sysprep.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,16 @@ func validateAutounattendPresence(dirPath string) error {
}

// CreateSysprepDisks creates Sysprep iso disks which are attached to vmis from either ConfigMap or Secret as a source
func CreateSysprepDisks(vmi *v1.VirtualMachineInstance) error {
func CreateSysprepDisks(vmi *v1.VirtualMachineInstance, emptyIso bool) error {
for _, volume := range vmi.Spec.Volumes {
if !shouldCreateSysprepDisk(volume.Sysprep) {
continue
}
if err := createSysprepDisk(volume.Name); err != nil {
vmiIsoSize, err := findIsoSize(vmi, &volume, emptyIso)
if err != nil {
return err
}
if err := createSysprepDisk(volume.Name, vmiIsoSize); err != nil {
return err
}
}
Expand All @@ -80,7 +84,7 @@ func shouldCreateSysprepDisk(volumeSysprep *v1.SysprepSource) bool {
return volumeSysprep != nil && sysprepVolumeHasContents(volumeSysprep)
}

func createSysprepDisk(volumeName string) error {
func createSysprepDisk(volumeName string, size int64) error {
sysprepSourcePath := GetSysprepSourcePath(volumeName)
if err := validateAutounattendPresence(sysprepSourcePath); err != nil {
return err
Expand All @@ -90,12 +94,12 @@ func createSysprepDisk(volumeName string) error {
return err
}

return createIsoImageAndSetFileOwnership(volumeName, filesPath)
return createIsoImageAndSetFileOwnership(volumeName, filesPath, size)
}

func createIsoImageAndSetFileOwnership(volumeName string, filesPath []string) error {
func createIsoImageAndSetFileOwnership(volumeName string, filesPath []string, size int64) error {
disk := GetSysprepDiskPath(volumeName)
if err := createIsoConfigImage(disk, sysprepVolumeLabel, filesPath); err != nil {
if err := createIsoConfigImage(disk, sysprepVolumeLabel, filesPath, size); err != nil {
return err
}
if err := ephemeraldiskutils.DefaultOwnershipManager.SetFileOwnership(disk); err != nil {
Expand Down
Loading

0 comments on commit 5ed15d7

Please sign in to comment.