Skip to content

Commit

Permalink
Merge pull request kubevirt#8209 from daghaian/fix/correct-external-boot
Browse files Browse the repository at this point in the history
Corrected issue with external boot which only kernelPath is specified without initrd path
  • Loading branch information
kubevirt-bot authored Aug 5, 2022
2 parents dc081af + ddbaede commit 8d51050
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 19 deletions.
48 changes: 32 additions & 16 deletions pkg/virt-handler/container-disk/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,19 +444,29 @@ func (m *mounter) mountKernelArtifacts(vmi *v1.VirtualMachineInstance, verify bo

nodeRes := isolation.NodeIsolationResult()

if err := safepath.TouchAtNoFollow(targetDir, filepath.Base(kb.InitrdPath), 0655); err != nil && !os.IsExist(err) {
return err
}
if err := safepath.TouchAtNoFollow(targetDir, filepath.Base(kb.KernelPath), 0655); err != nil && !os.IsExist(err) {
return err
}
targetInitrdPath, err := safepath.JoinNoFollow(targetDir, filepath.Base(kb.InitrdPath))
if err != nil {
return err
var targetInitrdPath *safepath.Path
var targetKernelPath *safepath.Path

if kb.InitrdPath != "" {
if err := safepath.TouchAtNoFollow(targetDir, filepath.Base(kb.InitrdPath), 0655); err != nil && !os.IsExist(err) {
return err
}

targetInitrdPath, err = safepath.JoinNoFollow(targetDir, filepath.Base(kb.InitrdPath))
if err != nil {
return err
}
}
targetKernelPath, err := safepath.JoinNoFollow(targetDir, filepath.Base(kb.KernelPath))
if err != nil {
return err

if kb.KernelPath != "" {
if err := safepath.TouchAtNoFollow(targetDir, filepath.Base(kb.KernelPath), 0655); err != nil && !os.IsExist(err) {
return err
}

targetKernelPath, err = safepath.JoinNoFollow(targetDir, filepath.Base(kb.KernelPath))
if err != nil {
return err
}
}

areKernelArtifactsMounted := func(artifactsDir *safepath.Path, artifactFiles ...*safepath.Path) (bool, error) {
Expand Down Expand Up @@ -499,12 +509,18 @@ func (m *mounter) mountKernelArtifacts(vmi *v1.VirtualMachineInstance, verify bo
return nil
}

if err = mount(kb.InitrdPath, targetInitrdPath); err != nil {
return err
if kb.InitrdPath != "" {
if err = mount(kb.InitrdPath, targetInitrdPath); err != nil {
return err
}
}
if err = mount(kb.KernelPath, targetKernelPath); err != nil {
return err

if kb.KernelPath != "" {
if err = mount(kb.KernelPath, targetKernelPath); err != nil {
return err
}
}

}

if verify {
Expand Down
8 changes: 5 additions & 3 deletions pkg/virt-handler/isolation/isolation.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,11 @@ func IsMounted(mountPoint *safepath.Path) (isMounted bool, err error) {
// If error occurs, the first error is returned.
func (r *RealIsolationResult) AreMounted(mountPoints ...*safepath.Path) (isMounted bool, err error) {
for _, mountPoint := range mountPoints {
isMounted, err = IsMounted(mountPoint)
if !isMounted || err != nil {
return
if mountPoint != nil {
isMounted, err = IsMounted(mountPoint)
if !isMounted || err != nil {
return
}
}
}

Expand Down
63 changes: 63 additions & 0 deletions tests/vmi_kernel_boot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ import (
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kubevirtv1 "kubevirt.io/api/core/v1"

cd "kubevirt.io/kubevirt/tests/containerdisk"
"kubevirt.io/kubevirt/tests/libvmi"

"kubevirt.io/kubevirt/tests/util"

Expand Down Expand Up @@ -122,4 +124,65 @@ var _ = Describe("[sig-compute]VMI with external kernel boot", func() {
Expect(err.Error()).To(ContainSubstring("denied the request: spec.domain.firmware.kernelBoot.container must be defined with at least one of the following: kernelPath, initrdPath"))
})
})

Context("with external alpine-based kernel only (without initrd)", func() {
getVMIKernelBoot := func() *kubevirtv1.VirtualMachineInstance {
vmi := utils.GetVMIKernelBoot()
// Remove initrd path from vmi spec
kernelBoot := vmi.Spec.Domain.Firmware.KernelBoot
kernelBoot.Container.InitrdPath = ""
return vmi
}

It("ensure successful boot", func() {
vmi := getVMIKernelBoot()

obj, err := virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(vmi)
Expect(err).ToNot(HaveOccurred())
tests.WaitForSuccessfulVMIStart(obj)
})

It("ensure successful boot and deletion when VMI has a disk defined", func() {
By("Creating VMI with disk and kernel boot")
vmi := libvmi.NewAlpine(libvmi.WithResourceMemory("1Gi"))

utils.AddKernelBootToVMI(vmi)
// Remove initrd path from vmi spec
kernelBoot := vmi.Spec.Domain.Firmware.KernelBoot
kernelBoot.Container.InitrdPath = ""

Expect(vmi.Spec.Volumes).ToNot(BeEmpty())
Expect(vmi.Spec.Domain.Devices.Disks).ToNot(BeEmpty())

By("Ensuring VMI can boot")
vmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Create(vmi)
Expect(err).ToNot(HaveOccurred())
tests.WaitForSuccessfulVMIStart(vmi)

By("Fetching virt-launcher pod")
virtLauncherPod := tests.GetRunningPodByVirtualMachineInstance(vmi, vmi.Namespace)

By("Ensuring VMI is deleted")
err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Delete(vmi.Name, &v1.DeleteOptions{})
Expect(err).ToNot(HaveOccurred())
Eventually(func() (isVmiDeleted bool) {
vmi, err = virtClient.VirtualMachineInstance(util.NamespaceTestDefault).Get(vmi.Name, &v1.GetOptions{})
if errors.IsNotFound(err) {
return true
}
Expect(err).ToNot(HaveOccurred())
return false
}, 60*time.Second, 3*time.Second).Should(BeTrue(), "VMI Should be successfully deleted")

By("Ensuring virt-launcher is deleted")
Eventually(func() (isVmiDeleted bool) {
_, err = virtClient.CoreV1().Pods(virtLauncherPod.Namespace).Get(context.Background(), virtLauncherPod.Name, v1.GetOptions{})
if errors.IsNotFound(err) {
return true
}
Expect(err).ToNot(HaveOccurred())
return false
}, 60*time.Second, 3*time.Second).Should(BeTrue(), fmt.Sprintf("virt-launcher pod (%s) Should be successfully deleted", virtLauncherPod.Name))
})
})
})

0 comments on commit 8d51050

Please sign in to comment.