Skip to content

Commit

Permalink
Merge pull request kubevirt#5763 from nunnatsa/fix-bug-1945589
Browse files Browse the repository at this point in the history
Prevent migration of VMIs that uses virtiofs
  • Loading branch information
kubevirt-bot authored Jun 18, 2021
2 parents edf8b8f + 0c29fe5 commit 099be90
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 21 deletions.
43 changes: 24 additions & 19 deletions pkg/virt-handler/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1255,37 +1255,42 @@ func calculatePausedCondition(vmi *v1.VirtualMachineInstance, reason api.StateCh
}
}

func (d *VirtualMachineController) calculateLiveMigrationCondition(vmi *v1.VirtualMachineInstance, hasHotplug bool) (*v1.VirtualMachineInstanceCondition, bool) {
liveMigrationCondition := v1.VirtualMachineInstanceCondition{
Type: v1.VirtualMachineInstanceIsMigratable,
Status: k8sv1.ConditionTrue,
}

setNonMigratable := func(err error, reason string) {
liveMigrationCondition.Status = k8sv1.ConditionFalse
liveMigrationCondition.Message = err.Error()
liveMigrationCondition.Reason = reason
func newNonMigratableCondition(msg string, reason string) *v1.VirtualMachineInstanceCondition {
return &v1.VirtualMachineInstanceCondition{
Type: v1.VirtualMachineInstanceIsMigratable,
Status: k8sv1.ConditionFalse,
Message: msg,
Reason: reason,
}
}

func (d *VirtualMachineController) calculateLiveMigrationCondition(vmi *v1.VirtualMachineInstance, hasHotplug bool) (*v1.VirtualMachineInstanceCondition, bool) {
isBlockMigration, err := d.checkVolumesForMigration(vmi)
if err != nil {
setNonMigratable(err, v1.VirtualMachineInstanceReasonDisksNotMigratable)
return &liveMigrationCondition, isBlockMigration
return newNonMigratableCondition(err.Error(), v1.VirtualMachineInstanceReasonDisksNotMigratable), isBlockMigration
}

err = d.checkNetworkInterfacesForMigration(vmi)
if err != nil {
setNonMigratable(err, v1.VirtualMachineInstanceReasonInterfaceNotMigratable)
return &liveMigrationCondition, isBlockMigration
return newNonMigratableCondition(err.Error(), v1.VirtualMachineInstanceReasonInterfaceNotMigratable), isBlockMigration
}

if hasHotplug {
setNonMigratable(fmt.Errorf("VMI has hotplugged disks"), v1.VirtualMachineInstanceReasonHotplugNotMigratable)
return &liveMigrationCondition, isBlockMigration
return newNonMigratableCondition("VMI has hotplugged disks", v1.VirtualMachineInstanceReasonHotplugNotMigratable), isBlockMigration
}

if err := d.isHostModelMigratable(vmi); err != nil {
setNonMigratable(err, v1.VirtualMachineInstanceReasonCPUModeNotMigratable)
return &liveMigrationCondition, isBlockMigration
return newNonMigratableCondition(err.Error(), v1.VirtualMachineInstanceReasonCPUModeNotMigratable), isBlockMigration
}

if util.IsVMIVirtiofsEnabled(vmi) {
return newNonMigratableCondition("VMI uses virtiofs", v1.VirtualMachineInstanceReasonVirtIOFSNotMigratable), isBlockMigration
}
return &liveMigrationCondition, isBlockMigration

return &v1.VirtualMachineInstanceCondition{
Type: v1.VirtualMachineInstanceIsMigratable,
Status: k8sv1.ConditionTrue,
}, isBlockMigration
}

func (c *VirtualMachineController) Run(threadiness int, stopCh chan struct{}) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/virt-handler/vm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2158,6 +2158,22 @@ var _ = Describe("VirtualMachineInstance", func() {
table.Entry("don't exist migration should fail", false),
)

It("should not be allowed to live-migrate if the VMI uses virtiofs ", func() {
vmi := v1.NewMinimalVMI("testvmi")
vmi.Spec.Domain.Devices.Filesystems = []v1.Filesystem{
{
Name: "VIRTIOFS",
Virtiofs: &v1.FilesystemVirtiofs{},
},
}

condition, isBlockMigration := controller.calculateLiveMigrationCondition(vmi, false)
Expect(isBlockMigration).To(BeFalse())
Expect(condition.Type).To(Equal(v1.VirtualMachineInstanceIsMigratable))
Expect(condition.Status).To(Equal(k8sv1.ConditionFalse))
Expect(condition.Reason).To(Equal(v1.VirtualMachineInstanceReasonVirtIOFSNotMigratable))
})

Context("with network configuration", func() {
It("should block migration for bridge binding assigned to the pod network", func() {
vmi := v1.NewMinimalVMI("testvmi")
Expand Down
4 changes: 3 additions & 1 deletion staging/src/kubevirt.io/client-go/api/v1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,12 @@ const (
VirtualMachineInstanceReasonDisksNotMigratable = "DisksNotLiveMigratable"
// Reason means that VMI is not live migratioable because of it's network interfaces collection
VirtualMachineInstanceReasonInterfaceNotMigratable = "InterfaceNotLiveMigratable"
// Reason means that VMI is not live migratioable because of it's network interfaces collection
// Reason means that VMI is not live migratioable because it uses hotplug
VirtualMachineInstanceReasonHotplugNotMigratable = "HotplugNotLiveMigratable"
// Reason means that VMI is not live migratioable because of it's CPU mode
VirtualMachineInstanceReasonCPUModeNotMigratable = "CPUModeLiveMigratable"
// Reason means that VMI is not live migratable because it uses virtiofs
VirtualMachineInstanceReasonVirtIOFSNotMigratable = "VirtIOFSNotLiveMigratable"
)

const (
Expand Down
12 changes: 11 additions & 1 deletion tests/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -387,12 +387,16 @@ var _ = Describe("[Serial][rfe_id:393][crit:high][vendor:[email protected]][leve
By("Checking that the VirtualMachineInstance console has expected output")
Expect(console.LoginToAlpine(vmi)).To(Succeed())

gotExpectedCondition := false
for _, c := range vmi.Status.Conditions {
if c.Type == v1.VirtualMachineInstanceIsMigratable {
Expect(c.Status).To(Equal(k8sv1.ConditionFalse))
gotExpectedCondition = true
}
}

Expect(gotExpectedCondition).Should(BeTrue())

// execute a migration, wait for finalized state
migration := tests.NewRandomMigration(vmi.Name, vmi.Namespace)

Expand Down Expand Up @@ -889,11 +893,14 @@ var _ = Describe("[Serial][rfe_id:393][crit:high][vendor:[email protected]][leve
By("Checking that the VirtualMachineInstance console has expected output")
Expect(console.LoginToAlpine(vmi)).To(Succeed())

gotExpectedCondition := false
for _, c := range vmi.Status.Conditions {
if c.Type == v1.VirtualMachineInstanceIsMigratable {
Expect(c.Status).To(Equal(k8sv1.ConditionFalse))
gotExpectedCondition = true
}
}
Expect(gotExpectedCondition).Should(BeTrue())

// execute a migration, wait for finalized state
migration := tests.NewRandomMigration(vmi.Name, vmi.Namespace)
Expand Down Expand Up @@ -1698,17 +1705,20 @@ var _ = Describe("[Serial][rfe_id:393][crit:high][vendor:[email protected]][leve
// Start the VirtualMachineInstance with the PVC attached
vmi := tests.NewRandomVMIWithPVC(pvName)
tests.AddUserData(vmi, "cloud-init", "#!/bin/bash\necho 'hello'\n")
vmi.Spec.Hostname = fmt.Sprintf("%s", cd.ContainerDiskCirros)
vmi.Spec.Hostname = string(cd.ContainerDiskCirros)
vmi = runVMIAndExpectLaunch(vmi, 180)

By("Checking that the VirtualMachineInstance console has expected output")
Expect(libnet.WithIPv6(console.LoginToCirros)(vmi)).To(Succeed())

gotExpectedCondition := false
for _, c := range vmi.Status.Conditions {
if c.Type == v1.VirtualMachineInstanceIsMigratable {
Expect(c.Status).To(Equal(k8sv1.ConditionFalse))
gotExpectedCondition = true
}
}
Expect(gotExpectedCondition).Should(BeTrue())

// execute a migration, wait for finalized state
migration := tests.NewRandomMigration(vmi.Name, vmi.Namespace)
Expand Down

0 comments on commit 099be90

Please sign in to comment.