[lxc-devel] [lxd/master] migrate: don't use ActionScript if it's not available
tych0 on Github
lxc-bot at linuxcontainers.org
Tue Oct 4 16:36:45 UTC 2016
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 361 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161004/9729aa1c/attachment.bin>
-------------- next part --------------
From 0d5b05c3f501159ca4a743790564c46b5e2948a2 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Tue, 4 Oct 2016 16:35:42 +0000
Subject: [PATCH] migrate: don't use ActionScript if it's not available
Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
lxd/migrate.go | 172 +++++++++++++++++++++++++++++----------------------------
1 file changed, 88 insertions(+), 84 deletions(-)
diff --git a/lxd/migrate.go b/lxd/migrate.go
index 947fd1c..2a10261 100644
--- a/lxd/migrate.go
+++ b/lxd/migrate.go
@@ -386,98 +386,102 @@ func (s *migrationSourceWs) Do(migrateOp *operation) error {
return abort(fmt.Errorf("Formats other than criu rsync not understood"))
}
- /* What happens below is slightly convoluted. Due to various
- * complications with networking, there's no easy way for criu
- * to exit and leave the container in a frozen state for us to
- * somehow resume later.
- *
- * Instead, we use what criu calls an "action-script", which is
- * basically a callback that lets us know when the dump is
- * done. (Unfortunately, we can't pass arguments, just an
- * executable path, so we write a custom action script with the
- * real command we want to run.)
- *
- * This script then hangs until the migration operation either
- * finishes successfully or fails, and exits 1 or 0, which
- * causes criu to either leave the container running or kill it
- * as we asked.
- */
- dumpDone := make(chan bool, 1)
- actionScriptOpSecret, err := shared.RandomCryptoString()
- if err != nil {
- return abort(err)
- }
-
- actionScriptOp, err := operationCreate(
- operationClassWebsocket,
- nil,
- nil,
- func(op *operation) error {
- _, err := migrateOp.WaitFinal(-1)
- if err != nil {
- return err
- }
-
- if migrateOp.status != shared.Success {
- return fmt.Errorf("restore failed: %s", op.status.String())
- }
- return nil
- },
- nil,
- func(op *operation, r *http.Request, w http.ResponseWriter) error {
- secret := r.FormValue("secret")
- if secret == "" {
- return fmt.Errorf("missing secret")
- }
-
- if secret != actionScriptOpSecret {
- return os.ErrPermission
- }
-
- c, err := shared.WebsocketUpgrader.Upgrade(w, r, nil)
- if err != nil {
- return err
- }
-
- dumpDone <- true
-
- closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")
- return c.WriteMessage(websocket.CloseMessage, closeMsg)
- },
- )
- if err != nil {
- return abort(err)
- }
-
checkpointDir, err := ioutil.TempDir("", "lxd_checkpoint_")
if err != nil {
return abort(err)
}
+ defer os.RemoveAll(checkpointDir)
+
+ if lxc.VersionAtLeast(2, 0, 4) {
+ /* What happens below is slightly convoluted. Due to various
+ * complications with networking, there's no easy way for criu
+ * to exit and leave the container in a frozen state for us to
+ * somehow resume later.
+ *
+ * Instead, we use what criu calls an "action-script", which is
+ * basically a callback that lets us know when the dump is
+ * done. (Unfortunately, we can't pass arguments, just an
+ * executable path, so we write a custom action script with the
+ * real command we want to run.)
+ *
+ * This script then hangs until the migration operation either
+ * finishes successfully or fails, and exits 1 or 0, which
+ * causes criu to either leave the container running or kill it
+ * as we asked.
+ */
+ dumpDone := make(chan bool, 1)
+ actionScriptOpSecret, err := shared.RandomCryptoString()
+ if err != nil {
+ return abort(err)
+ }
- if err := writeActionScript(checkpointDir, actionScriptOp.url, actionScriptOpSecret); err != nil {
- os.RemoveAll(checkpointDir)
- return abort(err)
- }
+ actionScriptOp, err := operationCreate(
+ operationClassWebsocket,
+ nil,
+ nil,
+ func(op *operation) error {
+ _, err := migrateOp.WaitFinal(-1)
+ if err != nil {
+ return err
+ }
+
+ if migrateOp.status != shared.Success {
+ return fmt.Errorf("restore failed: %s", op.status.String())
+ }
+ return nil
+ },
+ nil,
+ func(op *operation, r *http.Request, w http.ResponseWriter) error {
+ secret := r.FormValue("secret")
+ if secret == "" {
+ return fmt.Errorf("missing secret")
+ }
+
+ if secret != actionScriptOpSecret {
+ return os.ErrPermission
+ }
+
+ c, err := shared.WebsocketUpgrader.Upgrade(w, r, nil)
+ if err != nil {
+ return err
+ }
+
+ dumpDone <- true
+
+ closeMsg := websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")
+ return c.WriteMessage(websocket.CloseMessage, closeMsg)
+ },
+ )
+ if err != nil {
+ return abort(err)
+ }
- _, err = actionScriptOp.Run()
- if err != nil {
- os.RemoveAll(checkpointDir)
- return abort(err)
- }
+ if err := writeActionScript(checkpointDir, actionScriptOp.url, actionScriptOpSecret); err != nil {
+ return abort(err)
+ }
- migrateDone := make(chan error, 1)
- go func() {
- defer os.RemoveAll(checkpointDir)
- migrateDone <- s.container.Migrate(lxc.MIGRATE_DUMP, checkpointDir, "migration", true, true)
- }()
+ _, err = actionScriptOp.Run()
+ if err != nil {
+ return abort(err)
+ }
- select {
- /* the checkpoint failed, let's just abort */
- case err = <-migrateDone:
- return abort(err)
- /* the dump finished, let's continue on to the restore */
- case <-dumpDone:
- shared.LogDebugf("Dump finished, continuing with restore...")
+ migrateDone := make(chan error, 1)
+ go func() {
+ migrateDone <- s.container.Migrate(lxc.MIGRATE_DUMP, checkpointDir, "migration", true, true)
+ }()
+
+ select {
+ /* the checkpoint failed, let's just abort */
+ case err = <-migrateDone:
+ return abort(err)
+ /* the dump finished, let's continue on to the restore */
+ case <-dumpDone:
+ shared.LogDebugf("Dump finished, continuing with restore...")
+ }
+ } else {
+ if err := s.container.Migrate(lxc.MIGRATE_DUMP, checkpointDir, "migration", true, false); err != nil {
+ return abort(err)
+ }
}
/*
More information about the lxc-devel
mailing list