The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7010
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) === Avoids errors such as: ``` DBUG[03-12|09:36:31] New task Operation: c0d6aaba-3130-4987-8002-74f069bebe10 DBUG[03-12|09:36:31] Failure for task operation: 28799184-e121-4ad6-8139-9da30b7130b2: Error retrieving image info 8bac6546bbc5cfbe5c490f2c991cff8cff1428b57fb9a74d33a64cb6dff66601: No such object ```
From 666fbce982dca85bfd7dfcaa6a8e628499c63303 Mon Sep 17 00:00:00 2001 From: Thomas Parrott <thomas.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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.parr...@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) } }
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel