[lxc-devel] [lxd/master] Images: Allow pruning of expires images in non-default project
tomponline on Github
lxc-bot at linuxcontainers.org
Thu Mar 12 10:16:21 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 613 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200312/616d75da/attachment.bin>
-------------- next part --------------
From 666fbce982dca85bfd7dfcaa6a8e628499c63303 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 12 Mar 2020 10:12:39 +0000
Subject: [PATCH 1/3] lxd/db/images: Removes unnecessary whitespace
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/images.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/db/images.go b/lxd/db/images.go
index d8916d14f6..79d792d451 100644
--- a/lxd/db/images.go
+++ b/lxd/db/images.go
@@ -532,7 +532,7 @@ func (c *Cluster) imageFillProfiles(id int, image *api.Image, project string) er
// Get the profiles
q := `
-SELECT profiles.name FROM profiles
+SELECT profiles.name FROM profiles
JOIN images_profiles ON images_profiles.profile_id = profiles.id
JOIN projects ON profiles.project_id = projects.id
WHERE images_profiles.image_id = ? AND projects.name = ?
@@ -886,7 +886,7 @@ func (c *Cluster) ImageUpdate(id int, fname string, sz int64, public bool, autoU
if !enabled {
project = "default"
}
- q := `DELETE FROM images_profiles
+ q := `DELETE FROM images_profiles
WHERE image_id = ? AND profile_id IN (
SELECT profiles.id FROM profiles
JOIN projects ON profiles.project_id = projects.id
From dbc2ef7d06e61daa4a47a5397b75eb9694aa13b3 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 12 Mar 2020 10:10:42 +0000
Subject: [PATCH 2/3] lxd/db/images: Updates ImagesGetExpired to return
ExpireImage struct with projectName
So that deleting expired images can be done when the image is in a non-default project.
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/db/images.go | 37 ++++++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/lxd/db/images.go b/lxd/db/images.go
index 79d792d451..f196c3a0ce 100644
--- a/lxd/db/images.go
+++ b/lxd/db/images.go
@@ -88,23 +88,37 @@ SELECT fingerprint
return results, nil
}
-// ImagesGetExpired returns the names of all images that have expired since the
-// given time.
-func (c *Cluster) ImagesGetExpired(expiry int64) ([]string, error) {
- q := `SELECT fingerprint, last_use_date, upload_date FROM images WHERE cached=1`
+// ExpiredImage used to store expired image info.
+type ExpiredImage struct {
+ Fingerprint string
+ ProjectName string
+}
+
+// ImagesGetExpired returns the names and project name of all images that have expired since the given time.
+func (c *Cluster) ImagesGetExpired(expiry int64) ([]ExpiredImage, error) {
+ q := `
+ SELECT
+ fingerprint,
+ last_use_date,
+ upload_date,
+ projects.name as projectName
+ FROM images
+ JOIN projects ON projects.id = images.project_id
+ WHERE images.cached = 1`
var fpStr string
var useStr string
var uploadStr string
+ var projectName string
inargs := []interface{}{}
- outfmt := []interface{}{fpStr, useStr, uploadStr}
+ outfmt := []interface{}{fpStr, useStr, uploadStr, projectName}
dbResults, err := queryScan(c.db, q, inargs, outfmt)
if err != nil {
- return []string{}, err
+ return []ExpiredImage{}, err
}
- results := []string{}
+ results := []ExpiredImage{}
for _, r := range dbResults {
// Figure out the expiry
timestamp := r[2]
@@ -115,7 +129,7 @@ func (c *Cluster) ImagesGetExpired(expiry int64) ([]string, error) {
var imageExpiry time.Time
err = imageExpiry.UnmarshalText([]byte(timestamp.(string)))
if err != nil {
- return []string{}, err
+ return []ExpiredImage{}, err
}
imageExpiry = imageExpiry.Add(time.Duration(expiry*24) * time.Hour)
@@ -124,7 +138,12 @@ func (c *Cluster) ImagesGetExpired(expiry int64) ([]string, error) {
continue
}
- results = append(results, r[0].(string))
+ result := ExpiredImage{
+ Fingerprint: r[0].(string),
+ ProjectName: r[3].(string),
+ }
+
+ results = append(results, result)
}
return results, nil
From 5a3d40a46d065a21932f9e69c44804c811da2a2a Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parrott at canonical.com>
Date: Thu, 12 Mar 2020 10:12:06 +0000
Subject: [PATCH 3/3] lxd/images: Updates pruneExpiredImages to support
removing expired images from non-default projects
Signed-off-by: Thomas Parrott <thomas.parrott at canonical.com>
---
lxd/images.go | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/lxd/images.go b/lxd/images.go
index c05c7d6582..9f804c2c8c 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -33,7 +33,6 @@ import (
"github.com/lxc/lxd/lxd/instance/instancetype"
"github.com/lxc/lxd/lxd/node"
"github.com/lxc/lxd/lxd/operations"
- "github.com/lxc/lxd/lxd/project"
"github.com/lxc/lxd/lxd/response"
"github.com/lxc/lxd/lxd/state"
storagePools "github.com/lxc/lxd/lxd/storage"
@@ -1305,7 +1304,7 @@ func pruneExpiredImages(ctx context.Context, d *Daemon) error {
}
// Delete them
- for _, fp := range images {
+ for _, img := range images {
// At each iteration we check if we got cancelled in the
// meantime. It is safe to abort here since anything not
// expired now will be expired at the next run.
@@ -1317,7 +1316,7 @@ func pruneExpiredImages(ctx context.Context, d *Daemon) error {
// Get the IDs of all storage pools on which a storage volume
// for the requested image currently exists.
- poolIDs, err := d.cluster.ImageGetPools(fp)
+ poolIDs, err := d.cluster.ImageGetPools(img.Fingerprint)
if err != nil {
continue
}
@@ -1329,38 +1328,38 @@ func pruneExpiredImages(ctx context.Context, d *Daemon) error {
}
for _, pool := range poolNames {
- err := doDeleteImageFromPool(d.State(), fp, pool)
+ err := doDeleteImageFromPool(d.State(), img.Fingerprint, pool)
if err != nil {
- return errors.Wrapf(err, "Error deleting image %s from storage pool %s", fp, pool)
+ return errors.Wrapf(err, "Error deleting image %q from storage pool %q", img.Fingerprint, pool)
}
}
// Remove main image file.
- fname := filepath.Join(d.os.VarDir, "images", fp)
+ fname := filepath.Join(d.os.VarDir, "images", img.Fingerprint)
if shared.PathExists(fname) {
err = os.Remove(fname)
if err != nil && !os.IsNotExist(err) {
- return errors.Wrapf(err, "Error deleting image file %s", fname)
+ return errors.Wrapf(err, "Error deleting image file %q", fname)
}
}
// Remove the rootfs file for the image.
- fname = filepath.Join(d.os.VarDir, "images", fp) + ".rootfs"
+ fname = filepath.Join(d.os.VarDir, "images", img.Fingerprint) + ".rootfs"
if shared.PathExists(fname) {
err = os.Remove(fname)
if err != nil && !os.IsNotExist(err) {
- return errors.Wrapf(err, "Error deleting image file %s", fname)
+ return errors.Wrapf(err, "Error deleting image file %q", fname)
}
}
- imgID, _, err := d.cluster.ImageGet(project.Default, fp, false, false)
+ imgID, _, err := d.cluster.ImageGet(img.ProjectName, img.Fingerprint, false, false)
if err != nil {
- return errors.Wrapf(err, "Error retrieving image info %s", fp)
+ return errors.Wrapf(err, "Error retrieving image info for fingerprint %q and project %q", img.Fingerprint, img.ProjectName)
}
// Remove the database entry for the image.
if err = d.cluster.ImageDelete(imgID); err != nil {
- return errors.Wrapf(err, "Error deleting image %s from database", fp)
+ return errors.Wrapf(err, "Error deleting image %q from database", img.Fingerprint)
}
}
More information about the lxc-devel
mailing list