[lxc-devel] [lxd/master] Apply image properties in DB during publish

stgraber on Github lxc-bot at linuxcontainers.org
Mon Jul 13 14:06:27 UTC 2020


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200713/0d529f89/attachment.bin>
-------------- next part --------------
From 77e19289c20a218fc59dda591c952287fa8bad1d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 13 Jul 2020 09:53:11 -0400
Subject: [PATCH 1/2] lxd/images: Rename imgPostContInfo to imgPostInstanceInfo
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/images.go   | 4 ++--
 lxd/instance.go | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/lxd/images.go b/lxd/images.go
index 8c14b10d5d..c5453a3ab2 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -174,7 +174,7 @@ func compressFile(compress string, infile io.Reader, outfile io.Writer) error {
  * This function takes a container or snapshot from the local image server and
  * exports it as an image.
  */
-func imgPostContInfo(d *Daemon, r *http.Request, req api.ImagesPost, op *operations.Operation, builddir string) (*api.Image, error) {
+func imgPostInstanceInfo(d *Daemon, r *http.Request, req api.ImagesPost, op *operations.Operation, builddir string) (*api.Image, error) {
 	info := api.Image{}
 	info.Properties = map[string]string{}
 	project := projectParam(r)
@@ -821,7 +821,7 @@ func imagesPost(d *Daemon, r *http.Request) response.Response {
 			} else {
 				/* Processing image creation from container */
 				imagePublishLock.Lock()
-				info, err = imgPostContInfo(d, r, req, op, builddir)
+				info, err = imgPostInstanceInfo(d, r, req, op, builddir)
 				imagePublishLock.Unlock()
 			}
 		}
diff --git a/lxd/instance.go b/lxd/instance.go
index 9b63bb49a0..736c00c273 100644
--- a/lxd/instance.go
+++ b/lxd/instance.go
@@ -126,6 +126,7 @@ func instanceCreateFromImage(d *Daemon, args db.InstanceArgs, hash string, op *o
 	if img.Properties != nil {
 		for k, v := range img.Properties {
 			args.Config[fmt.Sprintf("image.%s", k)] = v
+			logger.Errorf("Setting: image.%v=%v", k, v)
 		}
 	}
 

From ffe63869ef256c135a46d7dd6fcee1a7cc8f45d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Mon, 13 Jul 2020 10:05:33 -0400
Subject: [PATCH 2/2] lxd/instances: Return and set image properties
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes #7648

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/images.go                       |  5 +-
 lxd/instance/drivers/driver_lxc.go  | 77 +++++++++++++-------------
 lxd/instance/drivers/driver_qemu.go | 85 +++++++++++++++--------------
 lxd/instance/instance_interface.go  |  2 +-
 4 files changed, 86 insertions(+), 83 deletions(-)

diff --git a/lxd/images.go b/lxd/images.go
index c5453a3ab2..61b4c79554 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -293,7 +293,8 @@ func imgPostInstanceInfo(d *Daemon, r *http.Request, req api.ImagesPost, op *ope
 	}
 
 	// Export instance to writer.
-	err = c.Export(writer, req.Properties)
+	var meta api.ImageMetadata
+	meta, err = c.Export(writer, req.Properties)
 
 	// Clean up file handles.
 	// When compression is used, Close on imageProgressWriter/tarWriter is required for compressFile/gzip to
@@ -337,7 +338,7 @@ func imgPostInstanceInfo(d *Daemon, r *http.Request, req api.ImagesPost, op *ope
 	}
 
 	info.Architecture, _ = osarch.ArchitectureName(c.Architecture())
-	info.Properties = req.Properties
+	info.Properties = meta.Properties
 
 	// Create the database entry
 	err = d.cluster.CreateImage(c.Project(), info.Fingerprint, info.Filename, info.Size, info.Public, info.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, info.Properties, info.Type)
diff --git a/lxd/instance/drivers/driver_lxc.go b/lxd/instance/drivers/driver_lxc.go
index 256cc7573a..b5eac46db7 100644
--- a/lxd/instance/drivers/driver_lxc.go
+++ b/lxd/instance/drivers/driver_lxc.go
@@ -4546,7 +4546,7 @@ func (c *lxc) updateDevices(removeDevices deviceConfig.Devices, addDevices devic
 }
 
 // Export backs up the instance.
-func (c *lxc) Export(w io.Writer, properties map[string]string) error {
+func (c *lxc) Export(w io.Writer, properties map[string]string) (api.ImageMetadata, error) {
 	ctxMap := log.Ctx{
 		"project":   c.project,
 		"name":      c.name,
@@ -4554,8 +4554,10 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 		"ephemeral": c.ephemeral,
 		"used":      c.lastUsedDate}
 
+	meta := api.ImageMetadata{}
+
 	if c.IsRunning() {
-		return fmt.Errorf("Cannot export a running instance as an image")
+		return meta, fmt.Errorf("Cannot export a running instance as an image")
 	}
 
 	logger.Info("Exporting instance", ctxMap)
@@ -4564,7 +4566,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 	ourStart, err := c.mount()
 	if err != nil {
 		logger.Error("Failed exporting instance", ctxMap)
-		return err
+		return meta, err
 	}
 	if ourStart {
 		defer c.unmount()
@@ -4574,7 +4576,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 	idmap, err := c.DiskIdmap()
 	if err != nil {
 		logger.Error("Failed exporting instance", ctxMap)
-		return err
+		return meta, err
 	}
 
 	// Create the tarball.
@@ -4607,7 +4609,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 		defer os.RemoveAll(tempDir)
 
@@ -4619,7 +4621,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 
 			arch, _ = osarch.ArchitectureName(parent.Architecture())
@@ -4631,12 +4633,11 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 			arch, err = osarch.ArchitectureName(c.state.OS.Architectures[0])
 			if err != nil {
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 		}
 
 		// Fill in the metadata.
-		meta := api.ImageMetadata{}
 		meta.Architecture = arch
 		meta.CreationDate = time.Now().UTC().Unix()
 		meta.Properties = properties
@@ -4645,7 +4646,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		// Write the actual file.
@@ -4654,14 +4655,14 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		fi, err := os.Lstat(fnam)
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		tmpOffset := len(path.Dir(fnam)) + 1
@@ -4669,41 +4670,41 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 			tarWriter.Close()
 			logger.Debugf("Error writing to tarfile: %s", err)
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 	} else {
-		if properties != nil {
-			// Parse the metadata.
-			content, err := ioutil.ReadFile(fnam)
-			if err != nil {
-				tarWriter.Close()
-				logger.Error("Failed exporting instance", ctxMap)
-				return err
-			}
+		// Parse the metadata.
+		content, err := ioutil.ReadFile(fnam)
+		if err != nil {
+			tarWriter.Close()
+			logger.Error("Failed exporting instance", ctxMap)
+			return meta, err
+		}
 
-			metadata := new(api.ImageMetadata)
-			err = yaml.Unmarshal(content, &metadata)
-			if err != nil {
-				tarWriter.Close()
-				logger.Error("Failed exporting instance", ctxMap)
-				return err
-			}
-			metadata.Properties = properties
+		err = yaml.Unmarshal(content, &meta)
+		if err != nil {
+			tarWriter.Close()
+			logger.Error("Failed exporting instance", ctxMap)
+			return meta, err
+		}
+
+		if properties != nil {
+			meta.Properties = properties
 
 			// Generate a new metadata.yaml.
 			tempDir, err := ioutil.TempDir("", "lxd_lxd_metadata_")
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 			defer os.RemoveAll(tempDir)
 
-			data, err := yaml.Marshal(&metadata)
+			data, err := yaml.Marshal(&meta)
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 
 			// Write the actual file.
@@ -4712,7 +4713,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 		}
 
@@ -4722,7 +4723,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 			tarWriter.Close()
 			logger.Debugf("Error statting %s during export", fnam)
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		if properties != nil {
@@ -4735,7 +4736,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 			tarWriter.Close()
 			logger.Debugf("Error writing to tarfile: %s", err)
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 	}
 
@@ -4744,7 +4745,7 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 	err = filepath.Walk(fnam, writeToTar)
 	if err != nil {
 		logger.Error("Failed exporting instance", ctxMap)
-		return err
+		return meta, err
 	}
 
 	// Include all the templates.
@@ -4753,18 +4754,18 @@ func (c *lxc) Export(w io.Writer, properties map[string]string) error {
 		err = filepath.Walk(fnam, writeToTar)
 		if err != nil {
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 	}
 
 	err = tarWriter.Close()
 	if err != nil {
 		logger.Error("Failed exporting instance", ctxMap)
-		return err
+		return meta, err
 	}
 
 	logger.Info("Exported instance", ctxMap)
-	return nil
+	return meta, nil
 }
 
 func collectCRIULogFile(c instance.Instance, imagesDir string, function string, method string) error {
diff --git a/lxd/instance/drivers/driver_qemu.go b/lxd/instance/drivers/driver_qemu.go
index 31c4bec940..bf38aeefdd 100644
--- a/lxd/instance/drivers/driver_qemu.go
+++ b/lxd/instance/drivers/driver_qemu.go
@@ -3345,7 +3345,7 @@ func (vm *qemu) deviceRemove(deviceName string, rawConfig deviceConfig.Device) e
 }
 
 // Export publishes the instance.
-func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
+func (vm *qemu) Export(w io.Writer, properties map[string]string) (api.ImageMetadata, error) {
 	ctxMap := log.Ctx{
 		"project":   vm.project,
 		"name":      vm.name,
@@ -3353,8 +3353,10 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 		"ephemeral": vm.ephemeral,
 		"used":      vm.lastUsedDate}
 
+	meta := api.ImageMetadata{}
+
 	if vm.IsRunning() {
-		return fmt.Errorf("Cannot export a running instance as an image")
+		return meta, fmt.Errorf("Cannot export a running instance as an image")
 	}
 
 	logger.Info("Exporting instance", ctxMap)
@@ -3363,7 +3365,7 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 	ourStart, err := vm.mount()
 	if err != nil {
 		logger.Error("Failed exporting instance", ctxMap)
-		return err
+		return meta, err
 	}
 	if ourStart {
 		defer vm.unmount()
@@ -3398,7 +3400,7 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 		defer os.RemoveAll(tempDir)
 
@@ -3410,7 +3412,7 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 
 			arch, _ = osarch.ArchitectureName(parent.Architecture())
@@ -3422,12 +3424,11 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 			arch, err = osarch.ArchitectureName(vm.state.OS.Architectures[0])
 			if err != nil {
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 		}
 
 		// Fill in the metadata.
-		meta := api.ImageMetadata{}
 		meta.Architecture = arch
 		meta.CreationDate = time.Now().UTC().Unix()
 		meta.Properties = properties
@@ -3436,7 +3437,7 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		// Write the actual file.
@@ -3445,55 +3446,55 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		fi, err := os.Lstat(fnam)
 		if err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		tmpOffset := len(filepath.Dir(fnam)) + 1
 		if err := tarWriter.WriteFile(fnam[tmpOffset:], fnam, fi, false); err != nil {
 			tarWriter.Close()
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 	} else {
-		if properties != nil {
-			// Parse the metadata.
-			content, err := ioutil.ReadFile(fnam)
-			if err != nil {
-				tarWriter.Close()
-				logger.Error("Failed exporting instance", ctxMap)
-				return err
-			}
+		// Parse the metadata.
+		content, err := ioutil.ReadFile(fnam)
+		if err != nil {
+			tarWriter.Close()
+			logger.Error("Failed exporting instance", ctxMap)
+			return meta, err
+		}
 
-			metadata := new(api.ImageMetadata)
-			err = yaml.Unmarshal(content, &metadata)
-			if err != nil {
-				tarWriter.Close()
-				logger.Error("Failed exporting instance", ctxMap)
-				return err
-			}
-			metadata.Properties = properties
+		err = yaml.Unmarshal(content, &meta)
+		if err != nil {
+			tarWriter.Close()
+			logger.Error("Failed exporting instance", ctxMap)
+			return meta, err
+		}
+
+		if properties != nil {
+			meta.Properties = properties
 
 			// Generate a new metadata.yaml.
 			tempDir, err := ioutil.TempDir("", "lxd_lxd_metadata_")
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 			defer os.RemoveAll(tempDir)
 
-			data, err := yaml.Marshal(&metadata)
+			data, err := yaml.Marshal(&meta)
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 
 			// Write the actual file.
@@ -3502,7 +3503,7 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 			if err != nil {
 				tarWriter.Close()
 				logger.Error("Failed exporting instance", ctxMap)
-				return err
+				return meta, err
 			}
 		}
 
@@ -3512,7 +3513,7 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 			tarWriter.Close()
 			logger.Debugf("Error statting %s during export", fnam)
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 
 		if properties != nil {
@@ -3525,43 +3526,43 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 			tarWriter.Close()
 			logger.Debugf("Error writing to tarfile: %s", err)
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 	}
 
 	// Convert and include the root image.
 	pool, err := vm.getStoragePool()
 	if err != nil {
-		return err
+		return meta, err
 	}
 
 	rootDrivePath, err := pool.GetInstanceDisk(vm)
 	if err != nil {
-		return err
+		return meta, err
 	}
 
 	// Convert from raw to qcow2 and add to tarball.
 	tmpPath, err := ioutil.TempDir(shared.VarPath("images"), "lxd_export_")
 	if err != nil {
-		return err
+		return meta, err
 	}
 	defer os.RemoveAll(tmpPath)
 
 	fPath := fmt.Sprintf("%s/rootfs.img", tmpPath)
 	_, err = shared.RunCommand("qemu-img", "convert", "-c", "-O", "qcow2", rootDrivePath, fPath)
 	if err != nil {
-		return fmt.Errorf("Failed converting image to qcow2: %v", err)
+		return meta, fmt.Errorf("Failed converting image to qcow2: %v", err)
 	}
 
 	fi, err := os.Lstat(fPath)
 	if err != nil {
-		return err
+		return meta, err
 	}
 
 	imgOffset := len(tmpPath) + 1
 	err = tarWriter.WriteFile(fPath[imgOffset:], fPath, fi, false)
 	if err != nil {
-		return err
+		return meta, err
 	}
 
 	// Include all the templates.
@@ -3570,18 +3571,18 @@ func (vm *qemu) Export(w io.Writer, properties map[string]string) error {
 		err = filepath.Walk(fnam, writeToTar)
 		if err != nil {
 			logger.Error("Failed exporting instance", ctxMap)
-			return err
+			return meta, err
 		}
 	}
 
 	err = tarWriter.Close()
 	if err != nil {
 		logger.Error("Failed exporting instance", ctxMap)
-		return err
+		return meta, err
 	}
 
 	logger.Info("Exported instance", ctxMap)
-	return nil
+	return meta, nil
 }
 
 // Migrate migrates the instance to another node.
diff --git a/lxd/instance/instance_interface.go b/lxd/instance/instance_interface.go
index efad8bea9b..cf2d316c32 100644
--- a/lxd/instance/instance_interface.go
+++ b/lxd/instance/instance_interface.go
@@ -66,7 +66,7 @@ type Instance interface {
 	Update(newConfig db.InstanceArgs, userRequested bool) error
 
 	Delete() error
-	Export(w io.Writer, properties map[string]string) error
+	Export(w io.Writer, properties map[string]string) (api.ImageMetadata, error)
 
 	// Live configuration.
 	CGroupSet(key string, value string) error


More information about the lxc-devel mailing list