The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6532

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) ===
Hi @stgraber, we wanted to get some input for our progress. We have created the new images_profiles table, and we can successfully read and modify it within the three lxc commands referenced in the issue. We are also able to apply the user-specified default profiles with `lxc launch <image>`, but we are still working on adding the "default" profile to the images_profile table when an image is first created. 

Please let us know if you have any thoughts about our progress.
From e171c7844a3f8bd3e326a2fe18c990b8c2b88a87 Mon Sep 17 00:00:00 2001
From: Jack Stenglein <jackstengl...@utexas.edu>
Date: Sun, 24 Nov 2019 18:08:54 -0600
Subject: [PATCH 1/4] api: Add image_profiles extension

Signed-off-by: Rizwan Lubis <rizwan.lu...@gmail.com>
Signed-off-by: Jack Stenglein <jackstengl...@gmail.com>
---
 doc/api-extensions.md | 3 +++
 shared/version/api.go | 1 +
 2 files changed, 4 insertions(+)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 1b836a0623..632ce186ac 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -886,3 +886,6 @@ This allows for existing a CEPH RDB or FS to be directly 
connected to a LXD cont
 
 ## virtual\_machines
 Add virtual machine support.
+
+## image\_profiles
+Allows a list of profiles to be applied to an image when launching a new 
container. 
diff --git a/shared/version/api.go b/shared/version/api.go
index 1afdc1b2d0..7a2602b1b5 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -179,6 +179,7 @@ var APIExtensions = []string{
        "container_syscall_intercept_mount_fuse",
        "container_disk_ceph",
        "virtual-machines",
+       "image_profiles"
 }
 
 // APIExtensionsCount returns the number of available API extensions.

From 57c49ee07753922e239c76f0d60ecc0d7e647819 Mon Sep 17 00:00:00 2001
From: Jack Stenglein <jackstengl...@utexas.edu>
Date: Sun, 24 Nov 2019 18:15:17 -0600
Subject: [PATCH 2/4] shared/api: Add image profiles

Signed-off-by: Rizwan Lubis <rizwan.lu...@gmail.com>
Signed-off-by: Jack Stenglein <jackstengl...@gmail.com>
---
 shared/api/image.go | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/shared/api/image.go b/shared/api/image.go
index 0eb4c392e6..dc48850c4b 100644
--- a/shared/api/image.go
+++ b/shared/api/image.go
@@ -44,6 +44,9 @@ type ImagePut struct {
 
        // API extension: images_expiry
        ExpiresAt time.Time `json:"expires_at" yaml:"expires_at"`
+       
+       // API extension: image_profiles
+       Profiles []string `json:"profiles" yaml:"profiles"`
 }
 
 // Image represents a LXD image

From d224caf8862dc0aab16e680e0a17c0b6edf457cf Mon Sep 17 00:00:00 2001
From: Jack Stenglein <jackstengl...@utexas.edu>
Date: Sun, 24 Nov 2019 18:52:14 -0600
Subject: [PATCH 3/4] lxd/db: Add images_profiles table

Signed-off-by: Rizwan Lubis <rizwan.lu...@gmail.com>
Signed-off-by: Jack Stenglein <jackstengl...@gmail.com>
---
 lxc/image.go               | 12 ++++++
 lxd/db/cluster/schema.go   |  8 +++-
 lxd/db/cluster/update.go   | 15 +++++++
 lxd/db/images.go           | 38 +++++++++++++++-
 lxd/db/instances.mapper.go | 88 +++++++++++++++++++-------------------
 lxd/images.go              | 20 +++++++--
 shared/version/api.go      |  2 +-
 7 files changed, 131 insertions(+), 52 deletions(-)

diff --git a/lxc/image.go b/lxc/image.go
index 47db1ae9ed..a89e729933 100644
--- a/lxc/image.go
+++ b/lxc/image.go
@@ -406,6 +406,9 @@ func (c *cmdImageEdit) Run(cmd *cobra.Command, args 
[]string) error {
                newdata := api.ImagePut{}
                err = yaml.Unmarshal(content, &newdata)
                if err == nil {
+                       if newdata.Profiles == nil {
+                               newdata.Profiles = []string{"default"}
+                       }
                        err = resource.server.UpdateImage(image, newdata, etag)
                }
 
@@ -927,6 +930,15 @@ func (c *cmdImageInfo) Run(cmd *cobra.Command, args 
[]string) error {
                fmt.Printf("    Alias: %s\n", info.UpdateSource.Alias)
        }
 
+       if len(info.Profiles) == 0 {
+               fmt.Printf(i18n.G("Profiles: ") + "[]\n")
+       } else {
+               fmt.Println(i18n.G("Profiles:"))
+               for _, name := range info.Profiles {
+                       fmt.Printf("    - %s\n", name)
+               }
+       }
+
        return nil
 }
 
diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go
index 33fe82b2e0..db03bbec58 100644
--- a/lxd/db/cluster/schema.go
+++ b/lxd/db/cluster/schema.go
@@ -57,6 +57,12 @@ CREATE TABLE images_nodes (
     FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE,
     FOREIGN KEY (node_id) REFERENCES nodes (id) ON DELETE CASCADE
 );
+CREATE TABLE images_profiles (
+       image_id INTEGER NOT NULL,
+       profile_id INTEGER NOT NULL,
+       FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE,
+       FOREIGN KEY (profile_id) REFERENCES profiles (id) ON DELETE CASCADE
+);
 CREATE INDEX images_project_id_idx ON images (project_id);
 CREATE TABLE images_properties (
     id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -487,5 +493,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..85d4c91efb 100644
--- a/lxd/db/cluster/update.go
+++ b/lxd/db/cluster/update.go
@@ -53,6 +53,21 @@ var updates = map[int]schema.Update{
        16: updateFromV15,
        17: updateFromV16,
        18: updateFromV17,
+       19: updateFromV18,
+}
+
+// Add images_profiles table
+func updateFromV18(tx *sql.Tx) error {
+       stmts := `
+CREATE TABLE images_profiles (
+       image_id INTEGER NOT NULL,
+       profile_id INTEGER NOT NULL,
+       FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE,
+       FOREIGN KEY (profile_id) REFERENCES profiles (id) ON DELETE CASCADE
+);
+`
+       _, err := tx.Exec(stmts)
+       return err
 }
 
 // Add nodes_roles table
diff --git a/lxd/db/images.go b/lxd/db/images.go
index 2db6855437..dc9e34878c 100644
--- a/lxd/db/images.go
+++ b/lxd/db/images.go
@@ -8,7 +8,6 @@ import (
        "time"
 
        "github.com/pkg/errors"
-
        "github.com/lxc/lxd/lxd/db/query"
        "github.com/lxc/lxd/lxd/instance/instancetype"
        "github.com/lxc/lxd/shared/api"
@@ -476,6 +475,23 @@ func (c *Cluster) imageFill(id int, image *api.Image, 
create, expire, used, uplo
 
        image.Aliases = aliases
 
+       // Get the profiles
+       q = "SELECT name FROM profiles WHERE id IN (SELECT profile_id FROM 
images_profiles WHERE image_id=?)"
+       inargs = []interface{}{id}
+       outfmt = []interface{}{name}
+       results, err = queryScan(c.db, q, inargs, outfmt)
+       if err != nil {
+               return err
+       }
+
+       profiles := make([]string, 0)
+       for _, r := range results {
+               name = r[0].(string)
+               profiles = append(profiles, name)
+       }
+
+       image.Profiles = profiles
+       
        _, source, err := c.ImageSourceGet(id)
        if err == nil {
                image.UpdateSource = &source
@@ -737,7 +753,7 @@ func (c *Cluster) ImageLastAccessInit(fingerprint string) 
error {
 }
 
 // ImageUpdate updates the image with the given ID.
-func (c *Cluster) ImageUpdate(id int, fname string, sz int64, public bool, 
autoUpdate bool, architecture string, createdAt time.Time, expiresAt time.Time, 
properties map[string]string) error {
+func (c *Cluster) ImageUpdate(id int, fname string, sz int64, public bool, 
autoUpdate bool, architecture string, createdAt time.Time, expiresAt time.Time, 
properties map[string]string, profileIds []int64) error {
        arch, err := osarch.ArchitectureId(architecture)
        if err != nil {
                arch = 0
@@ -783,6 +799,24 @@ func (c *Cluster) ImageUpdate(id int, fname string, sz 
int64, public bool, autoU
                        }
                }
 
+               _, err = tx.tx.Exec(`DELETE FROM images_profiles WHERE 
image_id=?`, id)
+               if err != nil {
+                       return err
+               }
+
+               stmt3, err := tx.tx.Prepare(`INSERT INTO images_profiles 
(image_id, profile_id) VALUES (?, ?)`)
+               if err != nil {
+                       return err
+               }
+               defer stmt3.Close()
+
+               for _, profileId := range profileIds {
+                       _, err = stmt3.Exec(id, profileId)
+                       if err != nil {
+                               return err
+                       }
+               }
+
                return nil
        })
        return err
diff --git a/lxd/db/instances.mapper.go b/lxd/db/instances.mapper.go
index ce827a8960..171d0aad25 100644
--- a/lxd/db/instances.mapper.go
+++ b/lxd/db/instances.mapper.go
@@ -235,19 +235,19 @@ func (c *ClusterTx) InstanceList(filter InstanceFilter) 
([]Instance, error) {
                        filter.Node,
                        filter.Name,
                }
-       } else if criteria["Project"] != nil && criteria["Type"] != nil && 
criteria["Node"] != nil {
-               stmt = c.stmt(instanceObjectsByProjectAndTypeAndNode)
+       } else if criteria["Project"] != nil && criteria["Name"] != nil && 
criteria["Node"] != nil {
+               stmt = c.stmt(instanceObjectsByProjectAndNameAndNode)
                args = []interface{}{
                        filter.Project,
-                       filter.Type,
+                       filter.Name,
                        filter.Node,
                }
-       } else if criteria["Project"] != nil && criteria["Type"] != nil && 
criteria["Name"] != nil {
-               stmt = c.stmt(instanceObjectsByProjectAndTypeAndName)
+       } else if criteria["Project"] != nil && criteria["Type"] != nil && 
criteria["Node"] != nil {
+               stmt = c.stmt(instanceObjectsByProjectAndTypeAndNode)
                args = []interface{}{
                        filter.Project,
                        filter.Type,
-                       filter.Name,
+                       filter.Node,
                }
        } else if criteria["Type"] != nil && criteria["Name"] != nil && 
criteria["Node"] != nil {
                stmt = c.stmt(instanceObjectsByTypeAndNameAndNode)
@@ -256,12 +256,12 @@ func (c *ClusterTx) InstanceList(filter InstanceFilter) 
([]Instance, error) {
                        filter.Name,
                        filter.Node,
                }
-       } else if criteria["Project"] != nil && criteria["Name"] != nil && 
criteria["Node"] != nil {
-               stmt = c.stmt(instanceObjectsByProjectAndNameAndNode)
+       } else if criteria["Project"] != nil && criteria["Type"] != nil && 
criteria["Name"] != nil {
+               stmt = c.stmt(instanceObjectsByProjectAndTypeAndName)
                args = []interface{}{
                        filter.Project,
+                       filter.Type,
                        filter.Name,
-                       filter.Node,
                }
        } else if criteria["Project"] != nil && criteria["Type"] != nil {
                stmt = c.stmt(instanceObjectsByProjectAndType)
@@ -275,16 +275,22 @@ func (c *ClusterTx) InstanceList(filter InstanceFilter) 
([]Instance, error) {
                        filter.Type,
                        filter.Node,
                }
+       } else if criteria["Type"] != nil && criteria["Name"] != nil {
+               stmt = c.stmt(instanceObjectsByTypeAndName)
+               args = []interface{}{
+                       filter.Type,
+                       filter.Name,
+               }
        } else if criteria["Project"] != nil && criteria["Node"] != nil {
                stmt = c.stmt(instanceObjectsByProjectAndNode)
                args = []interface{}{
                        filter.Project,
                        filter.Node,
                }
-       } else if criteria["Type"] != nil && criteria["Name"] != nil {
-               stmt = c.stmt(instanceObjectsByTypeAndName)
+       } else if criteria["Node"] != nil && criteria["Name"] != nil {
+               stmt = c.stmt(instanceObjectsByNodeAndName)
                args = []interface{}{
-                       filter.Type,
+                       filter.Node,
                        filter.Name,
                }
        } else if criteria["Project"] != nil && criteria["Name"] != nil {
@@ -293,10 +299,14 @@ func (c *ClusterTx) InstanceList(filter InstanceFilter) 
([]Instance, error) {
                        filter.Project,
                        filter.Name,
                }
-       } else if criteria["Node"] != nil && criteria["Name"] != nil {
-               stmt = c.stmt(instanceObjectsByNodeAndName)
+       } else if criteria["Project"] != nil {
+               stmt = c.stmt(instanceObjectsByProject)
+               args = []interface{}{
+                       filter.Project,
+               }
+       } else if criteria["Name"] != nil {
+               stmt = c.stmt(instanceObjectsByName)
                args = []interface{}{
-                       filter.Node,
                        filter.Name,
                }
        } else if criteria["Type"] != nil {
@@ -309,16 +319,6 @@ func (c *ClusterTx) InstanceList(filter InstanceFilter) 
([]Instance, error) {
                args = []interface{}{
                        filter.Node,
                }
-       } else if criteria["Project"] != nil {
-               stmt = c.stmt(instanceObjectsByProject)
-               args = []interface{}{
-                       filter.Project,
-               }
-       } else if criteria["Name"] != nil {
-               stmt = c.stmt(instanceObjectsByName)
-               args = []interface{}{
-                       filter.Name,
-               }
        } else {
                stmt = c.stmt(instanceObjects)
                args = []interface{}{}
@@ -583,28 +583,28 @@ func (c *ClusterTx) InstanceProfilesRef(filter 
InstanceFilter) (map[string]map[s
        var stmt *sql.Stmt
        var args []interface{}
 
-       if criteria["Project"] != nil && criteria["Name"] != nil {
-               stmt = c.stmt(instanceProfilesRefByProjectAndName)
-               args = []interface{}{
-                       filter.Project,
-                       filter.Name,
-               }
-       } else if criteria["Project"] != nil && criteria["Node"] != nil {
+       if criteria["Project"] != nil && criteria["Node"] != nil {
                stmt = c.stmt(instanceProfilesRefByProjectAndNode)
                args = []interface{}{
                        filter.Project,
                        filter.Node,
                }
-       } else if criteria["Project"] != nil {
-               stmt = c.stmt(instanceProfilesRefByProject)
+       } else if criteria["Project"] != nil && criteria["Name"] != nil {
+               stmt = c.stmt(instanceProfilesRefByProjectAndName)
                args = []interface{}{
                        filter.Project,
+                       filter.Name,
                }
        } else if criteria["Node"] != nil {
                stmt = c.stmt(instanceProfilesRefByNode)
                args = []interface{}{
                        filter.Node,
                }
+       } else if criteria["Project"] != nil {
+               stmt = c.stmt(instanceProfilesRefByProject)
+               args = []interface{}{
+                       filter.Project,
+               }
        } else {
                stmt = c.stmt(instanceProfilesRef)
                args = []interface{}{}
@@ -686,16 +686,16 @@ func (c *ClusterTx) InstanceConfigRef(filter 
InstanceFilter) (map[string]map[str
                        filter.Project,
                        filter.Name,
                }
-       } else if criteria["Project"] != nil {
-               stmt = c.stmt(instanceConfigRefByProject)
-               args = []interface{}{
-                       filter.Project,
-               }
        } else if criteria["Node"] != nil {
                stmt = c.stmt(instanceConfigRefByNode)
                args = []interface{}{
                        filter.Node,
                }
+       } else if criteria["Project"] != nil {
+               stmt = c.stmt(instanceConfigRefByProject)
+               args = []interface{}{
+                       filter.Project,
+               }
        } else {
                stmt = c.stmt(instanceConfigRef)
                args = []interface{}{}
@@ -782,16 +782,16 @@ func (c *ClusterTx) InstanceDevicesRef(filter 
InstanceFilter) (map[string]map[st
                        filter.Project,
                        filter.Node,
                }
-       } else if criteria["Node"] != nil {
-               stmt = c.stmt(instanceDevicesRefByNode)
-               args = []interface{}{
-                       filter.Node,
-               }
        } else if criteria["Project"] != nil {
                stmt = c.stmt(instanceDevicesRefByProject)
                args = []interface{}{
                        filter.Project,
                }
+       } else if criteria["Node"] != nil {
+               stmt = c.stmt(instanceDevicesRefByNode)
+               args = []interface{}{
+                       filter.Node,
+               }
        } else {
                stmt = c.stmt(instanceDevicesRef)
                args = []interface{}{}
diff --git a/lxd/images.go b/lxd/images.go
index cf989c4011..7eb732b8cd 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -347,7 +347,7 @@ func imgPostRemoteInfo(d *Daemon, req api.ImagesPost, op 
*operations.Operation,
 
        // Update the DB record if needed
        if req.Public || req.AutoUpdate || req.Filename != "" || 
len(req.Properties) > 0 {
-               err = d.cluster.ImageUpdate(id, req.Filename, info.Size, 
req.Public, req.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
info.Properties)
+               err = d.cluster.ImageUpdate(id, req.Filename, info.Size, 
req.Public, req.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
info.Properties, nil)
                if err != nil {
                        return nil, err
                }
@@ -415,7 +415,7 @@ func imgPostURLInfo(d *Daemon, req api.ImagesPost, op 
*operations.Operation, pro
        }
 
        if req.Public || req.AutoUpdate || req.Filename != "" || 
len(req.Properties) > 0 {
-               err = d.cluster.ImageUpdate(id, req.Filename, info.Size, 
req.Public, req.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
info.Properties)
+               err = d.cluster.ImageUpdate(id, req.Filename, info.Size, 
req.Public, req.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
info.Properties, nil)
                if err != nil {
                        return nil, err
                }
@@ -1597,7 +1597,19 @@ func imagePut(d *Daemon, r *http.Request) 
response.Response {
                info.ExpiresAt = req.ExpiresAt
        }
 
-       err = d.cluster.ImageUpdate(id, info.Filename, info.Size, req.Public, 
req.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
req.Properties)
+       // Get profile ids
+       profileIds := make([]int64, len(req.Profiles))
+       for i, profile := range req.Profiles {
+               profileId, _, err := d.cluster.ProfileGet(project, profile)
+               if err == db.ErrNoSuchObject {
+                       return response.BadRequest(fmt.Errorf("Profile '%s' 
doesn't exist", profile))
+               } else if (err != nil) {
+                       return response.SmartError(err)
+               }
+               profileIds[i] = profileId
+       }
+
+       err = d.cluster.ImageUpdate(id, info.Filename, info.Size, req.Public, 
req.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
req.Properties, profileIds)
        if err != nil {
                return response.SmartError(err)
        }
@@ -1664,7 +1676,7 @@ func imagePatch(d *Daemon, r *http.Request) 
response.Response {
                info.Properties = properties
        }
 
-       err = d.cluster.ImageUpdate(id, info.Filename, info.Size, info.Public, 
info.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
info.Properties)
+       err = d.cluster.ImageUpdate(id, info.Filename, info.Size, info.Public, 
info.AutoUpdate, info.Architecture, info.CreatedAt, info.ExpiresAt, 
info.Properties, nil)
        if err != nil {
                return response.SmartError(err)
        }
diff --git a/shared/version/api.go b/shared/version/api.go
index 7a2602b1b5..931606c8f0 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -179,7 +179,7 @@ var APIExtensions = []string{
        "container_syscall_intercept_mount_fuse",
        "container_disk_ceph",
        "virtual-machines",
-       "image_profiles"
+       "image_profiles",
 }
 
 // APIExtensionsCount returns the number of available API extensions.

From 2e40fc32048b3ad1c6f0eebcbc30539de8201aa8 Mon Sep 17 00:00:00 2001
From: Jack Stenglein <jackstengl...@utexas.edu>
Date: Fri, 29 Nov 2019 15:18:28 -0600
Subject: [PATCH 4/4] lxd/images: Add support for image profiles

Signed-off-by: Rizwan Lubis <rizwan.lu...@gmail.com>
Signed-off-by: Jack Stenglein <jackstengl...@gmail.com>
---
 lxc/init.go      | 21 +++++++++++----------
 lxd/container.go |  7 ++++++-
 lxd/db/images.go | 25 +++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/lxc/init.go b/lxc/init.go
index 3530ac214f..873cfe10b6 100644
--- a/lxc/init.go
+++ b/lxc/init.go
@@ -219,16 +219,6 @@ func (c *cmdInit) create(conf *config.Config, args 
[]string) (lxd.InstanceServer
        }
        req.Config = configMap
        req.Devices = devicesMap
-
-       if !c.flagNoProfiles && len(profiles) == 0 {
-               if len(stdinData.Profiles) > 0 {
-                       req.Profiles = stdinData.Profiles
-               } else {
-                       req.Profiles = nil
-               }
-       } else {
-               req.Profiles = profiles
-       }
        req.Ephemeral = c.flagEphemeral
 
        var opInfo api.Operation
@@ -274,6 +264,17 @@ func (c *cmdInit) create(conf *config.Config, args 
[]string) (lxd.InstanceServer
                        }
                }
 
+               // Set up profiles
+               if c.flagNoProfiles {
+                       req.Profiles = []string{}
+               } else if len(profiles) > 0 {
+                       req.Profiles = profiles
+               } else if len(stdinData.Profiles) > 0 {
+                       req.Profiles = stdinData.Profiles
+               } else {
+                       req.Profiles = imgInfo.Profiles
+               }
+
                // Create the instance
                op, err := d.CreateInstanceFromImage(imgRemote, *imgInfo, req)
                if err != nil {
diff --git a/lxd/container.go b/lxd/container.go
index 54ab1691d7..9e8b426c89 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -868,7 +868,12 @@ func instanceCreateInternal(s *state.State, args 
db.InstanceArgs) (instance.Inst
        }
 
        if args.Profiles == nil {
-               args.Profiles = []string{"default"}
+               profiles, err := s.Cluster.ImageProfilesGet(args.BaseImage)
+               if err != nil {
+                       return nil, err
+               }
+               args.Profiles = profiles
+               logger.Infof("Got profiles: %v", args.Profiles)
        }
 
        if args.Config == nil {
diff --git a/lxd/db/images.go b/lxd/db/images.go
index dc9e34878c..eb1bad5b50 100644
--- a/lxd/db/images.go
+++ b/lxd/db/images.go
@@ -737,6 +737,31 @@ func (c *Cluster) ImageAliasUpdate(id int, imageID int, 
desc string) error {
        return err
 }
 
+func (c *Cluster) ImageProfilesGet(fingerprint string) ([]string, error) {
+       // Get the profiles
+       q := `
+SELECT profiles.name FROM profiles 
+  JOIN images_profiles ON images_profiles.profile_id = profiles.id
+  JOIN images ON images_profiles.image_id = images.id
+WHERE images.fingerprint = ?
+`
+       var name string
+       inargs := []interface{}{fingerprint}
+       outfmt := []interface{}{name}
+       results, err := queryScan(c.db, q, inargs, outfmt)
+       if err != nil {
+               return nil, err
+       }
+
+       profiles := make([]string, 0)
+       for _, r := range results {
+               name = r[0].(string)
+               profiles = append(profiles, name)
+       }
+
+       return profiles, nil
+}
+
 // ImageLastAccessUpdate updates the last_use_date field of the image with the
 // given fingerprint.
 func (c *Cluster) ImageLastAccessUpdate(fingerprint string, date time.Time) 
error {
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to