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

Reply via email to