The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6894
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) ===
From 8d34e3adcbbbcc507f3b93330b9edc5145438d7a Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 11:37:38 +0000 Subject: [PATCH 01/38] lxd/db: un-export StorageVolumeNodeGet Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 2 +- lxd/db/storage_volumes.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 3dcc8e6a16..3ccd6ade3e 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -828,7 +828,7 @@ func (c *Cluster) StoragePoolVolumeGetType(project string, volumeName string, vo return -1, nil, err } - volumeNode, err := c.StorageVolumeNodeGet(volumeID) + volumeNode, err := c.storageVolumeNodeGet(volumeID) if err != nil { return -1, nil, err } diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index b377d7a630..4ef0e08c1b 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -85,8 +85,8 @@ SELECT nodes.id, nodes.address return addresses, nil } -// StorageVolumeNodeGet returns the name of the node a storage volume is on. -func (c *Cluster) StorageVolumeNodeGet(volumeID int64) (string, error) { +// Return the name of the node a storage volume is on. +func (c *Cluster) storageVolumeNodeGet(volumeID int64) (string, error) { name := "" query := ` SELECT nodes.name FROM storage_volumes From c0958a973b8c3578ca435da093f04563a61205a9 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 12:15:35 +0000 Subject: [PATCH 02/38] lxd/db: un-export StoragePoolVolumesGetType Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 3ccd6ade3e..60f8db160e 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -730,7 +730,7 @@ func (c *Cluster) storagePoolVolumesGet(project string, poolID, nodeID int64, vo // pool. result := []*api.StorageVolume{} for _, volumeType := range volumeTypes { - volumeNames, err := c.StoragePoolVolumesGetType(project, volumeType, poolID, nodeID) + volumeNames, err := c.storagePoolVolumesGetType(project, volumeType, poolID, nodeID) if err != nil && err != sql.ErrNoRows { return nil, errors.Wrap(err, "failed to fetch volume types") } @@ -750,9 +750,9 @@ func (c *Cluster) storagePoolVolumesGet(project string, poolID, nodeID int64, vo return result, nil } -// StoragePoolVolumesGetType get all storage volumes attached to a given -// storage pool of a given volume type, on the given node. -func (c *Cluster) StoragePoolVolumesGetType(project string, volumeType int, poolID, nodeID int64) ([]string, error) { +// Get all storage volumes attached to a given storage pool of a given volume +// type, on the given node. +func (c *Cluster) storagePoolVolumesGetType(project string, volumeType int, poolID, nodeID int64) ([]string, error) { var poolName string query := ` SELECT storage_volumes.name @@ -811,7 +811,7 @@ func (c *Cluster) StoragePoolVolumeSnapshotsGetType(volumeName string, volumeTyp // StoragePoolNodeVolumesGetType returns all storage volumes attached to a // given storage pool of a given volume type, on the current node. func (c *Cluster) StoragePoolNodeVolumesGetType(volumeType int, poolID int64) ([]string, error) { - return c.StoragePoolVolumesGetType("default", volumeType, poolID, c.nodeID) + return c.storagePoolVolumesGetType("default", volumeType, poolID, c.nodeID) } // StoragePoolVolumeGetType returns a single storage volume attached to a From 0958ad0c1d304b651e41f1eae0dd6e83210017dc Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 12:56:21 +0000 Subject: [PATCH 03/38] lxd/db: un-export StoragePoolVolumeGetTypeID Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 60f8db160e..2dac1f632c 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -823,7 +823,7 @@ func (c *Cluster) StoragePoolVolumeGetType(project string, volumeName string, vo project = "default" } - volumeID, err := c.StoragePoolVolumeGetTypeID(project, volumeName, volumeType, poolID, nodeID) + volumeID, err := c.storagePoolVolumeGetTypeID(project, volumeName, volumeType, poolID, nodeID) if err != nil { return -1, nil, err } @@ -1018,9 +1018,9 @@ INSERT INTO storage_volumes (storage_pool_id, node_id, type, snapshot, name, des return thisVolumeID, err } -// StoragePoolVolumeGetTypeID returns the ID of a storage volume on a given -// storage pool of a given storage volume type, on the given node. -func (c *Cluster) StoragePoolVolumeGetTypeID(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, error) { +// Return the ID of a storage volume on a given storage pool of a given storage +// volume type, on the given node. +func (c *Cluster) storagePoolVolumeGetTypeID(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, error) { volumeID := int64(-1) query := `SELECT storage_volumes.id FROM storage_volumes @@ -1045,13 +1045,13 @@ AND storage_volumes.name=? AND storage_volumes.type=?` // StoragePoolNodeVolumeGetTypeID get the ID of a storage volume on a given // storage pool of a given storage volume type, on the current node. func (c *Cluster) StoragePoolNodeVolumeGetTypeID(volumeName string, volumeType int, poolID int64) (int64, error) { - return c.StoragePoolVolumeGetTypeID("default", volumeName, volumeType, poolID, c.nodeID) + return c.storagePoolVolumeGetTypeID("default", volumeName, volumeType, poolID, c.nodeID) } // StoragePoolNodeVolumeGetTypeIDByProject gets the ID of a storage volume on a given storage pool // of a given storage volume type and project, on the current node. func (c *Cluster) StoragePoolNodeVolumeGetTypeIDByProject(project, volumeName string, volumeType int, poolID int64) (int64, error) { - return c.StoragePoolVolumeGetTypeID(project, volumeName, volumeType, poolID, c.nodeID) + return c.storagePoolVolumeGetTypeID(project, volumeName, volumeType, poolID, c.nodeID) } // XXX: this was extracted from lxd/storage_volume_utils.go, we find a way to From d3f2a5d718363dfdf0ac72e8a6da6accea887e70 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 13:03:33 +0000 Subject: [PATCH 04/38] lxd/db: un-export StoragePoolVolumeGetType Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 10 +++++----- lxd/db/storage_pools_export_test.go | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 lxd/db/storage_pools_export_test.go diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 2dac1f632c..7a7ccc7afd 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -735,7 +735,7 @@ func (c *Cluster) storagePoolVolumesGet(project string, poolID, nodeID int64, vo return nil, errors.Wrap(err, "failed to fetch volume types") } for _, volumeName := range volumeNames { - _, volume, err := c.StoragePoolVolumeGetType(project, volumeName, volumeType, poolID, nodeID) + _, volume, err := c.storagePoolVolumeGetType(project, volumeName, volumeType, poolID, nodeID) if err != nil { return nil, errors.Wrap(err, "failed to fetch volume type") } @@ -814,9 +814,9 @@ func (c *Cluster) StoragePoolNodeVolumesGetType(volumeType int, poolID int64) ([ return c.storagePoolVolumesGetType("default", volumeType, poolID, c.nodeID) } -// StoragePoolVolumeGetType returns a single storage volume attached to a -// given storage pool of a given type, on the node with the given ID. -func (c *Cluster) StoragePoolVolumeGetType(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, *api.StorageVolume, error) { +// Return a single storage volume attached to a given storage pool of a given +// type, on the node with the given ID. +func (c *Cluster) storagePoolVolumeGetType(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, *api.StorageVolume, error) { // Custom volumes are "global", i.e. they are associated with the // default project. if volumeType == StoragePoolVolumeTypeCustom { @@ -868,7 +868,7 @@ func (c *Cluster) StoragePoolNodeVolumeGetType(volumeName string, volumeType int // StoragePoolNodeVolumeGetTypeByProject gets a single storage volume attached to a // given storage pool of a given type, on the current node in the given project. func (c *Cluster) StoragePoolNodeVolumeGetTypeByProject(project, volumeName string, volumeType int, poolID int64) (int64, *api.StorageVolume, error) { - return c.StoragePoolVolumeGetType(project, volumeName, volumeType, poolID, c.nodeID) + return c.storagePoolVolumeGetType(project, volumeName, volumeType, poolID, c.nodeID) } // StoragePoolVolumeUpdateByProject updates the storage volume attached to a given storage pool. diff --git a/lxd/db/storage_pools_export_test.go b/lxd/db/storage_pools_export_test.go new file mode 100644 index 0000000000..6a83c10bc3 --- /dev/null +++ b/lxd/db/storage_pools_export_test.go @@ -0,0 +1,9 @@ +// +build linux,cgo,!agent + +package db + +import "github.com/lxc/lxd/shared/api" + +func (c *Cluster) StoragePoolVolumeGetType(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, *api.StorageVolume, error) { + return c.storagePoolVolumeGetType(project, volumeName, volumeType, poolID, nodeID) +} From 86cc9457d84726851b6ff0ed9bf9a62f4b660d6f Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 13:04:54 +0000 Subject: [PATCH 05/38] lxd/db: un-export StorageVolumeConfigGet Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 2 +- lxd/db/storage_volumes.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 7a7ccc7afd..ad48a44dee 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -833,7 +833,7 @@ func (c *Cluster) storagePoolVolumeGetType(project string, volumeName string, vo return -1, nil, err } - volumeConfig, err := c.StorageVolumeConfigGet(volumeID) + volumeConfig, err := c.storageVolumeConfigGet(volumeID) if err != nil { return -1, nil, err } diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 4ef0e08c1b..342bea8870 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -108,8 +108,8 @@ SELECT nodes.name FROM storage_volumes return name, nil } -// StorageVolumeConfigGet gets the config of a storage volume. -func (c *Cluster) StorageVolumeConfigGet(volumeID int64) (map[string]string, error) { +// Get the config of a storage volume. +func (c *Cluster) storageVolumeConfigGet(volumeID int64) (map[string]string, error) { var key, value string query := "SELECT key, value FROM storage_volumes_config WHERE storage_volume_id=?" inargs := []interface{}{volumeID} From a1f9334fd881805f84bafca3d89fc389e53a2fe8 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 13:05:54 +0000 Subject: [PATCH 06/38] lxd/db: un-export StoragePoolVolumeTypeToName Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index ad48a44dee..ac31cbb950 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -843,7 +843,7 @@ func (c *Cluster) storagePoolVolumeGetType(project string, volumeName string, vo return -1, nil, err } - volumeTypeName, err := StoragePoolVolumeTypeToName(volumeType) + volumeTypeName, err := storagePoolVolumeTypeToName(volumeType) if err != nil { return -1, nil, err } @@ -1084,9 +1084,8 @@ var StoragePoolNodeConfigKeys = []string{ "lvm.vg_name", } -// StoragePoolVolumeTypeToName converts a volume integer type code to its -// human-readable name. -func StoragePoolVolumeTypeToName(volumeType int) (string, error) { +// Convert a volume integer type code to its human-readable name. +func storagePoolVolumeTypeToName(volumeType int) (string, error) { switch volumeType { case StoragePoolVolumeTypeContainer: return StoragePoolVolumeTypeNameContainer, nil From 2a043c44a07d8c5b950b790d16e5c91d44183a35 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 13:53:05 +0000 Subject: [PATCH 07/38] lxd/db: un-export StorageVolumeDescriptionUpdate Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 2 +- lxd/db/storage_volumes.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index ac31cbb950..138141df3e 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -890,7 +890,7 @@ func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, v return err } - return StorageVolumeDescriptionUpdate(tx.tx, volumeID, volumeDescription) + return storageVolumeDescriptionUpdate(tx.tx, volumeID, volumeDescription) }) if err != nil { return err diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 342bea8870..3ae17e0d4a 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -251,8 +251,8 @@ func (c *Cluster) StorageVolumeIsAvailable(pool, volume string) (bool, error) { return isAvailable, nil } -// StorageVolumeDescriptionUpdate updates the description of a storage volume. -func StorageVolumeDescriptionUpdate(tx *sql.Tx, volumeID int64, description string) error { +// Updates the description of a storage volume. +func storageVolumeDescriptionUpdate(tx *sql.Tx, volumeID int64, description string) error { _, err := tx.Exec("UPDATE storage_volumes SET description=? WHERE id=?", description, volumeID) return err } From b6a033d79c6a95c38f59fda91963c4cf9e5f44c2 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:28:55 +0000 Subject: [PATCH 08/38] lxd/db: un-export StorageVolumeConfigAdd Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 4 ++-- lxd/db/storage_volumes.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 138141df3e..ff4e5fa2ea 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -885,7 +885,7 @@ func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, v return err } - err = StorageVolumeConfigAdd(tx.tx, volumeID, volumeConfig) + err = storageVolumeConfigAdd(tx.tx, volumeID, volumeConfig) if err != nil { return err } @@ -1003,7 +1003,7 @@ INSERT INTO storage_volumes (storage_pool_id, node_id, type, snapshot, name, des thisVolumeID = volumeID } - err = StorageVolumeConfigAdd(tx.tx, volumeID, volumeConfig) + err = storageVolumeConfigAdd(tx.tx, volumeID, volumeConfig) if err != nil { tx.tx.Rollback() return err diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 3ae17e0d4a..f009023ed0 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -257,8 +257,8 @@ func storageVolumeDescriptionUpdate(tx *sql.Tx, volumeID int64, description stri return err } -// StorageVolumeConfigAdd adds a new storage volume config into database. -func StorageVolumeConfigAdd(tx *sql.Tx, volumeID int64, volumeConfig map[string]string) error { +// Add a new storage volume config into database. +func storageVolumeConfigAdd(tx *sql.Tx, volumeID int64, volumeConfig map[string]string) error { str := "INSERT INTO storage_volumes_config (storage_volume_id, key, value) VALUES(?, ?, ?)" stmt, err := tx.Prepare(str) defer stmt.Close() From 396135330b508ff2d947f27d891bdeb21fb1a7cb Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:33:42 +0000 Subject: [PATCH 09/38] lxd/db: un-export StorageVolumeConfigClear Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 2 +- lxd/db/storage_volumes.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index ff4e5fa2ea..5a30af09b0 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -880,7 +880,7 @@ func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, v err = c.Transaction(func(tx *ClusterTx) error { err = storagePoolVolumeReplicateIfCeph(tx.tx, volumeID, project, volumeName, volumeType, poolID, func(volumeID int64) error { - err = StorageVolumeConfigClear(tx.tx, volumeID) + err = storageVolumeConfigClear(tx.tx, volumeID) if err != nil { return err } diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index f009023ed0..df77a1835f 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -280,8 +280,8 @@ func storageVolumeConfigAdd(tx *sql.Tx, volumeID int64, volumeConfig map[string] return nil } -// StorageVolumeConfigClear deletes storage volume config. -func StorageVolumeConfigClear(tx *sql.Tx, volumeID int64) error { +// Delete storage volume config. +func storageVolumeConfigClear(tx *sql.Tx, volumeID int64) error { _, err := tx.Exec("DELETE FROM storage_volumes_config WHERE storage_volume_id=?", volumeID) if err != nil { return err From 47b481e79b4c93fa836adbb96e5dbc6003a207a6 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 09:44:03 +0000 Subject: [PATCH 10/38] lxd/db/cluster: add new storage volume snapshots table Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/cluster/schema.go | 19 ++++++++++++++++++- lxd/db/cluster/update.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go index 02f2057d10..677f23a013 100644 --- a/lxd/db/cluster/schema.go +++ b/lxd/db/cluster/schema.go @@ -494,6 +494,23 @@ CREATE TABLE storage_volumes_config ( UNIQUE (storage_volume_id, key), FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE ); +CREATE TABLE storage_volumes_snapshots ( + id INTEGER NOT NULL, + storage_volume_id INTEGER NOT NULL, + name TEXT NOT NULL, + description TEXT, + UNIQUE (id), + UNIQUE (storage_volume_id, name), + FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE +); +CREATE TABLE storage_volumes_snapshots_config ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + storage_volume_snapshot_id INTEGER NOT NULL, + key TEXT NOT NULL, + value TEXT, + FOREIGN KEY (storage_volume_snapshot_id) REFERENCES storage_volumes_snapshots (id) ON DELETE CASCADE, + UNIQUE (storage_volume_snapshot_id, key) +); -INSERT INTO schema (version, updated_at) VALUES (24, strftime("%s")) +INSERT INTO schema (version, updated_at) VALUES (25, strftime("%s")) ` diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go index 7b9763a238..ec584f5c52 100644 --- a/lxd/db/cluster/update.go +++ b/lxd/db/cluster/update.go @@ -60,6 +60,35 @@ var updates = map[int]schema.Update{ 22: updateFromV21, 23: updateFromV22, 24: updateFromV23, + 25: updateFromV24, +} + +// Create new storage snapshot tables and migrate data to them. +func updateFromV24(tx *sql.Tx) error { + stmts := ` +CREATE TABLE storage_volumes_snapshots ( + id INTEGER NOT NULL, + storage_volume_id INTEGER NOT NULL, + name TEXT NOT NULL, + description TEXT, + UNIQUE (id), + UNIQUE (storage_volume_id, name), + FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE +); +CREATE TABLE storage_volumes_snapshots_config ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + storage_volume_snapshot_id INTEGER NOT NULL, + key TEXT NOT NULL, + value TEXT, + FOREIGN KEY (storage_volume_snapshot_id) REFERENCES storage_volumes_snapshots (id) ON DELETE CASCADE, + UNIQUE (storage_volume_snapshot_id, key) +); +` + _, err := tx.Exec(stmts) + if err != nil { + return errors.Wrap(err, "Failed to create storage snapshots tables") + } + return nil } // The lvm.vg_name config key is required for LVM to function. From 6d6cf0d4099ddf0297efc1148ad4553b9e61f7fa Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 10:05:02 +0000 Subject: [PATCH 11/38] lxd/db/cluster: drop snapshot column from storage_volumes table This also migrates the data of all non-snapshot storage volumes. Data migration for snapshot storage volumes will come in a follow-up commit. Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/cluster/schema.go | 1 - lxd/db/cluster/update.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go index 677f23a013..df7ab1e364 100644 --- a/lxd/db/cluster/schema.go +++ b/lxd/db/cluster/schema.go @@ -479,7 +479,6 @@ CREATE TABLE "storage_volumes" ( node_id INTEGER NOT NULL, type INTEGER NOT NULL, description TEXT, - snapshot INTEGER NOT NULL DEFAULT 0, project_id INTEGER NOT NULL, UNIQUE (storage_pool_id, node_id, project_id, name, type), FOREIGN KEY (storage_pool_id) REFERENCES storage_pools (id) ON DELETE CASCADE, diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go index ec584f5c52..3e6ca346a2 100644 --- a/lxd/db/cluster/update.go +++ b/lxd/db/cluster/update.go @@ -66,6 +66,37 @@ var updates = map[int]schema.Update{ // Create new storage snapshot tables and migrate data to them. func updateFromV24(tx *sql.Tx) error { stmts := ` +ALTER TABLE storage_volumes RENAME TO old_storage_volumes; +CREATE TABLE "storage_volumes" ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + name TEXT NOT NULL, + storage_pool_id INTEGER NOT NULL, + node_id INTEGER NOT NULL, + type INTEGER NOT NULL, + description TEXT, + project_id INTEGER NOT NULL, + UNIQUE (storage_pool_id, node_id, project_id, name, type), + FOREIGN KEY (storage_pool_id) REFERENCES storage_pools (id) ON DELETE CASCADE, + FOREIGN KEY (node_id) REFERENCES nodes (id) ON DELETE CASCADE, + FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE +); +ALTER TABLE storage_volumes_config RENAME TO old_storage_volumes_config; +CREATE TABLE storage_volumes_config ( + id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + storage_volume_id INTEGER NOT NULL, + key TEXT NOT NULL, + value TEXT, + UNIQUE (storage_volume_id, key), + FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE +); +INSERT INTO storage_volumes(id, name, storage_pool_id, node_id, type, description, project_id) + SELECT id, name, storage_pool_id, node_id, type, description, project_id FROM old_storage_volumes + WHERE snapshot=0; +INSERT INTO storage_volumes_config + SELECT * FROM old_storage_volumes_config + WHERE storage_volume_id IN (SELECT id FROM storage_volumes); +DROP TABLE old_storage_volumes; +DROP TABLE old_storage_volumes_config; CREATE TABLE storage_volumes_snapshots ( id INTEGER NOT NULL, storage_volume_id INTEGER NOT NULL, From adc57351c41956d229b98dee717718e3be64125f Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 12:30:00 +0000 Subject: [PATCH 12/38] lxd/db/cluster: add storage_volumes_all view This lists both regular volumes and shapshots, and is virtually equivalent to the old storage_volumes table. Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/cluster/schema.go | 27 +++++++++++++++++++++++++++ lxd/db/cluster/update.go | 25 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go index df7ab1e364..903512c6a2 100644 --- a/lxd/db/cluster/schema.go +++ b/lxd/db/cluster/schema.go @@ -485,6 +485,33 @@ CREATE TABLE "storage_volumes" ( FOREIGN KEY (node_id) REFERENCES nodes (id) ON DELETE CASCADE, FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE ); +CREATE VIEW storage_volumes_all ( + id, + name, + storage_pool_id, + node_id, + type, + description, + project_id) AS + SELECT id, + name, + storage_pool_id, + node_id, + type, + description, + project_id + FROM storage_volumes UNION + SELECT storage_volumes_snapshots.id, + printf('%s/%s', + storage_volumes.name, + storage_volumes_snapshots.name), + storage_volumes.storage_pool_id, + storage_volumes.node_id, + storage_volumes.type, + storage_volumes_snapshots.description, + storage_volumes.project_id + FROM storage_volumes + JOIN storage_volumes_snapshots ON storage_volumes.id = storage_volumes_snapshots.storage_volume_id; CREATE TABLE storage_volumes_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, storage_volume_id INTEGER NOT NULL, diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go index 3e6ca346a2..ab02b7cbc5 100644 --- a/lxd/db/cluster/update.go +++ b/lxd/db/cluster/update.go @@ -114,6 +114,31 @@ CREATE TABLE storage_volumes_snapshots_config ( FOREIGN KEY (storage_volume_snapshot_id) REFERENCES storage_volumes_snapshots (id) ON DELETE CASCADE, UNIQUE (storage_volume_snapshot_id, key) ); +CREATE VIEW storage_volumes_all ( + id, + name, + storage_pool_id, + node_id, + type, + description, + project_id) AS + SELECT id, + name, + storage_pool_id, + node_id, + type, + description, + project_id + FROM storage_volumes UNION + SELECT storage_volumes_snapshots.id, + printf('%s/%s', storage_volumes.name, storage_volumes_snapshots.name), + storage_volumes.storage_pool_id, + storage_volumes.node_id, + storage_volumes.type, + storage_volumes_snapshots.description, + storage_volumes.project_id + FROM storage_volumes + JOIN storage_volumes_snapshots ON storage_volumes.id = storage_volumes_snapshots.storage_volume_id; ` _, err := tx.Exec(stmts) if err != nil { From 8773c85517757edc32309d6cdf763efe7d139bba Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:02:15 +0000 Subject: [PATCH 13/38] lxd/db/schema: include triggers when generating SQL for fresh schemas Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/schema/query.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/db/schema/query.go b/lxd/db/schema/query.go index 6672cdd140..f0e1eed8f0 100644 --- a/lxd/db/schema/query.go +++ b/lxd/db/schema/query.go @@ -50,7 +50,7 @@ SELECT version FROM schema ORDER BY version func selectTablesSQL(tx *sql.Tx) ([]string, error) { statement := ` SELECT sql FROM sqlite_master WHERE - type IN ('table', 'index', 'view') AND + type IN ('table', 'index', 'view', 'trigger') AND name != 'schema' AND name NOT LIKE 'sqlite_%' ORDER BY name From c2868fcd534be1f54db4a29e71f9bfc56be63208 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:03:47 +0000 Subject: [PATCH 14/38] lxd/db/cluster: add triggers to check that volume IDs don't overlap Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/cluster/schema.go | 14 ++++++++++++++ lxd/db/cluster/update.go | 12 ++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lxd/db/cluster/schema.go b/lxd/db/cluster/schema.go index 903512c6a2..f0f5563101 100644 --- a/lxd/db/cluster/schema.go +++ b/lxd/db/cluster/schema.go @@ -512,6 +512,13 @@ CREATE VIEW storage_volumes_all ( storage_volumes.project_id FROM storage_volumes JOIN storage_volumes_snapshots ON storage_volumes.id = storage_volumes_snapshots.storage_volume_id; +CREATE TRIGGER storage_volumes_check_id + BEFORE INSERT ON storage_volumes + WHEN NEW.id IN (SELECT id FROM storage_volumes_snapshots) + BEGIN + SELECT RAISE(FAIL, + "invalid ID"); + END; CREATE TABLE storage_volumes_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, storage_volume_id INTEGER NOT NULL, @@ -529,6 +536,13 @@ CREATE TABLE storage_volumes_snapshots ( UNIQUE (storage_volume_id, name), FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE ); +CREATE TRIGGER storage_volumes_snapshots_check_id + BEFORE INSERT ON storage_volumes_snapshots + WHEN NEW.id IN (SELECT id FROM storage_volumes) + BEGIN + SELECT RAISE(FAIL, + "invalid ID"); + END; CREATE TABLE storage_volumes_snapshots_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, storage_volume_snapshot_id INTEGER NOT NULL, diff --git a/lxd/db/cluster/update.go b/lxd/db/cluster/update.go index ab02b7cbc5..5febf383ef 100644 --- a/lxd/db/cluster/update.go +++ b/lxd/db/cluster/update.go @@ -106,6 +106,18 @@ CREATE TABLE storage_volumes_snapshots ( UNIQUE (storage_volume_id, name), FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE ); +CREATE TRIGGER storage_volumes_check_id + BEFORE INSERT ON storage_volumes + WHEN NEW.id IN (SELECT id FROM storage_volumes_snapshots) + BEGIN + SELECT RAISE(FAIL, "invalid ID"); + END; +CREATE TRIGGER storage_volumes_snapshots_check_id + BEFORE INSERT ON storage_volumes_snapshots + WHEN NEW.id IN (SELECT id FROM storage_volumes) + BEGIN + SELECT RAISE(FAIL, "invalid ID"); + END; CREATE TABLE storage_volumes_snapshots_config ( id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, storage_volume_snapshot_id INTEGER NOT NULL, From 22a6c9ae4312b5f4a2d316fddc767f16eab24b37 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 10:36:42 +0000 Subject: [PATCH 15/38] lxd/db: change StoragePoolVolumeSnapshotsGetType to query the snapshots table Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 5a30af09b0..07cfc90475 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -781,15 +781,21 @@ SELECT storage_volumes.name // Returns snapshots slice ordered by when they were created, oldest first. func (c *Cluster) StoragePoolVolumeSnapshotsGetType(volumeName string, volumeType int, poolID int64) ([]StorageVolumeArgs, error) { result := []StorageVolumeArgs{} - regexp := volumeName + shared.SnapshotDelimiter - length := len(regexp) // ORDER BY id is important here as the users of this function can expect that the results // will be returned in the order that the snapshots were created. This is specifically used // during migration to ensure that the storage engines can re-create snapshots using the // correct deltas. - query := "SELECT name, description FROM storage_volumes WHERE storage_pool_id=? AND node_id=? AND type=? AND snapshot=? AND SUBSTR(name,1,?)=? ORDER BY id" - inargs := []interface{}{poolID, c.nodeID, volumeType, true, length, regexp} + query := ` +SELECT storage_volumes_snapshots.name, storage_volumes_snapshots.description FROM storage_volumes_snapshots + JOIN storage_volumes ON storage_volumes_snapshots.storage_volume_id = storage_volumes.id + WHERE storage_volumes.storage_pool_id=? + AND storage_volumes.node_id=? + AND storage_volumes.type=? + AND storage_volumes.name=? + ORDER BY id +` + inargs := []interface{}{poolID, c.nodeID, volumeType, volumeName} typeGuide := StorageVolumeArgs{} // StorageVolume struct used to guide the types expected. outfmt := []interface{}{typeGuide.Name, typeGuide.Description} dbResults, err := queryScan(c.db, query, inargs, outfmt) @@ -799,7 +805,7 @@ func (c *Cluster) StoragePoolVolumeSnapshotsGetType(volumeName string, volumeTyp for _, r := range dbResults { row := StorageVolumeArgs{ - Name: r[0].(string), + Name: volumeName + shared.SnapshotDelimiter + r[0].(string), Description: r[1].(string), } result = append(result, row) From 5d9bb60a59506288add74dc496e773eb082897e6 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 13:51:47 +0000 Subject: [PATCH 16/38] lxd/db: change StorageVolumeNextSnapshot to query the snapshot table Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_volumes.go | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index df77a1835f..80b85db918 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -9,7 +9,6 @@ import ( "time" "github.com/lxc/lxd/lxd/db/query" - "github.com/lxc/lxd/shared" "github.com/pkg/errors" ) @@ -150,17 +149,23 @@ func (c *Cluster) StorageVolumeDescriptionGet(volumeID int64) (string, error) { return description.String, nil } -// StorageVolumeNextSnapshot returns the index the next snapshot of the storage +// StorageVolumeNextSnapshot returns the index of the next snapshot of the storage // volume with the given name should have. // // Note, the code below doesn't deal with snapshots of snapshots. // To do that, we'll need to weed out based on # slashes in names func (c *Cluster) StorageVolumeNextSnapshot(name string, typ int) int { - base := name + shared.SnapshotDelimiter + "snap" + base := "snap" length := len(base) - q := fmt.Sprintf("SELECT name FROM storage_volumes WHERE type=? AND snapshot=? AND SUBSTR(name,1,?)=?") + q := fmt.Sprintf(` +SELECT storage_volumes_snapshots.name FROM storage_volumes_snapshots + JOIN storage_volumes ON storage_volumes_snapshots.storage_volume_id=storage_volumes.id + WHERE storage_volumes.type=? + AND storage_volumes.name=? + AND SUBSTR(storage_volumes_snapshots.name,1,?)=? +`) var numstr string - inargs := []interface{}{typ, true, length, base} + inargs := []interface{}{typ, name, length, base} outfmt := []interface{}{numstr} results, err := queryScan(c.db, q, inargs, outfmt) if err != nil { @@ -169,11 +174,7 @@ func (c *Cluster) StorageVolumeNextSnapshot(name string, typ int) int { max := 0 for _, r := range results { - numstr = r[0].(string) - if len(numstr) <= length { - continue - } - substr := numstr[length:] + substr := r[0].(string) var num int count, err := fmt.Sscanf(substr, "%d", &num) if err != nil || count != 1 { From cd96100d804e3c68b6114bcd7db5727f7ac3e11c Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Fri, 14 Feb 2020 12:34:30 +0000 Subject: [PATCH 17/38] lxd/db: update StorageVolumeNodeAddresses to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_volumes.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 80b85db918..6662050c82 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -35,6 +35,8 @@ type StorageVolumeArgs struct { // StorageVolumeNodeAddresses returns the addresses of all nodes on which the // volume with the given name if defined. // +// The volume name can be either a regular name or a volume snapshot name. +// // The empty string is used in place of the address of the current node. func (c *ClusterTx) StorageVolumeNodeAddresses(poolID int64, project, name string, typ int) ([]string, error) { nodes := []struct { @@ -52,9 +54,12 @@ func (c *ClusterTx) StorageVolumeNodeAddresses(poolID int64, project, name strin sql := ` SELECT nodes.id, nodes.address FROM nodes - JOIN storage_volumes ON storage_volumes.node_id=nodes.id - JOIN projects ON projects.id = storage_volumes.project_id - WHERE storage_volumes.storage_pool_id=? AND projects.name=? AND storage_volumes.name=? AND storage_volumes.type=? + JOIN storage_volumes_all ON storage_volumes_all.node_id=nodes.id + JOIN projects ON projects.id = storage_volumes_all.project_id + WHERE storage_volumes_all.storage_pool_id=? + AND projects.name=? + AND storage_volumes_all.name=? + AND storage_volumes_all.type=? ` stmt, err := c.tx.Prepare(sql) if err != nil { From 25c9ebaba9067eb4cc165629c22f1f85496591ac Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 12:31:29 +0000 Subject: [PATCH 18/38] lxd/db: update storagePoolVolumeGetTypeID to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 07cfc90475..4de793afe2 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -1028,12 +1028,12 @@ INSERT INTO storage_volumes (storage_pool_id, node_id, type, snapshot, name, des // volume type, on the given node. func (c *Cluster) storagePoolVolumeGetTypeID(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, error) { volumeID := int64(-1) - query := `SELECT storage_volumes.id -FROM storage_volumes -JOIN storage_pools ON storage_volumes.storage_pool_id = storage_pools.id -JOIN projects ON storage_volumes.project_id = projects.id -WHERE projects.name=? AND storage_volumes.storage_pool_id=? AND storage_volumes.node_id=? -AND storage_volumes.name=? AND storage_volumes.type=?` + query := `SELECT storage_volumes_all.id +FROM storage_volumes_all +JOIN storage_pools ON storage_volumes_all.storage_pool_id = storage_pools.id +JOIN projects ON storage_volumes_all.project_id = projects.id +WHERE projects.name=? AND storage_volumes_all.storage_pool_id=? AND storage_volumes_all.node_id=? +AND storage_volumes_all.name=? AND storage_volumes_all.type=?` inargs := []interface{}{project, poolID, nodeID, volumeName, volumeType} outargs := []interface{}{&volumeID} From 21130a84e99b2d741a5b3398841dbdb68cbde41c Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 12:36:53 +0000 Subject: [PATCH 19/38] lxd/db: update storageVolumeNodeGet to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_volumes.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 6662050c82..d7e39c88b6 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -93,9 +93,9 @@ SELECT nodes.id, nodes.address func (c *Cluster) storageVolumeNodeGet(volumeID int64) (string, error) { name := "" query := ` -SELECT nodes.name FROM storage_volumes - JOIN nodes ON nodes.id=storage_volumes.node_id - WHERE storage_volumes.id=? +SELECT nodes.name FROM storage_volumes_all + JOIN nodes ON nodes.id=storage_volumes_all.node_id + WHERE storage_volumes_all.id=? ` inargs := []interface{}{volumeID} outargs := []interface{}{&name} From b60deea15973b7ba2e24e4415487002237dbc165 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 12:37:01 +0000 Subject: [PATCH 20/38] lxd/db: update StorageVolumeDescriptionGet to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_volumes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index d7e39c88b6..6779dfcbc9 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -139,7 +139,7 @@ func (c *Cluster) storageVolumeConfigGet(volumeID int64) (map[string]string, err // StorageVolumeDescriptionGet gets the description of a storage volume. func (c *Cluster) StorageVolumeDescriptionGet(volumeID int64) (string, error) { description := sql.NullString{} - query := "SELECT description FROM storage_volumes WHERE id=?" + query := "SELECT description FROM storage_volumes_all WHERE id=?" inargs := []interface{}{volumeID} outargs := []interface{}{&description} From 5c5bff5959349f26813fc276b265cc138e402bb0 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:40:02 +0000 Subject: [PATCH 21/38] lxd/db: update storageVolumeIDsGet to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_volumes.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 6779dfcbc9..2a04d01190 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -300,10 +300,13 @@ func storageVolumeConfigClear(tx *sql.Tx, volumeID int64) error { // given pool, regardless of their node_id column. func storageVolumeIDsGet(tx *sql.Tx, project, volumeName string, volumeType int, poolID int64) ([]int64, error) { ids, err := query.SelectIntegers(tx, ` -SELECT storage_volumes.id - FROM storage_volumes - JOIN projects ON projects.id = storage_volumes.project_id - WHERE projects.name=? AND storage_volumes.name=? AND storage_volumes.type=? AND storage_pool_id=? +SELECT storage_volumes_all.id + FROM storage_volumes_all + JOIN projects ON projects.id = storage_volumes_all.project_id + WHERE projects.name=? + AND storage_volumes_all.name=? + AND storage_volumes_all.type=? + AND storage_volumes_all.storage_pool_id=? `, project, volumeName, volumeType, poolID) if err != nil { return nil, err From 475cde01d9a93526c8552940fb26c12153f74039 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:50:59 +0000 Subject: [PATCH 22/38] lxd/db: update StoragePoolVolumesGetNames to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 4de793afe2..4fae34a6b9 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -669,7 +669,7 @@ func (c *Cluster) StoragePoolDelete(poolName string) (*api.StoragePool, error) { // a given storage pool. func (c *Cluster) StoragePoolVolumesGetNames(poolID int64) ([]string, error) { var volumeName string - query := "SELECT name FROM storage_volumes WHERE storage_pool_id=? AND node_id=?" + query := "SELECT name FROM storage_volumes_all WHERE storage_pool_id=? AND node_id=?" inargs := []interface{}{poolID, c.nodeID} outargs := []interface{}{volumeName} From 69b907b878f0031c4a6d4bb806633e194f4a8f23 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:52:02 +0000 Subject: [PATCH 23/38] lxd/db: update StoragePoolVolumesGet to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 4fae34a6b9..02784cfd3b 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -696,9 +696,9 @@ func (c *Cluster) StoragePoolVolumesGet(project string, poolID int64, volumeType var err error nodeIDs, err = query.SelectIntegers(tx.tx, ` SELECT DISTINCT node_id - FROM storage_volumes - JOIN projects ON projects.id = storage_volumes.project_id - WHERE (projects.name=? OR storage_volumes.type=?) AND storage_pool_id=? + FROM storage_volumes_all + JOIN projects ON projects.id = storage_volumes_all.project_id + WHERE (projects.name=? OR storage_volumes_all.type=?) AND storage_volumes_all.storage_pool_id=? `, project, StoragePoolVolumeTypeCustom, poolID) return err }) From 3ed52bd61a82aacf64397d36ea2466755554b583 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:53:53 +0000 Subject: [PATCH 24/38] lxd/db: update storagePoolVolumesGetType to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 02784cfd3b..ea91896582 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -755,10 +755,13 @@ func (c *Cluster) storagePoolVolumesGet(project string, poolID, nodeID int64, vo func (c *Cluster) storagePoolVolumesGetType(project string, volumeType int, poolID, nodeID int64) ([]string, error) { var poolName string query := ` -SELECT storage_volumes.name - FROM storage_volumes - JOIN projects ON projects.id=storage_volumes.project_id - WHERE (projects.name=? OR storage_volumes.type=?) AND storage_pool_id=? AND node_id=? AND type=? +SELECT storage_volumes_all.name + FROM storage_volumes_all + JOIN projects ON projects.id=storage_volumes_all.project_id + WHERE (projects.name=? OR storage_volumes_all.type=?) + AND storage_volumes_all.storage_pool_id=? + AND storage_volumes_all.node_id=? + AND storage_volumes_all.type=? ` inargs := []interface{}{project, StoragePoolVolumeTypeCustom, poolID, nodeID, volumeType} outargs := []interface{}{poolName} From 992bbdf7fec809f34b987051559e6b400223faf9 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 15:19:06 +0000 Subject: [PATCH 25/38] lxd/db: update InstancePool to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/containers.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lxd/db/containers.go b/lxd/db/containers.go index 7f0864fce2..c8686db828 100644 --- a/lxd/db/containers.go +++ b/lxd/db/containers.go @@ -1096,10 +1096,13 @@ func (c *ClusterTx) InstancePool(project, instanceName string) (string, error) { poolName := "" query := ` SELECT storage_pools.name FROM storage_pools - JOIN storage_volumes ON storage_pools.id=storage_volumes.storage_pool_id - JOIN instances ON instances.name=storage_volumes.name + JOIN storage_volumes_all ON storage_pools.id=storage_volumes_all.storage_pool_id + JOIN instances ON instances.name=storage_volumes_all.name JOIN projects ON projects.id=instances.project_id - WHERE projects.name=? AND storage_volumes.node_id=? AND storage_volumes.name=? AND storage_volumes.type IN(?,?) + WHERE projects.name=? + AND storage_volumes_all.node_id=? + AND storage_volumes_all.name=? + AND storage_volumes_all.type IN(?,?) ` inargs := []interface{}{project, c.nodeID, instanceName, StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeVM} outargs := []interface{}{&poolName} From 14daaee3ca71b3b502af33ec2a8ec6ca47d85084 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 15:20:12 +0000 Subject: [PATCH 26/38] lxd/db: update instancePoolSnapshot to use storage_volumes_all Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/containers.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lxd/db/containers.go b/lxd/db/containers.go index c8686db828..6523d2d407 100644 --- a/lxd/db/containers.go +++ b/lxd/db/containers.go @@ -1123,9 +1123,12 @@ func (c *ClusterTx) instancePoolSnapshot(project, fullName string) (string, erro poolName := "" query := ` SELECT storage_pools.name FROM storage_pools - JOIN storage_volumes ON storage_pools.id=storage_volumes.storage_pool_id - JOIN projects ON projects.id=storage_volumes.project_id - WHERE projects.name=? AND storage_volumes.node_id=? AND storage_volumes.name=? AND storage_volumes.type IN(?,?) + JOIN storage_volumes_all ON storage_pools.id=storage_volumes_all.storage_pool_id + JOIN projects ON projects.id=storage_volumes_all.project_id + WHERE projects.name=? + AND storage_volumes_all.node_id=? + AND storage_volumes_all.name=? + AND storage_volumes_all.type IN(?,?) ` inargs := []interface{}{project, c.nodeID, fullName, StoragePoolVolumeTypeContainer, StoragePoolVolumeTypeVM} outargs := []interface{}{&poolName} From f1d4aacd9b5a864794d30753d02bb2d774fa8cec Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:57:38 +0000 Subject: [PATCH 27/38] lxd/db: make StoragePoolVolumeDelete differentiate between regular volumes and snapshots Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index ea91896582..5c26a28e67 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -918,9 +918,17 @@ func (c *Cluster) StoragePoolVolumeDelete(project, volumeName string, volumeType return err } + isSnapshot := strings.Contains(volumeName, shared.SnapshotDelimiter) + var stmt string + if isSnapshot { + stmt = "DELETE FROM storage_volumes_snapshots WHERE id=?" + } else { + stmt = "DELETE FROM storage_volumes WHERE id=?" + } + err = c.Transaction(func(tx *ClusterTx) error { err := storagePoolVolumeReplicateIfCeph(tx.tx, volumeID, project, volumeName, volumeType, poolID, func(volumeID int64) error { - _, err := tx.tx.Exec("DELETE FROM storage_volumes WHERE id=?", volumeID) + _, err := tx.tx.Exec(stmt, volumeID) return err }) return err From b3169414cec511adabf27599529f91dc1bced004 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:18:38 +0000 Subject: [PATCH 28/38] lxd/db: make storageVolumeConfigGet differentiate between regular volumes and snapshots Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 4 +++- lxd/db/storage_volumes.go | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 5c26a28e67..7f34b578c5 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -832,6 +832,8 @@ func (c *Cluster) storagePoolVolumeGetType(project string, volumeName string, vo project = "default" } + isSnapshot := strings.Contains(volumeName, shared.SnapshotDelimiter) + volumeID, err := c.storagePoolVolumeGetTypeID(project, volumeName, volumeType, poolID, nodeID) if err != nil { return -1, nil, err @@ -842,7 +844,7 @@ func (c *Cluster) storagePoolVolumeGetType(project string, volumeName string, vo return -1, nil, err } - volumeConfig, err := c.storageVolumeConfigGet(volumeID) + volumeConfig, err := c.storageVolumeConfigGet(volumeID, isSnapshot) if err != nil { return -1, nil, err } diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 2a04d01190..e173bfae69 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -113,9 +113,14 @@ SELECT nodes.name FROM storage_volumes_all } // Get the config of a storage volume. -func (c *Cluster) storageVolumeConfigGet(volumeID int64) (map[string]string, error) { +func (c *Cluster) storageVolumeConfigGet(volumeID int64, isSnapshot bool) (map[string]string, error) { var key, value string - query := "SELECT key, value FROM storage_volumes_config WHERE storage_volume_id=?" + var query string + if isSnapshot { + query = "SELECT key, value FROM storage_volumes_snapshots_config WHERE storage_volume_snapshot_id=?" + } else { + query = "SELECT key, value FROM storage_volumes_config WHERE storage_volume_id=?" + } inargs := []interface{}{volumeID} outargs := []interface{}{key, value} From 6e552278f06ec70884a44c3e88d5e835894915e9 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:26:53 +0000 Subject: [PATCH 29/38] lxd/db: make storageVolumeDescriptionUpdate differentiate between regular volumes and snapshots Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 4 +++- lxd/db/storage_volumes.go | 11 +++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 7f34b578c5..54883f0655 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -889,6 +889,8 @@ func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, v return err } + isSnapshot := strings.Contains(volumeName, shared.SnapshotDelimiter) + err = c.Transaction(func(tx *ClusterTx) error { err = storagePoolVolumeReplicateIfCeph(tx.tx, volumeID, project, volumeName, volumeType, poolID, func(volumeID int64) error { err = storageVolumeConfigClear(tx.tx, volumeID) @@ -901,7 +903,7 @@ func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, v return err } - return storageVolumeDescriptionUpdate(tx.tx, volumeID, volumeDescription) + return storageVolumeDescriptionUpdate(tx.tx, volumeID, volumeDescription, isSnapshot) }) if err != nil { return err diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index e173bfae69..8b8565a688 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -263,8 +263,15 @@ func (c *Cluster) StorageVolumeIsAvailable(pool, volume string) (bool, error) { } // Updates the description of a storage volume. -func storageVolumeDescriptionUpdate(tx *sql.Tx, volumeID int64, description string) error { - _, err := tx.Exec("UPDATE storage_volumes SET description=? WHERE id=?", description, volumeID) +func storageVolumeDescriptionUpdate(tx *sql.Tx, volumeID int64, description string, isSnapshot bool) error { + var table string + if isSnapshot { + table = "storage_volumes_snapshots" + } else { + table = "storage_volumes" + } + stmt := fmt.Sprintf("UPDATE %s SET description=? WHERE id=?", table) + _, err := tx.Exec(stmt, description, volumeID) return err } From ad4789df96988c345f51b181116f95f1e636e734 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:32:23 +0000 Subject: [PATCH 30/38] lxd/db: make storageVolumeConfigAdd differentiate between regular volumes and snapshots Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 4 ++-- lxd/db/storage_volumes.go | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 54883f0655..4d0ca4e6b2 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -898,7 +898,7 @@ func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, v return err } - err = storageVolumeConfigAdd(tx.tx, volumeID, volumeConfig) + err = storageVolumeConfigAdd(tx.tx, volumeID, volumeConfig, isSnapshot) if err != nil { return err } @@ -1024,7 +1024,7 @@ INSERT INTO storage_volumes (storage_pool_id, node_id, type, snapshot, name, des thisVolumeID = volumeID } - err = storageVolumeConfigAdd(tx.tx, volumeID, volumeConfig) + err = storageVolumeConfigAdd(tx.tx, volumeID, volumeConfig, snapshot) if err != nil { tx.tx.Rollback() return err diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 8b8565a688..9016a31f37 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -276,8 +276,13 @@ func storageVolumeDescriptionUpdate(tx *sql.Tx, volumeID int64, description stri } // Add a new storage volume config into database. -func storageVolumeConfigAdd(tx *sql.Tx, volumeID int64, volumeConfig map[string]string) error { - str := "INSERT INTO storage_volumes_config (storage_volume_id, key, value) VALUES(?, ?, ?)" +func storageVolumeConfigAdd(tx *sql.Tx, volumeID int64, volumeConfig map[string]string, isSnapshot bool) error { + var str string + if isSnapshot { + str = "INSERT INTO storage_volumes_snapshots_config (storage_volume_snapshot_id, key, value) VALUES(?, ?, ?)" + } else { + str = "INSERT INTO storage_volumes_config (storage_volume_id, key, value) VALUES(?, ?, ?)" + } stmt, err := tx.Prepare(str) defer stmt.Close() if err != nil { From 3c7636ef3716310e532cbaee24b590537963beb9 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:36:38 +0000 Subject: [PATCH 31/38] lxd/db: make storageVolumeConfigClear differentiate between regular volumes and snapshots Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 2 +- lxd/db/storage_volumes.go | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 4d0ca4e6b2..734d0aa22a 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -893,7 +893,7 @@ func (c *Cluster) StoragePoolVolumeUpdateByProject(project, volumeName string, v err = c.Transaction(func(tx *ClusterTx) error { err = storagePoolVolumeReplicateIfCeph(tx.tx, volumeID, project, volumeName, volumeType, poolID, func(volumeID int64) error { - err = storageVolumeConfigClear(tx.tx, volumeID) + err = storageVolumeConfigClear(tx.tx, volumeID, isSnapshot) if err != nil { return err } diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index 9016a31f37..c143827334 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -304,8 +304,14 @@ func storageVolumeConfigAdd(tx *sql.Tx, volumeID int64, volumeConfig map[string] } // Delete storage volume config. -func storageVolumeConfigClear(tx *sql.Tx, volumeID int64) error { - _, err := tx.Exec("DELETE FROM storage_volumes_config WHERE storage_volume_id=?", volumeID) +func storageVolumeConfigClear(tx *sql.Tx, volumeID int64, isSnapshot bool) error { + var stmt string + if isSnapshot { + stmt = "DELETE FROM storage_volumes_snapshots_config WHERE storage_volume_snapshot_id=?" + } else { + stmt = "DELETE FROM storage_volumes_config WHERE storage_volume_id=?" + } + _, err := tx.Exec(stmt, volumeID) if err != nil { return err } From 61675a451eac6076bb816b92637a5e69bad61964 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 15:00:38 +0000 Subject: [PATCH 32/38] lxd/db: make StoragePoolVolumeRename differentiate between regular volumes and snapshots Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index 734d0aa22a..f3c3dff375 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -948,9 +948,19 @@ func (c *Cluster) StoragePoolVolumeRename(project, oldVolumeName string, newVolu return err } + isSnapshot := strings.Contains(oldVolumeName, shared.SnapshotDelimiter) + var stmt string + if isSnapshot { + parts := strings.Split(newVolumeName, shared.SnapshotDelimiter) + newVolumeName = parts[1] + stmt = "UPDATE storage_volumes_snapshots SET name=? WHERE id=?" + } else { + stmt = "UPDATE storage_volumes SET name=? WHERE id=?" + } + err = c.Transaction(func(tx *ClusterTx) error { err := storagePoolVolumeReplicateIfCeph(tx.tx, volumeID, project, oldVolumeName, volumeType, poolID, func(volumeID int64) error { - _, err := tx.tx.Exec("UPDATE storage_volumes SET name=? WHERE id=? AND type=?", newVolumeName, volumeID, volumeType) + _, err := tx.tx.Exec(stmt, newVolumeName, volumeID) return err }) return err From d58515084168f4aee31c728997ee405ef8b491e4 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:42:50 +0000 Subject: [PATCH 33/38] lxd/db: consider snapshots in StorageVolumeMoveToLVMThinPoolNameKey Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_volumes.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lxd/db/storage_volumes.go b/lxd/db/storage_volumes.go index c143827334..314d2fef68 100644 --- a/lxd/db/storage_volumes.go +++ b/lxd/db/storage_volumes.go @@ -366,6 +366,10 @@ func (c *Cluster) StorageVolumeMoveToLVMThinPoolNameKey() error { if err != nil { return err } + err = exec(c.db, "DELETE FROM storage_volumes_snapshots_config WHERE key='lvm.thinpool_name';") + if err != nil { + return err + } return nil } From dfd38d908468fa7fb478d0922bff35a1816357ad Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Tue, 18 Feb 2020 13:25:07 +0000 Subject: [PATCH 34/38] lxd/db: add ClusterTx.storagePoolVolumeGetTypeID() method Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 42 +++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index f3c3dff375..c60a3fefce 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -1052,25 +1052,39 @@ INSERT INTO storage_volumes (storage_pool_id, node_id, type, snapshot, name, des // Return the ID of a storage volume on a given storage pool of a given storage // volume type, on the given node. func (c *Cluster) storagePoolVolumeGetTypeID(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, error) { - volumeID := int64(-1) - query := `SELECT storage_volumes_all.id -FROM storage_volumes_all -JOIN storage_pools ON storage_volumes_all.storage_pool_id = storage_pools.id -JOIN projects ON storage_volumes_all.project_id = projects.id -WHERE projects.name=? AND storage_volumes_all.storage_pool_id=? AND storage_volumes_all.node_id=? -AND storage_volumes_all.name=? AND storage_volumes_all.type=?` - inargs := []interface{}{project, poolID, nodeID, volumeName, volumeType} - outargs := []interface{}{&volumeID} + var id int64 + err := c.Transaction(func(tx *ClusterTx) error { + var err error + id, err = tx.storagePoolVolumeGetTypeID(project, volumeName, volumeType, poolID, nodeID) + return err + }) + if err != nil { + return -1, err + } + return id, nil +} + +func (c *ClusterTx) storagePoolVolumeGetTypeID(project string, volumeName string, volumeType int, poolID, nodeID int64) (int64, error) { + result, err := query.SelectIntegers(c.tx, ` +SELECT storage_volumes_all.id + FROM storage_volumes_all + JOIN storage_pools ON storage_volumes_all.storage_pool_id = storage_pools.id + JOIN projects ON storage_volumes_all.project_id = projects.id + WHERE projects.name=? + AND storage_volumes_all.storage_pool_id=? + AND storage_volumes_all.node_id=? + AND storage_volumes_all.name=? + AND storage_volumes_all.type=?`, project, poolID, nodeID, volumeName, volumeType) - err := dbQueryRowScan(c.db, query, inargs, outargs) if err != nil { - if err == sql.ErrNoRows { - return -1, ErrNoSuchObject - } return -1, err } - return volumeID, nil + if len(result) == 0 { + return -1, ErrNoSuchObject + } + + return int64(result[0]), nil } // StoragePoolNodeVolumeGetTypeID get the ID of a storage volume on a given From 32df5a1c655aa26cd7fe1e700705291ed907abb6 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 15:11:29 +0000 Subject: [PATCH 35/38] lxd/db: make StoragePoolVolumeCreate differentiate between regular volumes and snapshots Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index c60a3fefce..f30350ab55 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -1002,6 +1002,13 @@ func storagePoolVolumeReplicateIfCeph(tx *sql.Tx, volumeID int64, project, volum func (c *Cluster) StoragePoolVolumeCreate(project, volumeName, volumeDescription string, volumeType int, snapshot bool, poolID int64, volumeConfig map[string]string) (int64, error) { var thisVolumeID int64 + var snapshotName string + if snapshot { + parts := strings.Split(volumeName, shared.SnapshotDelimiter) + volumeName = parts[0] + snapshotName = parts[1] + } + err := c.Transaction(func(tx *ClusterTx) error { nodeIDs := []int{int(c.nodeID)} driver, err := storagePoolDriverGet(tx.tx, poolID) @@ -1017,10 +1024,34 @@ func (c *Cluster) StoragePoolVolumeCreate(project, volumeName, volumeDescription } for _, nodeID := range nodeIDs { - result, err := tx.tx.Exec(` -INSERT INTO storage_volumes (storage_pool_id, node_id, type, snapshot, name, description, project_id) VALUES (?, ?, ?, ?, ?, ?, (SELECT id FROM projects WHERE name = ?)) + var result sql.Result + // If we are creating a snapshot, figure out the volume + // ID of the parent. + if snapshot { + parentID, err := tx.storagePoolVolumeGetTypeID( + project, volumeName, volumeType, poolID, int64(nodeID)) + if err != nil { + return errors.Wrap(err, "Find parent volume") + } + _, err = tx.tx.Exec(` +UPDATE sqlite_sequence SET seq = seq + 1 WHERE name = 'storage_volumes' +`) + if err != nil { + return errors.Wrap(err, "Increment storage volumes sequence") + } + result, err = tx.tx.Exec(` +INSERT INTO storage_volumes_snapshots (id, storage_volume_id, name, description) + VALUES ((SELECT seq FROM sqlite_sequence WHERE name = 'storage_volumes' LIMIT 1), ?, ?, ?) `, - poolID, nodeID, volumeType, snapshot, volumeName, volumeDescription, project) + parentID, snapshotName, volumeDescription) + } else { + + result, err = tx.tx.Exec(` +INSERT INTO storage_volumes (storage_pool_id, node_id, type, name, description, project_id) + VALUES (?, ?, ?, ?, ?, (SELECT id FROM projects WHERE name = ?)) +`, + poolID, nodeID, volumeType, volumeName, volumeDescription, project) + } if err != nil { return err } From 05fb1147845c1c5c0aa6ea52f59f11fd48f1ddc5 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 15:17:04 +0000 Subject: [PATCH 36/38] lxd/db: no need to update snapshot names in ContainerNodeMove Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/containers.go | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/lxd/db/containers.go b/lxd/db/containers.go index 6523d2d407..6e855dfda6 100644 --- a/lxd/db/containers.go +++ b/lxd/db/containers.go @@ -467,10 +467,6 @@ func (c *ClusterTx) ContainerNodeMove(project, oldName, newName, newNode string) if err != nil { return errors.Wrap(err, "failed to get container's ID") } - snapshots, err := c.snapshotIDsAndNames(project, oldName) - if err != nil { - return errors.Wrap(err, "failed to get container's snapshots") - } node, err := c.NodeByName(newNode) if err != nil { return errors.Wrap(err, "failed to get new node's info") @@ -493,7 +489,7 @@ func (c *ClusterTx) ContainerNodeMove(project, oldName, newName, newNode string) return nil } - // Update the container's and snapshots' storage volume name (since this is ceph, + // Update the instance's storage volume name (since this is ceph, // there's a clone of the volume for each node). count, err := c.NodesCount() if err != nil { @@ -511,23 +507,6 @@ func (c *ClusterTx) ContainerNodeMove(project, oldName, newName, newNode string) if n != int64(count) { return fmt.Errorf("unexpected number of updated rows in volumes table: %d", n) } - for _, snapshotName := range snapshots { - oldSnapshotName := oldName + shared.SnapshotDelimiter + snapshotName - newSnapshotName := newName + shared.SnapshotDelimiter + snapshotName - stmt := "UPDATE storage_volumes SET name=? WHERE name=? AND storage_pool_id=? AND type=?" - result, err := c.tx.Exec( - stmt, newSnapshotName, oldSnapshotName, poolID, StoragePoolVolumeTypeContainer) - if err != nil { - return errors.Wrap(err, "failed to update snapshot volume") - } - n, err = result.RowsAffected() - if err != nil { - return errors.Wrap(err, "failed to get rows affected by snapshot volume update") - } - if n != int64(count) { - return fmt.Errorf("unexpected number of updated snapshots in volumes table: %d", n) - } - } return nil } From 68907d21989d5e82a1db180f982d5f18abf1fdd6 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Mon, 17 Feb 2020 14:49:30 +0000 Subject: [PATCH 37/38] lxd/db: copy volume snapshots in StoragePoolNodeJoinCeph Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/db/storage_pools.go | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/lxd/db/storage_pools.go b/lxd/db/storage_pools.go index f30350ab55..1995b6cdc0 100644 --- a/lxd/db/storage_pools.go +++ b/lxd/db/storage_pools.go @@ -161,6 +161,7 @@ SELECT id FROM storage_volumes WHERE storage_pool_id=? AND node_id=? return fmt.Errorf("not all ceph volumes were copied") } for i, otherVolumeID := range otherVolumeIDs { + volumeID := volumeIDs[i] config, err := query.SelectConfig( c.tx, "storage_volumes_config", "storage_volume_id=?", otherVolumeID) if err != nil { @@ -169,11 +170,46 @@ SELECT id FROM storage_volumes WHERE storage_pool_id=? AND node_id=? for key, value := range config { _, err := c.tx.Exec(` INSERT INTO storage_volumes_config(storage_volume_id, key, value) VALUES(?, ?, ?) -`, volumeIDs[i], key, value) +`, volumeID, key, value) if err != nil { return errors.Wrap(err, "failed to copy volume config") } } + + // Copy volume snapshots as well. + otherSnapshotIDs, err := query.SelectIntegers(c.tx, + "SELECT id FROM storage_volumes_snapshots WHERE storage_volume_id = ?", + otherVolumeID) + + for _, otherSnapshotID := range otherSnapshotIDs { + _, err := c.tx.Exec("UPDATE sqlite_sequence SET seq = seq + 1 WHERE name = 'storage_volumes") + if err != nil { + return errors.Wrap(err, "Increment storage volumes sequence") + } + + result, err := c.tx.Exec(` +INSERT INTO storage_volumes_snapshots (id, storage_volume_id, name, description) +SELECT (SELECT seq FROM sqlite_sequence WHERE name = 'storage_volumes' LIMIT 1), ?, name, description + FROM storage_volumes_snapshots WHERE id=? +`, volumeID, otherSnapshotID) + if err != nil { + return errors.Wrap(err, "Copy volume snapshot") + } + snapshotID, err := result.LastInsertId() + if err != nil { + return err + } + + _, err = c.tx.Exec(` +INSERT INTO storage_volumes_snapshots_config (storage_volume_snapshot_id, key, value) +SELECT ?, key, value + FROM storage_volumes_snapshots_config + WHERE storage_volume_snapshot_id=? +`, snapshotID, otherSnapshotID) + if err != nil { + return errors.Wrap(err, "Copy volume snapshot config") + } + } } return nil From 1803e53a897a63c68ab30ccc27480512e08ac7a1 Mon Sep 17 00:00:00 2001 From: Free Ekanayaka <free.ekanay...@canonical.com> Date: Tue, 18 Feb 2020 16:07:25 +0000 Subject: [PATCH 38/38] lxd: no need to rename snapshot volumes when renaming a container Signed-off-by: Free Ekanayaka <free.ekanay...@canonical.com> --- lxd/container_lxc.go | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go index 361ff52d6e..c7ec0200e9 100644 --- a/lxd/container_lxc.go +++ b/lxd/container_lxc.go @@ -3681,28 +3681,6 @@ func (c *containerLXC) Rename(newName string) error { poolID, _, _ := c.storage.GetContainerPoolInfo() - if !c.IsSnapshot() { - // Rename all the snapshot volumes. - results, err := c.state.Cluster.ContainerGetSnapshots(c.project, oldName) - if err != nil { - logger.Error("Failed to get container snapshots", ctxMap) - return err - } - - for _, sname := range results { - // Rename the snapshot volume. - baseSnapName := filepath.Base(sname) - newSnapshotName := newName + shared.SnapshotDelimiter + baseSnapName - - // Rename storage volume for the snapshot. - err = c.state.Cluster.StoragePoolVolumeRename(c.project, sname, newSnapshotName, storagePoolVolumeTypeContainer, poolID) - if err != nil { - logger.Error("Failed renaming storage volume", ctxMap) - return err - } - } - } - // Rename storage volume for the container. err = c.state.Cluster.StoragePoolVolumeRename(c.project, oldName, newName, storagePoolVolumeTypeContainer, poolID) if err != nil {
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel