The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/4110
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === With the previous commits pre-copy migration was opt-in as not all architecture/kernel/CRIU combinations support it. With the newly added CRIU feature checking support added to lxc and go-lxc the pre-copy migration is now switched from defaulting to off to default to what the platform actual supports. If the architecture/kernel/CRIU combination supports pre-copy migration it is turned on. The user has still the chance to opt-out of pre-copy migration by setting 'migration.incremental.memory' to 'false'.
From 2582ae0fa8e5f1d6fc91893bf242ab27df1b07a6 Mon Sep 17 00:00:00 2001 From: Adrian Reber <are...@redhat.com> Date: Sun, 17 Dec 2017 20:37:57 +0100 Subject: [PATCH 1/4] migration: add handler for CRIU feature checking Now that lxc and go-lxc know about CRIU feature checking also start to include feature checking in LXD. Signed-off-by: Adrian Reber <are...@redhat.com> --- lxd/container_lxc.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index 5851f36a7..e2a89b9c1 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -4646,6 +4646,7 @@ type CriuMigrationArgs struct { actionScript bool dumpDir string preDumpDir string + features lxc.CriuFeatures } func (c *containerLXC) Migrate(args *CriuMigrationArgs) error { @@ -4656,6 +4657,7 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error { "statedir": args.stateDir, "actionscript": args.actionScript, "predumpdir": args.preDumpDir, + "features": args.features, "stop": args.stop} _, err := exec.LookPath("criu") @@ -4679,6 +4681,8 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error { prettyCmd = "dump" case lxc.MIGRATE_RESTORE: prettyCmd = "restore" + case lxc.MIGRATE_FEATURE_CHECK: + prettyCmd = "feature-check" default: prettyCmd = "unknown" logger.Warn("unknown migrate call", log.Ctx{"cmd": args.cmd}) @@ -4757,7 +4761,17 @@ func (c *containerLXC) Migrate(args *CriuMigrationArgs) error { logger.Debugf("forkmigrate: %s", line) } } + } else if args.cmd == lxc.MIGRATE_FEATURE_CHECK { + opts := lxc.MigrateOptions{ + FeaturesToCheck: args.features, + } + migrateErr = c.c.Migrate(args.cmd, opts) + if migrateErr != nil { + logger.Info("CRIU feature check failed", ctxMap) + return migrateErr + } + return nil } else { err := c.initLXC(true) if err != nil { From 29b84750eacb7e75ab25f18b1531c43ab4faa37a Mon Sep 17 00:00:00 2001 From: Adrian Reber <are...@redhat.com> Date: Sun, 17 Dec 2017 20:40:03 +0100 Subject: [PATCH 2/4] migration: remove obsolete TODO comment Initially the idea was to check for pre-copy support also on the receiving side. CRIU supports pre-copying for a 'very long' time already and there is no special kernel support required to restore a pre-copy checkpoint. If the sender wants to do pre-copy migration let's just do it. If the receiving side does not include the code for pre-copy migration the protobuf header will neither be filled with 'true' or 'false' concerning the pre-copy support of the receiving side which will be interpreted as 'false' on the side of the sender as the protocol to handle multiple rsync transfers for each pre-copy iteration is only available after the pre-copy support has been added. Interestingly this is a rather long commit message for a single line comment removal. Signed-off-by: Adrian Reber <are...@redhat.com> --- lxd/migrate.go | 1 - 1 file changed, 1 deletion(-) diff --git a/lxd/migrate.go b/lxd/migrate.go index e7789fddb..d237a65a0 100644 --- a/lxd/migrate.go +++ b/lxd/migrate.go @@ -1102,7 +1102,6 @@ func (c *migrationSink) Do(migrateOp *operation) error { if header.GetPredump() == true { // If the other side wants pre-dump and if // this side supports it, let's use it. - // TODO: check kernel+criu (and config?) resp.Predump = proto.Bool(true) } else { resp.Predump = proto.Bool(false) From a6e77fd7b4c71e810dbe4525587515f97a7db975 Mon Sep 17 00:00:00 2001 From: Adrian Reber <are...@redhat.com> Date: Sun, 17 Dec 2017 20:55:07 +0100 Subject: [PATCH 3/4] migration: move pre-dump check to its own function This just moves code around to decrease the size of the main migration function. The pre-dump configuration variable reading is moved to its own function. Signed-off-by: Adrian Reber <are...@redhat.com> --- lxd/migrate.go | 83 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/lxd/migrate.go b/lxd/migrate.go index d237a65a0..4067a184f 100644 --- a/lxd/migrate.go +++ b/lxd/migrate.go @@ -357,6 +357,51 @@ func snapshotToProtobuf(c container) *Snapshot { } } +// Check if CRIU supports pre-dumping and number of +// pre-dump iterations +func (s *migrationSourceWs) checkForPreDumpSupport() (bool, int) { + // TODO: ask CRIU if this system (kernel+criu) supports + // pre-copy (dirty memory tracking) + // The user should also be enable to influence it from the + // command-line. + + // What does the configuration say about pre-copy + tmp := s.container.ExpandedConfig()["migration.incremental.memory"] + + // default to false for pre-dumps as long as libxlc has no + // detection for the feature + use_pre_dumps := false + + if tmp != "" { + use_pre_dumps = shared.IsTrue(tmp) + } + logger.Debugf("migration.incremental.memory %d", use_pre_dumps) + + + // migration.incremental.memory.iterations is the value after which the + // container will be definitely migrated, even if the remaining number + // of memory pages is below the defined threshold. + // TODO: implement threshold (needs reading of CRIU output files) + var max_iterations int + tmp = s.container.ExpandedConfig()["migration.incremental.memory.iterations"] + if tmp != "" { + max_iterations, _ = strconv.Atoi(tmp) + } else { + // default to 10 + max_iterations = 10 + } + if max_iterations > 999 { + // the pre-dump directory is hardcoded to a string + // with maximal 3 digits. 999 pre-dumps makes no + // sense at all, but let's make sure the number + // is not higher than this. + max_iterations = 999 + } + logger.Debugf("using maximal %d iterations for pre-dumping", max_iterations) + + return use_pre_dumps, max_iterations +} + // The function readCriuStatsDump() reads the CRIU 'stats-dump' file // in path and returns the pages_written, pages_skipped_parent, error. func readCriuStatsDump(path string) (uint64, uint64, error) { @@ -552,43 +597,7 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error { } } - // TODO: ask CRIU if this system (kernel+criu) supports - // pre-copy (dirty memory tracking) - // The user should also be enable to influence it from the - // command-line. - - // What does the config say about pre-copy - tmp := s.container.ExpandedConfig()["migration.incremental.memory"] - - // default to false for pre-dumps as long as libxlc has no - // detection for the feature - use_pre_dumps := false - - if tmp != "" { - use_pre_dumps = shared.IsTrue(tmp) - } - logger.Debugf("migration.incremental.memory %d", use_pre_dumps) - - // migration.incremental.memory.iterations is the value after which the - // container will be definitely migrated, even if the remaining number - // of memory pages is below the defined threshold. - // TODO: implement threshold (needs reading of CRIU output files) - var max_iterations int - tmp = s.container.ExpandedConfig()["migration.incremental.memory.iterations"] - if tmp != "" { - max_iterations, _ = strconv.Atoi(tmp) - } else { - // default to 10 - max_iterations = 10 - } - if max_iterations > 999 { - // the pre-dump directory is hardcoded to a string - // with maximal 3 digits. 999 pre-dumps makes no - // sense at all, but let's make sure the number - // is not higher than this. - max_iterations = 999 - } - logger.Debugf("using maximal %d iterations for pre-dumping", max_iterations) + use_pre_dumps, max_iterations := s.checkForPreDumpSupport() // The protocol says we have to send a header no matter what, so let's // do that, but then immediately send an error. From f7399e045a4643eed1e1df3e03f39fde3e3e755f Mon Sep 17 00:00:00 2001 From: Adrian Reber <are...@redhat.com> Date: Sun, 17 Dec 2017 21:07:48 +0100 Subject: [PATCH 4/4] migration: default to pre-copy migration if CRIU supports it Now that everything has been prepared to be able to handle pre-copy migration detection (lxc, go-lxc, lxd) this is the final step to default to pre-copy migration if all involved layers support it. The user can still opt-out of pre-copy migration by setting 'migration.incremental.memory' to 'false'. Signed-off-by: Adrian Reber <are...@redhat.com> --- lxd/migrate.go | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/lxd/migrate.go b/lxd/migrate.go index 4067a184f..f11eeaeb2 100644 --- a/lxd/migrate.go +++ b/lxd/migrate.go @@ -360,29 +360,44 @@ func snapshotToProtobuf(c container) *Snapshot { // Check if CRIU supports pre-dumping and number of // pre-dump iterations func (s *migrationSourceWs) checkForPreDumpSupport() (bool, int) { - // TODO: ask CRIU if this system (kernel+criu) supports - // pre-copy (dirty memory tracking) - // The user should also be enable to influence it from the - // command-line. + use_pre_dumps := false + + // Ask CRIU if this architecture/kernel/criu combination + // supports pre-copy (dirty memory tracking) + criuMigrationArgs := CriuMigrationArgs{ + cmd: lxc.MIGRATE_FEATURE_CHECK, + stateDir: "", + function: "feature-check", + stop: false, + actionScript: false, + dumpDir: "", + preDumpDir: "", + features: lxc.FEATURE_MEM_TRACK, + } + err := s.container.Migrate(&criuMigrationArgs) + + if err != nil { + // CRIU says it does not know about dirty memory tracking. + // This means the rest of this function is irrelevant. + return false, 0 + } + + // CRIU says it can actually do pre-dump + use_pre_dumps = true // What does the configuration say about pre-copy tmp := s.container.ExpandedConfig()["migration.incremental.memory"] - // default to false for pre-dumps as long as libxlc has no - // detection for the feature - use_pre_dumps := false - if tmp != "" { use_pre_dumps = shared.IsTrue(tmp) } logger.Debugf("migration.incremental.memory %d", use_pre_dumps) + var max_iterations int // migration.incremental.memory.iterations is the value after which the // container will be definitely migrated, even if the remaining number // of memory pages is below the defined threshold. - // TODO: implement threshold (needs reading of CRIU output files) - var max_iterations int tmp = s.container.ExpandedConfig()["migration.incremental.memory.iterations"] if tmp != "" { max_iterations, _ = strconv.Atoi(tmp)
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel