[lxc-devel] [lxd/master] Dont hard code UsedBy urls in db views

freeekanayaka on Github lxc-bot at linuxcontainers.org
Tue Nov 26 17:44:34 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 388 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20191126/ff687e7d/attachment.bin>
-------------- next part --------------
From 97e4e2fc22c7af4660990a71493962b184c738bf Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 26 Nov 2019 17:00:01 +0000
Subject: [PATCH 1/2] Change the profiles_used_by_ref db view to not hard-code
 URLs

Free Ekanayaka <free.ekanayaka at canonical.com>
---
 lxd/db/cluster/schema.go |  9 +++++----
 lxd/db/cluster/update.go | 27 +++++++++++++++++++++++++++
 lxd/db/db.go             | 23 +++++++++++++++++++++++
 lxd/db/profiles.go       |  2 +-
 4 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go
index 33fe82b2e0..27d0cb2fa8 100644
--- a/lxd/db/cluster/schema.go
+++ b/lxd/db/cluster/schema.go
@@ -389,9 +389,10 @@ CREATE VIEW profiles_used_by_ref (project,
     value) AS
   SELECT projects.name,
     profiles.name,
-    printf('/1.0/containers/%s?project=%s',
-    "instances".name,
-    instances_projects.name)
+    printf('%s/%s/%d',
+    instances_projects.name,
+    instances.name,
+    instances.type)
     FROM profiles
     JOIN projects ON projects.id=profiles.project_id
     JOIN "instances_profiles"
@@ -487,5 +488,5 @@ CREATE TABLE storage_volumes_config (
     FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE
 );
 
-INSERT INTO schema (version, updated_at) VALUES (18, strftime("%s"))
+INSERT INTO schema (version, updated_at) VALUES (19, strftime("%s"))
 `
diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go
index 461672ad67..ecfc45bf2a 100644
--- a/lxd/db/cluster/update.go
+++ b/lxd/db/cluster/update.go
@@ -53,6 +53,33 @@ var updates = map[int]schema.Update{
 	16: updateFromV15,
 	17: updateFromV16,
 	18: updateFromV17,
+	19: updateFromV18,
+}
+
+// Don't hardcode resource URLs in used-by views.
+func updateFromV18(tx *sql.Tx) error {
+	stmts := `
+DROP VIEW profiles_used_by_ref;
+CREATE VIEW profiles_used_by_ref (project,
+    name,
+    value) AS
+  SELECT projects.name,
+    profiles.name,
+    printf('%s/%s/%d',
+    instances_projects.name,
+    instances.name,
+    instances.type)
+    FROM profiles
+    JOIN projects ON projects.id=profiles.project_id
+    JOIN "instances_profiles"
+      ON "instances_profiles".profile_id=profiles.id
+    JOIN "instances"
+      ON "instances".id="instances_profiles".instance_id
+    JOIN projects AS instances_projects
+      ON instances_projects.id="instances".project_id;
+`
+	_, err := tx.Exec(stmts)
+	return err
 }
 
 // Add nodes_roles table
diff --git a/lxd/db/db.go b/lxd/db/db.go
index c0f5d1f5b5..39b111a258 100644
--- a/lxd/db/db.go
+++ b/lxd/db/db.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
+	"strings"
 	"sync"
 	"time"
 
@@ -323,6 +324,28 @@ func ForLocalInspectionWithPreparedStmts(db *sql.DB) (*Cluster, error) {
 	return c, nil
 }
 
+// UsedByToAPI transforms all entries in the given usedBy slice from the
+// database representation ("<project>|<name>|<type>") to an actual API
+// resource URL. Note that this applies only to containers/instances/vms. Other
+// types of UsedBy strings (such as for images and profiles) are still returned
+// as URLs natively by the underlying VIEW.
+func UsedByToAPI(usedBy []string) []string {
+	usedByURLs := make([]string, len(usedBy))
+	for i, usedBy := range usedBy {
+		if strings.HasPrefix(usedBy, "/1.0/images/") || strings.HasPrefix(usedBy, "/1.0/profiles/") {
+			usedByURLs[i] = usedBy
+			continue
+		}
+		parts := strings.Split(usedBy, "/")
+		if len(parts) != 3 {
+			panic(fmt.Sprintf("unexpected UsedBy format: %s", usedBy))
+		}
+		project, name, _ := parts[0], parts[1], parts[2]
+		usedByURLs[i] = fmt.Sprintf("/1.0/containers/%s?project=%s", name, project)
+	}
+	return usedByURLs
+}
+
 // SetDefaultTimeout sets the default go-dqlite driver timeout.
 func (c *Cluster) SetDefaultTimeout(timeout time.Duration) {
 	driver := c.db.Driver().(*driver.Driver)
diff --git a/lxd/db/profiles.go b/lxd/db/profiles.go
index 99083b511f..4e41a903f8 100644
--- a/lxd/db/profiles.go
+++ b/lxd/db/profiles.go
@@ -66,7 +66,7 @@ type Profile struct {
 func ProfileToAPI(profile *Profile) *api.Profile {
 	p := &api.Profile{
 		Name:   profile.Name,
-		UsedBy: profile.UsedBy,
+		UsedBy: UsedByToAPI(profile.UsedBy),
 	}
 	p.Description = profile.Description
 	p.Config = profile.Config

From ea1af1dd662533a444477fe97418f6eff1fc75a8 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 26 Nov 2019 17:34:00 +0000
Subject: [PATCH 2/2] Change the projects_used_by_ref db view to not hard-code
 URLs for instances

---
 lxd/api_project.go       |  2 ++
 lxd/db/cluster/schema.go |  7 ++++---
 lxd/db/cluster/update.go | 18 ++++++++++++++++++
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/lxd/api_project.go b/lxd/api_project.go
index 27709e412c..1843f8a281 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -55,6 +55,7 @@ func projectsGet(d *Daemon, r *http.Request) response.Response {
 					continue
 				}
 
+				project.UsedBy = db.UsedByToAPI(project.UsedBy)
 				filtered = append(filtered, project)
 			}
 
@@ -194,6 +195,7 @@ func projectGet(d *Daemon, r *http.Request) response.Response {
 	if err != nil {
 		return response.SmartError(err)
 	}
+	project.UsedBy = db.UsedByToAPI(project.UsedBy)
 
 	etag := []interface{}{
 		project.Description,
diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go
index 27d0cb2fa8..13c92eb1af 100644
--- a/lxd/db/cluster/schema.go
+++ b/lxd/db/cluster/schema.go
@@ -426,9 +426,10 @@ CREATE VIEW projects_config_ref (name,
 CREATE VIEW projects_used_by_ref (name,
     value) AS
   SELECT projects.name,
-    printf('/1.0/containers/%s?project=%s',
-    "instances".name,
-    projects.name)
+    printf('%s/%s/%d',
+    projects.name,
+    instances.name,
+    instances.type)
     FROM "instances" JOIN projects ON project_id=projects.id UNION
   SELECT projects.name,
     printf('/1.0/images/%s',
diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go
index ecfc45bf2a..b92a97e82f 100644
--- a/lxd/db/cluster/update.go
+++ b/lxd/db/cluster/update.go
@@ -77,6 +77,24 @@ CREATE VIEW profiles_used_by_ref (project,
       ON "instances".id="instances_profiles".instance_id
     JOIN projects AS instances_projects
       ON instances_projects.id="instances".project_id;
+DROP VIEW projects_used_by_ref;
+CREATE VIEW projects_used_by_ref (name,
+    value) AS
+  SELECT projects.name,
+    printf('%s/%s/%d',
+    projects.name,
+    instances.name,
+    instances.type)
+    FROM "instances" JOIN projects ON project_id=projects.id UNION
+  SELECT projects.name,
+    printf('/1.0/images/%s',
+    images.fingerprint)
+    FROM images JOIN projects ON project_id=projects.id UNION
+  SELECT projects.name,
+    printf('/1.0/profiles/%s?project=%s',
+    profiles.name,
+    projects.name)
+    FROM profiles JOIN projects ON project_id=projects.id;
 `
 	_, err := tx.Exec(stmts)
 	return err


More information about the lxc-devel mailing list