[lxc-devel] [lxd/master] Return an error if an image already exists on import

albertodonato on Github lxc-bot at linuxcontainers.org
Wed May 3 15:47:01 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 397 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170503/586b8c4d/attachment.bin>
-------------- next part --------------
From ffef165814825126bc01a935760424e430a7d027 Mon Sep 17 00:00:00 2001
From: Alberto Donato <alberto.donato at canonical.com>
Date: Wed, 3 May 2017 16:36:12 +0200
Subject: [PATCH] Check if the image already exists.

Signed-off-by: Alberto Donato <alberto.donato at canonical.com>
---
 lxd/db_images.go | 36 ++++++++++++++++++------------------
 lxd/db_test.go   | 30 ++++++++++++++++++++++++++++++
 lxd/images.go    |  8 ++++++++
 3 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/lxd/db_images.go b/lxd/db_images.go
index 19f4269..cc6af2e 100644
--- a/lxd/db_images.go
+++ b/lxd/db_images.go
@@ -105,8 +105,17 @@ func dbImageSourceGet(db *sql.DB, imageId int) (int, api.ImageSource, error) {
 
 }
 
-// dbImageGet gets an ImageBaseInfo object from the database.
-// The argument fingerprint will be queried with a LIKE query, means you can
+// Whether an image with the given fingerprint exists.
+func dbImageExists(db *sql.DB, fingerprint string) (exists bool, err error) {
+	query := "SELECT COUNT(*) > 0 FROM images WHERE fingerprint=?"
+	inargs := []interface{}{fingerprint}
+	outargs := []interface{}{&exists}
+	err = dbQueryRowScan(db, query, inargs, outargs)
+	return
+}
+
+// dbImageGet gets an Image object from the database.
+// If strictMatching is false, The fingerprint argument will be queried with a LIKE query, means you can
 // pass a shortform and will get the full fingerprint.
 // There can never be more than one image with a given fingerprint, as it is
 // enforced by a UNIQUE constraint in the schema.
@@ -124,31 +133,22 @@ func dbImageGet(db *sql.DB, fingerprint string, public bool, strictMatching bool
 		&image.Size, &image.Cached, &image.Public, &image.AutoUpdate, &arch,
 		&create, &expire, &used, &upload}
 
-	var query string
-
 	var inargs []interface{}
-	if strictMatching {
-		inargs = []interface{}{fingerprint}
-		query = `
+	query := `
         SELECT
             id, fingerprint, filename, size, cached, public, auto_update, architecture,
             creation_date, expiry_date, last_use_date, upload_date
-        FROM
-            images
-        WHERE fingerprint = ?`
+        FROM images`
+	if strictMatching {
+		inargs = []interface{}{fingerprint}
+		query += " WHERE fingerprint = ?"
 	} else {
 		inargs = []interface{}{fingerprint + "%"}
-		query = `
-        SELECT
-            id, fingerprint, filename, size, cached, public, auto_update, architecture,
-            creation_date, expiry_date, last_use_date, upload_date
-        FROM
-            images
-        WHERE fingerprint LIKE ?`
+		query += " WHERE fingerprint LIKE ?"
 	}
 
 	if public {
-		query = query + " AND public=1"
+		query += " AND public=1"
 	}
 
 	err = dbQueryRowScan(db, query, inargs, outfmt)
diff --git a/lxd/db_test.go b/lxd/db_test.go
index 03adce0..2a406e6 100644
--- a/lxd/db_test.go
+++ b/lxd/db_test.go
@@ -463,6 +463,36 @@ func Test_dbImageGet_for_missing_fingerprint(t *testing.T) {
 	}
 }
 
+func Test_dbImageExists(t *testing.T) {
+	var db *sql.DB
+	var err error
+
+	db = createTestDb(t)
+	defer db.Close()
+
+	t.Run("true", func(t *testing.T) {
+		exists, err := dbImageExists(db, "fingerprint")
+
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !exists {
+			t.Fatal("Image not found by fingerprint")
+		}
+	})
+
+	t.Run("false", func(t *testing.T) {
+		exists, err := dbImageExists(db, "foobar")
+
+		if err != nil {
+			t.Fatal(err)
+		}
+		if exists {
+			t.Fatal("Image should not have been found")
+		}
+	})
+}
+
 func Test_dbImageAliasGet_alias_exists(t *testing.T) {
 	var db *sql.DB
 	var err error
diff --git a/lxd/images.go b/lxd/images.go
index 01c44f6..1bcd5d9 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -620,6 +620,14 @@ func getImgPostInfo(d *Daemon, r *http.Request, builddir string, post *os.File)
 		}
 	}
 
+	// Check if the image already exists
+	exists, err := dbImageExists(d.db, info.Fingerprint)
+	if err != nil {
+		return nil, err
+	}
+	if exists {
+		return nil, fmt.Errorf("Image with same fingerprint already exists")
+	}
 	// Create the database entry
 	err = dbImageInsert(d.db, info.Fingerprint, info.Filename, info.Size, info.Public, info.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, info.Properties)
 	if err != nil {


More information about the lxc-devel mailing list