Skip to content

Commit

Permalink
Merge pull request kubevirt#2326 from vladikr/force_auto_converge
Browse files Browse the repository at this point in the history
Allow live migration to auto converge
  • Loading branch information
stu-gott authored Jul 3, 2019
2 parents ad46adf + 3308268 commit 147b09f
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 4 deletions.
4 changes: 4 additions & 0 deletions pkg/virt-config/config-map.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const (
ParallelOutboundMigrationsPerNodeDefault uint32 = 2
ParallelMigrationsPerClusterDefault uint32 = 5
BandwithPerMigrationDefault = "64Mi"
MigrationAllowAutoConverge bool = false
MigrationProgressTimeout int64 = 150
MigrationCompletionTimeoutPerGiB int64 = 800
DefaultMachineType = "q35"
Expand Down Expand Up @@ -130,6 +131,7 @@ func defaultClusterConfig() *Config {
parallelMigrationsPerClusterDefault := ParallelMigrationsPerClusterDefault
bandwithPerMigrationDefault := resource.MustParse(BandwithPerMigrationDefault)
nodeDrainTaintDefaultKey := NodeDrainTaintDefaultKey
allowAutoConverge := MigrationAllowAutoConverge
progressTimeout := MigrationProgressTimeout
completionTimeoutPerGiB := MigrationCompletionTimeoutPerGiB
cpuRequestDefault := resource.MustParse(DefaultCPURequest)
Expand All @@ -148,6 +150,7 @@ func defaultClusterConfig() *Config {
ProgressTimeout: &progressTimeout,
CompletionTimeoutPerGiB: &completionTimeoutPerGiB,
UnsafeMigrationOverride: false,
AllowAutoConverge: allowAutoConverge,
},
MachineType: DefaultMachineType,
CPURequest: cpuRequestDefault,
Expand Down Expand Up @@ -185,6 +188,7 @@ type MigrationConfig struct {
ProgressTimeout *int64 `json:"progressTimeout,omitempty"`
CompletionTimeoutPerGiB *int64 `json:"completionTimeoutPerGiB,omitempty"`
UnsafeMigrationOverride bool `json:"unsafeMigrationOverride"`
AllowAutoConverge bool `json:"allowAutoConverge"`
}

type ClusterConfig struct {
Expand Down
3 changes: 2 additions & 1 deletion pkg/virt-config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ var _ = Describe("ConfigMap", func() {

It("Should return migration config values if specified as json", func() {
clusterConfig, _ := testutils.NewFakeClusterConfig(&kubev1.ConfigMap{
Data: map[string]string{virtconfig.MigrationsConfigKey: `{"parallelOutboundMigrationsPerNode" : 10, "parallelMigrationsPerCluster": 20, "bandwidthPerMigration": "110Mi", "progressTimeout" : 5, "completionTimeoutPerGiB": 5, "unsafeMigrationOverride": true}`},
Data: map[string]string{virtconfig.MigrationsConfigKey: `{"parallelOutboundMigrationsPerNode" : 10, "parallelMigrationsPerCluster": 20, "bandwidthPerMigration": "110Mi", "progressTimeout" : 5, "completionTimeoutPerGiB": 5, "unsafeMigrationOverride": true, "allowAutoConverge": true}`},
})
result := clusterConfig.GetMigrationConfig()
Expect(*result.ParallelOutboundMigrationsPerNode).To(BeNumerically("==", 10))
Expand All @@ -167,6 +167,7 @@ var _ = Describe("ConfigMap", func() {
Expect(*result.ProgressTimeout).To(BeNumerically("==", 5))
Expect(*result.CompletionTimeoutPerGiB).To(BeNumerically("==", 5))
Expect(result.UnsafeMigrationOverride).To(BeTrue())
Expect(result.AllowAutoConverge).To(BeTrue())
})

It("Should return migration config values if specified as yaml", func() {
Expand Down
1 change: 1 addition & 0 deletions pkg/virt-handler/cmd-client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type MigrationOptions struct {
ProgressTimeout int64
CompletionTimeoutPerGiB int64
UnsafeMigration bool
AllowAutoConverge bool
}

type LauncherClient interface {
Expand Down
1 change: 1 addition & 0 deletions pkg/virt-handler/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,7 @@ func (d *VirtualMachineController) processVmUpdate(origVMI *v1.VirtualMachineIns
ProgressTimeout: *d.clusterConfig.GetMigrationConfig().ProgressTimeout,
CompletionTimeoutPerGiB: *d.clusterConfig.GetMigrationConfig().CompletionTimeoutPerGiB,
UnsafeMigration: d.clusterConfig.GetMigrationConfig().UnsafeMigrationOverride,
AllowAutoConverge: d.clusterConfig.GetMigrationConfig().AllowAutoConverge,
}
err = client.MigrateVirtualMachine(vmi, options)
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions pkg/virt-launcher/virtwrap/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (l *LibvirtDomainManager) setMigrationResultHelper(vmi *v1.VirtualMachineIn

}

func prepareMigrationFlags(isBlockMigration bool, isUnsafeMigration bool) libvirt.DomainMigrateFlags {
func prepareMigrationFlags(isBlockMigration bool, isUnsafeMigration bool, allowAutoConverge bool) libvirt.DomainMigrateFlags {
migrateFlags := libvirt.MIGRATE_LIVE | libvirt.MIGRATE_PEER2PEER

if isBlockMigration {
Expand All @@ -250,6 +250,9 @@ func prepareMigrationFlags(isBlockMigration bool, isUnsafeMigration bool) libvir
if isUnsafeMigration {
migrateFlags |= libvirt.MIGRATE_UNSAFE
}
if allowAutoConverge {
migrateFlags |= libvirt.MIGRATE_AUTO_CONVERGE
}
return migrateFlags

}
Expand Down Expand Up @@ -375,7 +378,7 @@ func (l *LibvirtDomainManager) asyncMigrate(vmi *v1.VirtualMachineInstance, opti
return
}

migrateFlags := prepareMigrationFlags(isBlockMigration, options.UnsafeMigration)
migrateFlags := prepareMigrationFlags(isBlockMigration, options.UnsafeMigration, options.AllowAutoConverge)
if options.UnsafeMigration {
log.Log.Object(vmi).Info("UNSAFE_MIGRATION flag is set, libvirt's migration checks will be disabled!")
}
Expand Down
7 changes: 6 additions & 1 deletion pkg/virt-launcher/virtwrap/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,19 +576,24 @@ var _ = Describe("Manager", func() {
func(migrationType string) {
isBlockMigration := migrationType == "block"
isUnsafeMigration := migrationType == "unsafe"
flags := prepareMigrationFlags(isBlockMigration, isUnsafeMigration)
allowAutoConverge := migrationType == "autoConverge"
flags := prepareMigrationFlags(isBlockMigration, isUnsafeMigration, allowAutoConverge)
expectedMigrateFlags := libvirt.MIGRATE_LIVE | libvirt.MIGRATE_PEER2PEER

if isBlockMigration {
expectedMigrateFlags |= libvirt.MIGRATE_NON_SHARED_INC
} else if migrationType == "unsafe" {
expectedMigrateFlags |= libvirt.MIGRATE_UNSAFE
}
if allowAutoConverge {
expectedMigrateFlags |= libvirt.MIGRATE_AUTO_CONVERGE
}
Expect(flags).To(Equal(expectedMigrateFlags))
},
table.Entry("with block migration", "block"),
table.Entry("without block migration", "live"),
table.Entry("unsafe migration", "unsafe"),
table.Entry("migration auto converge", "autoConverge"),
)

table.DescribeTable("on successful list all domains",
Expand Down
78 changes: 78 additions & 0 deletions tests/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,84 @@ var _ = Describe("[rfe_id:393][crit:high[vendor:[email protected]][level:system]

})
})
Context("with auto converge enabled", func() {
var options metav1.GetOptions
var cfgMap *k8sv1.ConfigMap
var originalMigrationConfig string
var kubevirtConfig = "kubevirt-config"
BeforeEach(func() {
tests.BeforeTestCleanup()

// set autoconverge flag
options = metav1.GetOptions{}
cfgMap, err = virtClient.CoreV1().ConfigMaps(tests.KubeVirtInstallNamespace).Get(kubevirtConfig, options)
Expect(err).ToNot(HaveOccurred())
originalMigrationConfig = cfgMap.Data["migrations"]
cfgMap.Data["migrations"] = `{"allowAutoConverge": true}`

_, err = virtClient.CoreV1().ConfigMaps(tests.KubeVirtInstallNamespace).Update(cfgMap)
Expect(err).ToNot(HaveOccurred())
time.Sleep(5 * time.Second)

}, 60)

AfterEach(func() {
cfgMap, err = virtClient.CoreV1().ConfigMaps(tests.KubeVirtInstallNamespace).Get(kubevirtConfig, options)
Expect(err).ToNot(HaveOccurred())
cfgMap.Data["migrations"] = originalMigrationConfig
_, err = virtClient.CoreV1().ConfigMaps(tests.KubeVirtInstallNamespace).Update(cfgMap)
Expect(err).ToNot(HaveOccurred())
}, 60)

It("should complete a migration", func() {
vmi := tests.NewRandomFedoraVMIWitGuestAgent()
vmi.Spec.Domain.Resources.Requests[k8sv1.ResourceMemory] = resource.MustParse("1Gi")

By("Starting the VirtualMachineInstance")
vmi = runVMIAndExpectLaunch(vmi, 240)

getOptions := &metav1.GetOptions{}
var updatedVmi *v1.VirtualMachineInstance
By("Checking that the VirtualMachineInstance console has expected output")
expecter, expecterErr := tests.LoggedInFedoraExpecter(vmi)
Expect(expecterErr).To(BeNil())
defer expecter.Close()

// Need to wait for cloud init to finnish and start the agent inside the vmi.
Eventually(func() bool {
updatedVmi, err = virtClient.VirtualMachineInstance(tests.NamespaceTestDefault).Get(vmi.Name, getOptions)
Expect(err).ToNot(HaveOccurred())
for _, condition := range updatedVmi.Status.Conditions {
if condition.Type == "AgentConnected" && condition.Status == "True" {
return true
}
}
return false
}, 420*time.Second, 2).Should(BeTrue(), "Should have agent connected condition")

By("Run a stress test")
_, err = expecter.ExpectBatch([]expect.Batcher{
&expect.BSnd{S: "stress --vm 1 --vm-bytes 600M --vm-keep --timeout 1600s&\n"},
}, 15*time.Second)
Expect(err).ToNot(HaveOccurred(), "should run a stress test")

// execute a migration, wait for finalized state
By("Starting the Migration")
migration := tests.NewRandomMigration(vmi.Name, vmi.Namespace)
migrationUID := runMigrationAndExpectCompletion(migration, 240)

// check VMI, confirm migration state
confirmVMIPostMigration(vmi, migrationUID)

// delete VMI
By("Deleting the VMI")
err = virtClient.VirtualMachineInstance(vmi.Namespace).Delete(vmi.Name, &metav1.DeleteOptions{})
Expect(err).To(BeNil())

By("Waiting for VMI to disappear")
tests.WaitForVirtualMachineToDisappearWithTimeout(vmi, 240)
})
})
Context("with a shared ISCSI Filesystem PVC", func() {
var options metav1.GetOptions
var cfgMap *k8sv1.ConfigMap
Expand Down

0 comments on commit 147b09f

Please sign in to comment.