[lxc-devel] [lxd/master] UsedBy consistency
stgraber on Github
lxc-bot at linuxcontainers.org
Thu Jun 18 23:36:01 UTC 2020
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20200618/aae2f260/attachment-0001.bin>
-------------- next part --------------
From 7b91d36fa35fa67a167d07842a9771d31687dc07 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jun 2020 17:10:14 -0400
Subject: [PATCH 1/6] lxd/storage-pools: Tweak UsedBy URLs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/db/storage_pools.go | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go
index 72d436d6f8..294cb6e751 100644
--- a/lxd/db/storage_pools.go
+++ b/lxd/db/storage_pools.go
@@ -88,16 +88,16 @@ func (c *ClusterTx) GetStoragePoolUsedBy(name string) ([]string, error) {
}
for _, r := range vols {
- // Handle the containers.
- if r.volType == StoragePoolVolumeTypeContainer {
+ // Handle instances.
+ if r.volType == StoragePoolVolumeTypeContainer || r.volType == StoragePoolVolumeTypeVM {
if r.projectName == "default" {
- usedby = append(usedby, fmt.Sprintf("/1.0/container/%s", r.volName))
+ usedby = append(usedby, fmt.Sprintf("/1.0/instances/%s", r.volName))
} else {
- usedby = append(usedby, fmt.Sprintf("/1.0/container/%s?project=%s", r.volName, r.projectName))
+ usedby = append(usedby, fmt.Sprintf("/1.0/instances/%s?project=%s", r.volName, r.projectName))
}
}
- // Handle the images.
+ // Handle images.
if r.volType == StoragePoolVolumeTypeImage {
// Get the projects using an image.
stmt := "SELECT projects.name FROM images LEFT JOIN projects ON projects.id=images.project_id WHERE fingerprint=?"
@@ -115,7 +115,7 @@ func (c *ClusterTx) GetStoragePoolUsedBy(name string) ([]string, error) {
}
}
- // Handle the custom volumes.
+ // Handle custom storage volumes.
if r.volType == StoragePoolVolumeTypeCustom {
if len(nodes) > 1 {
if r.projectName == "default" {
@@ -131,15 +131,6 @@ func (c *ClusterTx) GetStoragePoolUsedBy(name string) ([]string, error) {
}
}
}
-
- // Handle the virtual machines.
- if r.volType == StoragePoolVolumeTypeVM {
- if r.projectName == "default" {
- usedby = append(usedby, fmt.Sprintf("/1.0/virtual-machine/%s", r.volName))
- } else {
- usedby = append(usedby, fmt.Sprintf("/1.0/virtual-machine/%s?project=%s", r.volName, r.projectName))
- }
- }
}
// Get all the profiles using the storage pool.
From bbb08bc183f4ba5b31dfde30837a403a2e1d492a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jun 2020 18:09:32 -0400
Subject: [PATCH 2/6] lxd/networks: Reports profiles in UsedBy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/network/network.go | 2 +-
lxd/network/network_utils.go | 17 ++++++++++++++---
lxd/networks.go | 27 ++++++++++++++++++++++++++-
3 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/lxd/network/network.go b/lxd/network/network.go
index 2c5d9abad3..6e2fcd3dd6 100644
--- a/lxd/network/network.go
+++ b/lxd/network/network.go
@@ -80,7 +80,7 @@ func (n *Network) IsUsed() bool {
}
for _, inst := range insts {
- if IsInUse(inst, n.name) {
+ if IsInUseByInstance(inst, n.name) {
return true
}
}
diff --git a/lxd/network/network_utils.go b/lxd/network/network_utils.go
index 14fe9230df..668764fe87 100644
--- a/lxd/network/network_utils.go
+++ b/lxd/network/network_utils.go
@@ -18,6 +18,7 @@ import (
"github.com/pkg/errors"
+ deviceConfig "github.com/lxc/lxd/lxd/device/config"
"github.com/lxc/lxd/lxd/dnsmasq"
"github.com/lxc/lxd/lxd/instance"
"github.com/lxc/lxd/lxd/instance/instancetype"
@@ -28,10 +29,20 @@ import (
"github.com/lxc/lxd/shared/logger"
)
-// IsInUse indicates if network is reference by any instance's NIC devices.
+// IsInUseByInstance indicates if network is referenced by an instance's NIC devices.
// Checks if the device's parent or network properties match the network name.
-func IsInUse(c instance.Instance, networkName string) bool {
- for _, d := range c.ExpandedDevices() {
+func IsInUseByInstance(c instance.Instance, networkName string) bool {
+ return isInUseByDevices(c.ExpandedDevices(), networkName)
+}
+
+// IsInUseByProfile indicates if network is referenced by a profile's NIC devices.
+// Checks if the device's parent or network properties match the network name.
+func IsInUseByProfile(profile api.Profile, networkName string) bool {
+ return isInUseByDevices(deviceConfig.NewDevices(profile.Devices), networkName)
+}
+
+func isInUseByDevices(devices deviceConfig.Devices, networkName string) bool {
+ for _, d := range devices {
if d["type"] != "nic" {
continue
}
diff --git a/lxd/networks.go b/lxd/networks.go
index 20ca524815..73d40bc168 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -402,13 +402,14 @@ func doNetworkGet(d *Daemon, name string) (api.Network, error) {
// Look for containers using the interface
if n.Type != "loopback" {
+ // Look at instances.
insts, err := instance.LoadFromAllProjects(d.State())
if err != nil {
return api.Network{}, err
}
for _, inst := range insts {
- if network.IsInUse(inst, n.Name) {
+ if network.IsInUseByInstance(inst, n.Name) {
uri := fmt.Sprintf("/%s/instances/%s", version.APIVersion, inst.Name())
if inst.Project() != project.Default {
uri += fmt.Sprintf("?project=%s", inst.Project())
@@ -416,6 +417,30 @@ func doNetworkGet(d *Daemon, name string) (api.Network, error) {
n.UsedBy = append(n.UsedBy, uri)
}
}
+
+ // Look for profiles.
+ var profiles []db.Profile
+ err = d.cluster.Transaction(func(tx *db.ClusterTx) error {
+ profiles, err = tx.GetProfiles(db.ProfileFilter{})
+ if err != nil {
+ return err
+ }
+
+ return nil
+ })
+ if err != nil {
+ return api.Network{}, err
+ }
+
+ for _, profile := range profiles {
+ if network.IsInUseByProfile(*db.ProfileToAPI(&profile), n.Name) {
+ uri := fmt.Sprintf("/%s/profiles/%s", version.APIVersion, profile.Name)
+ if profile.Project != project.Default {
+ uri += fmt.Sprintf("?project=%s", profile.Project)
+ }
+ n.UsedBy = append(n.UsedBy, uri)
+ }
+ }
}
if dbInfo != nil {
From 58c49f14870a898082338f38d8e69be0b6be858d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jun 2020 18:28:49 -0400
Subject: [PATCH 3/6] lxd/db: Tweak joins
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/db/storage_pools.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go
index 294cb6e751..145fda4b12 100644
--- a/lxd/db/storage_pools.go
+++ b/lxd/db/storage_pools.go
@@ -77,7 +77,7 @@ func (c *ClusterTx) GetStoragePoolUsedBy(name string) ([]string, error) {
return []interface{}{&vols[i].volName, &vols[i].volType, &vols[i].projectName, &vols[i].nodeID}
}
- stmt, err := c.tx.Prepare("SELECT storage_volumes.name, storage_volumes.type, projects.name, storage_volumes.node_id FROM storage_volumes LEFT JOIN projects ON projects.id=storage_volumes.project_id WHERE storage_pool_id=? AND (node_id=? OR storage_volumes.type == 2) ORDER BY storage_volumes.type ASC, projects.name ASC, storage_volumes.name ASC, storage_volumes.node_id ASC")
+ stmt, err := c.tx.Prepare("SELECT storage_volumes.name, storage_volumes.type, projects.name, storage_volumes.node_id FROM storage_volumes JOIN projects ON projects.id=storage_volumes.project_id WHERE storage_pool_id=? AND (node_id=? OR storage_volumes.type == 2) ORDER BY storage_volumes.type ASC, projects.name ASC, storage_volumes.name ASC, storage_volumes.node_id ASC")
if err != nil {
return nil, err
}
@@ -100,7 +100,7 @@ func (c *ClusterTx) GetStoragePoolUsedBy(name string) ([]string, error) {
// Handle images.
if r.volType == StoragePoolVolumeTypeImage {
// Get the projects using an image.
- stmt := "SELECT projects.name FROM images LEFT JOIN projects ON projects.id=images.project_id WHERE fingerprint=?"
+ stmt := "SELECT projects.name FROM images JOIN projects ON projects.id=images.project_id WHERE fingerprint=?"
projects, err := query.SelectStrings(c.tx, stmt, r.volName)
if err != nil {
return nil, err
From fdbcb6a502b946e886769978071023cecc9a28fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jun 2020 18:33:37 -0400
Subject: [PATCH 4/6] lxd/db: Fix UsedBy on projects
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/db/cluster/schema.go | 14 +++++++++++---
lxd/db/cluster/update.go | 34 ++++++++++++++++++++++++++++++++++
lxd/db/profiles.mapper.go | 9 ++++++---
lxd/db/projects.mapper.go | 9 ++++++---
lxd/db/storage_pools.go | 2 +-
shared/generate/db/method.go | 9 ++++++---
6 files changed, 64 insertions(+), 13 deletions(-)
diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go
index ed551c5cda..4280575b98 100644
--- a/lxd/db/cluster/schema.go
+++ b/lxd/db/cluster/schema.go
@@ -438,9 +438,17 @@ CREATE VIEW projects_used_by_ref (name,
projects.name)
FROM "instances" JOIN projects ON project_id=projects.id UNION
SELECT projects.name,
- printf('/1.0/images/%s',
- images.fingerprint)
+ printf('/1.0/images/%s?project=%s',
+ images.fingerprint,
+ projects.name)
FROM images JOIN projects ON project_id=projects.id UNION
+ SELECT projects.name,
+ printf('/1.0/storage-pools/%s/volumes/custom/%s?project=%s&target=%s',
+ storage_pools.name,
+ storage_volumes.name,
+ projects.name,
+ nodes.name)
+ FROM storage_volumes JOIN storage_pools ON storage_pool_id=storage_pools.id JOIN nodes ON node_id=nodes.id JOIN projects ON project_id=projects.id WHERE storage_volumes.type=2 UNION
SELECT projects.name,
printf('/1.0/profiles/%s?project=%s',
profiles.name,
@@ -553,5 +561,5 @@ CREATE TABLE storage_volumes_snapshots_config (
UNIQUE (storage_volume_snapshot_id, key)
);
-INSERT INTO schema (version, updated_at) VALUES (29, strftime("%s"))
+INSERT INTO schema (version, updated_at) VALUES (30, strftime("%s"))
`
diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go
index f2bb9f8cfd..51758c5f32 100644
--- a/lxd/db/cluster/update.go
+++ b/lxd/db/cluster/update.go
@@ -66,6 +66,40 @@ var updates = map[int]schema.Update{
27: updateFromV26,
28: updateFromV27,
29: updateFromV28,
+ 30: updateFromV29,
+}
+
+// Add storage volumes to projects references and fix images.
+func updateFromV29(tx *sql.Tx) error {
+ stmts := `
+DROP VIEW projects_used_by_ref;
+CREATE VIEW projects_used_by_ref (name,
+ value) AS
+ SELECT projects.name,
+ printf('/1.0/instances/%s?project=%s',
+ "instances".name,
+ projects.name)
+ FROM "instances" JOIN projects ON project_id=projects.id UNION
+ SELECT projects.name,
+ printf('/1.0/images/%s?project=%s',
+ images.fingerprint,
+ projects.name)
+ FROM images JOIN projects ON project_id=projects.id UNION
+ SELECT projects.name,
+ printf('/1.0/storage-pools/%s/volumes/custom/%s?project=%s&target=%s',
+ storage_pools.name,
+ storage_volumes.name,
+ projects.name,
+ nodes.name)
+ FROM storage_volumes JOIN storage_pools ON storage_pool_id=storage_pools.id JOIN nodes ON node_id=nodes.id JOIN projects ON project_id=projects.id WHERE storage_volumes.type=2 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
}
// Attempt to add missing project feature
diff --git a/lxd/db/profiles.mapper.go b/lxd/db/profiles.mapper.go
index 256733abfe..6df1fdcd66 100644
--- a/lxd/db/profiles.mapper.go
+++ b/lxd/db/profiles.mapper.go
@@ -278,9 +278,12 @@ func (c *ClusterTx) GetProfiles(filter ProfileFilter) ([]Profile, error) {
if value == nil {
value = []string{}
}
- for j, entry := range value {
- if len(entry) > 16 && entry[len(entry)-16:] == "?project=default" {
- value[j] = entry[0 : len(entry)-16]
+ for j := range value {
+ if len(value[j]) > 12 && value[j][len(value[j])-12:] == "&target=none" {
+ value[j] = value[j][0 : len(value[j])-12]
+ }
+ if len(value[j]) > 16 && value[j][len(value[j])-16:] == "?project=default" {
+ value[j] = value[j][0 : len(value[j])-16]
}
}
objects[i].UsedBy = value
diff --git a/lxd/db/projects.mapper.go b/lxd/db/projects.mapper.go
index 01b9ef3cf5..6c8565127b 100644
--- a/lxd/db/projects.mapper.go
+++ b/lxd/db/projects.mapper.go
@@ -177,9 +177,12 @@ func (c *ClusterTx) GetProjects(filter ProjectFilter) ([]api.Project, error) {
if value == nil {
value = []string{}
}
- for j, entry := range value {
- if len(entry) > 16 && entry[len(entry)-16:] == "?project=default" {
- value[j] = entry[0 : len(entry)-16]
+ for j := range value {
+ if len(value[j]) > 12 && value[j][len(value[j])-12:] == "&target=none" {
+ value[j] = value[j][0 : len(value[j])-12]
+ }
+ if len(value[j]) > 16 && value[j][len(value[j])-16:] == "?project=default" {
+ value[j] = value[j][0 : len(value[j])-16]
}
}
objects[i].UsedBy = value
diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go
index 145fda4b12..e89431ad0f 100644
--- a/lxd/db/storage_pools.go
+++ b/lxd/db/storage_pools.go
@@ -117,7 +117,7 @@ func (c *ClusterTx) GetStoragePoolUsedBy(name string) ([]string, error) {
// Handle custom storage volumes.
if r.volType == StoragePoolVolumeTypeCustom {
- if len(nodes) > 1 {
+ if nodesName[r.nodeID] != "none" {
if r.projectName == "default" {
usedby = append(usedby, fmt.Sprintf("/1.0/storage-pools/%s/volumes/custom/%s?target=%s", name, r.volName, nodesName[r.nodeID]))
} else {
diff --git a/shared/generate/db/method.go b/shared/generate/db/method.go
index acb6048121..d89b8efc5f 100644
--- a/shared/generate/db/method.go
+++ b/shared/generate/db/method.go
@@ -532,9 +532,12 @@ func (m *Method) fillSliceReferenceField(buf *file.Buffer, nk []*Field, field *F
buf.L(" value = %s{}", field.Type.Name)
buf.L(" }")
if field.Name == "UsedBy" {
- buf.L(" for j, entry := range value {")
- buf.L(" if len(entry) > 16 && entry[len(entry)-16:] == \"?project=default\" {")
- buf.L(" value[j] = entry[0:len(entry)-16]")
+ buf.L(" for j := range value {")
+ buf.L(" if len(value[j]) > 12 && value[j][len(value[j])-12:] == \"&target=none\" {")
+ buf.L(" value[j] = value[j][0:len(value[j])-12]")
+ buf.L(" }")
+ buf.L(" if len(value[j]) > 16 && value[j][len(value[j])-16:] == \"?project=default\" {")
+ buf.L(" value[j] = value[j][0:len(value[j])-16]")
buf.L(" }")
buf.L(" }")
}
From fe00ecde2c695a3d2fc19d990cc3af3603d5fc3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jun 2020 19:12:42 -0400
Subject: [PATCH 5/6] lxd/storage_volumes: Fix UsedBy
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
lxd/storage_volumes.go | 24 ++++++++++++----
lxd/storage_volumes_utils.go | 54 +++++++++++++++++++++++-------------
2 files changed, 53 insertions(+), 25 deletions(-)
diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index f4c194fe2c..cd4ee60f7c 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -155,13 +155,25 @@ func storagePoolVolumesGet(d *Daemon, r *http.Request) response.Response {
if !recursion {
volName, snapName, ok := shared.InstanceGetParentAndSnapshotName(volume.Name)
if ok {
- resultString = append(resultString,
- fmt.Sprintf("/%s/storage-pools/%s/volumes/%s/%s/snapshots/%s",
- version.APIVersion, poolName, apiEndpoint, volName, snapName))
+ if projectName == project.Default {
+ resultString = append(resultString,
+ fmt.Sprintf("/%s/storage-pools/%s/volumes/%s/%s/snapshots/%s",
+ version.APIVersion, poolName, apiEndpoint, volName, snapName))
+ } else {
+ resultString = append(resultString,
+ fmt.Sprintf("/%s/storage-pools/%s/volumes/%s/%s/snapshots/%s?project=%s",
+ version.APIVersion, poolName, apiEndpoint, volName, snapName, projectName))
+ }
} else {
- resultString = append(resultString,
- fmt.Sprintf("/%s/storage-pools/%s/volumes/%s/%s",
- version.APIVersion, poolName, apiEndpoint, volume.Name))
+ if projectName == project.Default {
+ resultString = append(resultString,
+ fmt.Sprintf("/%s/storage-pools/%s/volumes/%s/%s",
+ version.APIVersion, poolName, apiEndpoint, volume.Name))
+ } else {
+ resultString = append(resultString,
+ fmt.Sprintf("/%s/storage-pools/%s/volumes/%s/%s?project=%s",
+ version.APIVersion, poolName, apiEndpoint, volume.Name, projectName))
+ }
}
} else {
volumeUsedBy, err := storagePoolVolumeUsedByGet(d.State(), projectName, poolName, volume.Name, volume.Type)
diff --git a/lxd/storage_volumes_utils.go b/lxd/storage_volumes_utils.go
index 7a014e13af..9de58c8cdf 100644
--- a/lxd/storage_volumes_utils.go
+++ b/lxd/storage_volumes_utils.go
@@ -203,24 +203,35 @@ func storagePoolVolumeUpdateUsers(d *Daemon, projectName string, oldPoolName str
}
// volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/containers/%s", version.APIVersion, ct))
-func storagePoolVolumeUsedByGet(s *state.State, project, poolName string, volumeName string, volumeTypeName string) ([]string, error) {
- // Handle container volumes
- if volumeTypeName == "container" {
+func storagePoolVolumeUsedByGet(s *state.State, projectName string, poolName string, volumeName string, volumeTypeName string) ([]string, error) {
+ // Handle instance volumes.
+ if volumeTypeName == "container" || volumeTypeName == "virtual-machine" {
cName, sName, snap := shared.InstanceGetParentAndSnapshotName(volumeName)
-
if snap {
- return []string{fmt.Sprintf("/%s/containers/%s/snapshots/%s", version.APIVersion, cName, sName)}, nil
+ if projectName == project.Default {
+ return []string{fmt.Sprintf("/%s/instances/%s/snapshots/%s", version.APIVersion, cName, sName)}, nil
+ } else {
+ return []string{fmt.Sprintf("/%s/instances/%s/snapshots/%s?project=%s", version.APIVersion, cName, sName, projectName)}, nil
+ }
}
- return []string{fmt.Sprintf("/%s/containers/%s", version.APIVersion, cName)}, nil
+ if projectName == project.Default {
+ return []string{fmt.Sprintf("/%s/instances/%s", version.APIVersion, cName)}, nil
+ } else {
+ return []string{fmt.Sprintf("/%s/instances/%s?project=%s", version.APIVersion, cName, projectName)}, nil
+ }
}
- // Handle image volumes
+ // Handle image volumes.
if volumeTypeName == "image" {
- return []string{fmt.Sprintf("/%s/images/%s", version.APIVersion, volumeName)}, nil
+ if projectName == project.Default {
+ return []string{fmt.Sprintf("/%s/images/%s", version.APIVersion, volumeName)}, nil
+ } else {
+ return []string{fmt.Sprintf("/%s/images/%s?project=%s", version.APIVersion, volumeName, projectName)}, nil
+ }
}
- // Check if the daemon itself is using it
+ // Check if the daemon itself is using it.
used, err := storagePools.VolumeUsedByDaemon(s, poolName, volumeName)
if err != nil {
return []string{}, err
@@ -230,29 +241,34 @@ func storagePoolVolumeUsedByGet(s *state.State, project, poolName string, volume
return []string{fmt.Sprintf("/%s", version.APIVersion)}, nil
}
- // Look for containers using this volume
- ctsUsingVolume, err := storagePools.VolumeUsedByInstancesGet(s, project, poolName, volumeName)
+ // Look for instances using this volume.
+ volumeUsedBy := []string{}
+
+ ctsUsingVolume, err := storagePools.VolumeUsedByInstancesGet(s, projectName, poolName, volumeName)
if err != nil {
return []string{}, err
}
- volumeUsedBy := []string{}
for _, ct := range ctsUsingVolume {
- volumeUsedBy = append(volumeUsedBy,
- fmt.Sprintf("/%s/containers/%s", version.APIVersion, ct))
+ if projectName == project.Default {
+ volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/instances/%s", version.APIVersion, ct))
+ } else {
+ volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/instances/%s?project=%s", version.APIVersion, ct, projectName))
+ }
}
+ // Look for profiles using this volume.
profiles, err := profilesUsingPoolVolumeGetNames(s.Cluster, volumeName, volumeTypeName)
if err != nil {
return []string{}, err
}
- if len(volumeUsedBy) == 0 && len(profiles) == 0 {
- return []string{}, nil
- }
-
for _, pName := range profiles {
- volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/profiles/%s", version.APIVersion, pName))
+ if projectName == project.Default {
+ volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/profiles/%s", version.APIVersion, pName))
+ } else {
+ volumeUsedBy = append(volumeUsedBy, fmt.Sprintf("/%s/profiles/%s?project=%s", version.APIVersion, pName, projectName))
+ }
}
return volumeUsedBy, nil
From 6ca075cd2b56fd796477f37916019d9ce728db28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Thu, 18 Jun 2020 19:32:07 -0400
Subject: [PATCH 6/6] api: usedby_consistency
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Closes #7518
Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
doc/api-extensions.md | 11 +++++++++++
shared/version/api.go | 1 +
2 files changed, 12 insertions(+)
diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index a5d7c6a655..2e32afd456 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -1077,3 +1077,14 @@ Bridge:
## resources\_cpu\_isolated
Add an `Isolated` property on CPU threads to indicate if the thread is
physically `Online` but is configured not to accept tasks.
+
+## usedby\_consistency
+This extension indicates that UsedBy should now be consistent with
+suitable ?project= and ?target= when appropriate.
+
+The 5 entities that have UsedBy are:
+ - Profiles
+ - Projects
+ - Networks
+ - Storage pools
+ - Storage volumes
diff --git a/shared/version/api.go b/shared/version/api.go
index f5b80fe004..340c4389e6 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -214,6 +214,7 @@ var APIExtensions = []string{
"container_nic_routed_limits",
"instance_nic_bridged_vlan",
"network_state_bond_bridge",
+ "usedby_consistency",
}
// APIExtensionsCount returns the number of available API extensions.
More information about the lxc-devel
mailing list