[lxc-devel] [lxd/master] lxd/containers: Allow sending progress

stgraber on Github lxc-bot at linuxcontainers.org
Fri Apr 20 17:13:14 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 370 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180420/d1991c72/attachment.bin>
-------------- next part --------------
From c5cbe5c8e98fc02cc70b7bd8d48db3c6e2271f24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Fri, 20 Apr 2018 13:11:31 -0400
Subject: [PATCH] lxd/containers: Allow sending progress
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #4447

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxc/action.go          |  9 +++++++++
 lxc/utils/progress.go  | 11 ++++++-----
 lxd/container.go       |  4 ++++
 lxd/container_lxc.go   | 28 ++++++++++++++++++++++++++++
 lxd/container_state.go |  7 +++++++
 5 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/lxc/action.go b/lxc/action.go
index e8699ed69..965361286 100644
--- a/lxc/action.go
+++ b/lxc/action.go
@@ -8,6 +8,7 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/lxc/lxd/lxc/config"
+	"github.com/lxc/lxd/lxc/utils"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 	cli "github.com/lxc/lxd/shared/cmd"
@@ -174,7 +175,15 @@ func (c *cmdAction) doAction(action string, conf *config.Config, nameArg string)
 		return err
 	}
 
+	progress := utils.ProgressRenderer{}
+	_, err = op.AddHandler(progress.UpdateOp)
+	if err != nil {
+		progress.Done("")
+		return err
+	}
+
 	err = op.Wait()
+	progress.Done("")
 	if err != nil {
 		return fmt.Errorf("%s\n"+i18n.G("Try `lxc info --show-log %s` for more info"), err, nameArg)
 	}
diff --git a/lxc/utils/progress.go b/lxc/utils/progress.go
index 1a781895a..acde53530 100644
--- a/lxc/utils/progress.go
+++ b/lxc/utils/progress.go
@@ -118,11 +118,12 @@ func (p *ProgressRenderer) UpdateOp(op api.Operation) {
 		return
 	}
 
-	for _, key := range []string{"fs_progress", "download_progress"} {
-		value, ok := op.Metadata[key]
-		if ok {
-			p.Update(value.(string))
-			break
+	for key, value := range op.Metadata {
+		if !strings.HasSuffix(key, "_progress") {
+			continue
 		}
+
+		p.Update(value.(string))
+		break
 	}
 }
diff --git a/lxd/container.go b/lxd/container.go
index 5fec29aef..f5c87f3d3 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -533,8 +533,12 @@ type container interface {
 	ConsoleBufferLogPath() string
 	LogPath() string
 
+	// Storage
 	StoragePool() (string, error)
 
+	// Progress reporting
+	SetOperation(op *operation)
+
 	// FIXME: Those should be internal functions
 	// Needed for migration for now.
 	StorageStart() (bool, error)
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 82fe1bddc..63e137031 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -523,6 +523,9 @@ type containerLXC struct {
 
 	// Clustering
 	node string
+
+	// Progress tracking
+	op *operation
 }
 
 func (c *containerLXC) createOperation(action string, reusable bool, reuse bool) (*lxcContainerOperation, error) {
@@ -1887,6 +1890,7 @@ func (c *containerLXC) startCommon() (string, error) {
 
 	if !reflect.DeepEqual(idmap, lastIdmap) {
 		logger.Debugf("Container idmap changed, remapping")
+		c.updateProgress("Remapping container filesystem")
 
 		ourStart, err = c.StorageStart()
 		if err != nil {
@@ -1942,6 +1946,8 @@ func (c *containerLXC) startCommon() (string, error) {
 				return "", err
 			}
 		}
+
+		c.updateProgress("")
 	}
 
 	err = c.ConfigKeySet("volatile.last_state.idmap", jsonIdmap)
@@ -8157,6 +8163,28 @@ func (c *containerLXC) StoragePool() (string, error) {
 	return poolName, nil
 }
 
+// Progress tracking
+func (c *containerLXC) SetOperation(op *operation) {
+	c.op = op
+}
+
+func (c *containerLXC) updateProgress(progress string) {
+	if c.op == nil {
+		return
+	}
+
+	meta := c.op.metadata
+	if meta == nil {
+		meta = make(map[string]interface{})
+	}
+
+	if meta["container_progress"] != progress {
+		meta["container_progress"] = progress
+		c.op.UpdateMetadata(meta)
+	}
+}
+
+// Internal MAAS handling
 func (c *containerLXC) maasInterfaces() ([]maas.ContainerInterface, error) {
 	interfaces := []maas.ContainerInterface{}
 	for k, m := range c.expandedDevices {
diff --git a/lxd/container_state.go b/lxd/container_state.go
index 00b044b20..24a988076 100644
--- a/lxd/container_state.go
+++ b/lxd/container_state.go
@@ -73,6 +73,7 @@ func containerStatePut(d *Daemon, r *http.Request) Response {
 	case shared.Start:
 		opDescription = "Starting container"
 		do = func(op *operation) error {
+			c.SetOperation(op)
 			if err = c.Start(raw.Stateful); err != nil {
 				return err
 			}
@@ -82,6 +83,7 @@ func containerStatePut(d *Daemon, r *http.Request) Response {
 		opDescription = "Stopping container"
 		if raw.Stateful {
 			do = func(op *operation) error {
+				c.SetOperation(op)
 				err := c.Stop(raw.Stateful)
 				if err != nil {
 					return err
@@ -91,6 +93,7 @@ func containerStatePut(d *Daemon, r *http.Request) Response {
 			}
 		} else if raw.Timeout == 0 || raw.Force {
 			do = func(op *operation) error {
+				c.SetOperation(op)
 				err = c.Stop(false)
 				if err != nil {
 					return err
@@ -100,6 +103,7 @@ func containerStatePut(d *Daemon, r *http.Request) Response {
 			}
 		} else {
 			do = func(op *operation) error {
+				c.SetOperation(op)
 				if c.IsFrozen() {
 					err := c.Unfreeze()
 					if err != nil {
@@ -118,6 +122,7 @@ func containerStatePut(d *Daemon, r *http.Request) Response {
 	case shared.Restart:
 		opDescription = "Restarting container"
 		do = func(op *operation) error {
+			c.SetOperation(op)
 			ephemeral := c.IsEphemeral()
 
 			if ephemeral {
@@ -169,11 +174,13 @@ func containerStatePut(d *Daemon, r *http.Request) Response {
 	case shared.Freeze:
 		opDescription = "Freezing container"
 		do = func(op *operation) error {
+			c.SetOperation(op)
 			return c.Freeze()
 		}
 	case shared.Unfreeze:
 		opDescription = "Unfreezing container"
 		do = func(op *operation) error {
+			c.SetOperation(op)
 			return c.Unfreeze()
 		}
 	default:


More information about the lxc-devel mailing list