[lxc-devel] [lxd/master] Separate db-level update logic from daemon-level one

freeekanayaka on Github lxc-bot at linuxcontainers.org
Tue May 16 10:47:36 UTC 2017


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 1477 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20170516/fd4c651b/attachment.bin>
-------------- next part --------------
From 0c8b56f8b602b1da0e8476850bd1e1fb0823b510 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Tue, 16 May 2017 12:38:11 +0200
Subject: [PATCH] Separate db-level update logic from daemon-level one

Our DB patches are currently performing a mix of pure SQL changes and
higher-level upgrade logic (such as dealing with container paths and
LVM volumes). This introduces coupling between the daemon layer and
the db layer, and makes it harder to test SQL upgrade logic in
isolation, and perhaps to eventually make the db code its own
self-contained package that doesn't depend on deamon code (this will
probably turn out to be more important when we start working on the
clustering feature, which will require a more complex persistent story
based on rqlite).

This change moves daemon-specific upgrade logic to its own
daemon_update.go file, which is analogous to db_update.go. Each daemon
update will be performed as a hook that gets run after the matching
database update. I think in general we might have daemon-level updates
that are somehow unrelated to db updates, so we should check something
else than the schema version, but for now I think we can go for this
simple solution, and revise it when we have more real-world cases.

There are now no references to Deamon left in db_update.go

Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
 lxd/daemon.go        |  42 +++++++++
 lxd/daemon_update.go |  90 +++++++++++++++++++
 lxd/db.go            |  36 --------
 lxd/db_test.go       |   4 +-
 lxd/db_update.go     | 245 +++++++++++++++++++++------------------------------
 5 files changed, 233 insertions(+), 184 deletions(-)
 create mode 100644 lxd/daemon_update.go

diff --git a/lxd/daemon.go b/lxd/daemon.go
index cec26f3..b75ae05 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -1393,3 +1393,45 @@ func (s *lxdHttpServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
 	// Call the original server
 	s.r.ServeHTTP(rw, req)
 }
+
+// Create a database connection and perform any updates needed.
+func initializeDbObject(d *Daemon, path string) error {
+	var openPath string
+	var err error
+
+	timeout := 5 // TODO - make this command-line configurable?
+
+	// These are used to tune the transaction BEGIN behavior instead of using the
+	// similar "locking_mode" pragma (locking for the whole database connection).
+	openPath = fmt.Sprintf("%s?_busy_timeout=%d&_txlock=exclusive", path, timeout*1000)
+
+	// Open the database. If the file doesn't exist it is created.
+	d.db, err = sql.Open("sqlite3_with_fk", openPath)
+	if err != nil {
+		return err
+	}
+
+	// Create the DB if it doesn't exist.
+	err = createDb(d.db)
+	if err != nil {
+		return fmt.Errorf("Error creating database: %s", err)
+	}
+
+	// Detect LXD downgrades
+	if dbGetSchema(d.db) > dbGetLatestSchema() {
+		return fmt.Errorf("The database schema is more recent than LXD's schema.")
+	}
+
+	// Apply any update
+	err = dbUpdatesApplyAll(d.db, true, func(version int) error {
+		if daemonUpdate, ok := daemonUpdates[version]; ok {
+			return daemonUpdate(d)
+		}
+		return nil
+	})
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/lxd/daemon_update.go b/lxd/daemon_update.go
new file mode 100644
index 0000000..e8cc29c
--- /dev/null
+++ b/lxd/daemon_update.go
@@ -0,0 +1,90 @@
+// Daemon-level update logic to perform migrations between different
+// versions.
+
+package main
+
+import (
+	"fmt"
+	"os"
+	"strings"
+
+	"github.com/lxc/lxd/shared"
+	"github.com/lxc/lxd/shared/logger"
+
+	log "gopkg.in/inconshreveable/log15.v2"
+)
+
+var daemonUpdates = map[int](func(d *Daemon) error){
+	11: daemonUpdateFromV10,
+	16: daemonUpdateFromV15,
+}
+
+func daemonUpdateFromV10(d *Daemon) error {
+	if shared.PathExists(shared.VarPath("lxc")) {
+		err := os.Rename(shared.VarPath("lxc"), shared.VarPath("containers"))
+		if err != nil {
+			return err
+		}
+
+		logger.Debugf("Restarting all the containers following directory rename")
+		containersShutdown(d)
+		containersRestart(d)
+	}
+
+	return nil
+}
+
+func daemonUpdateFromV15(d *Daemon) error {
+	// munge all LVM-backed containers' LV names to match what is
+	// required for snapshot support
+
+	cNames, err := dbContainersList(d.db, cTypeRegular)
+	if err != nil {
+		return err
+	}
+
+	err = daemonConfigInit(d.db)
+	if err != nil {
+		return err
+	}
+
+	vgName := daemonConfig["storage.lvm_vg_name"].Get()
+
+	for _, cName := range cNames {
+		var lvLinkPath string
+		if strings.Contains(cName, shared.SnapshotDelimiter) {
+			lvLinkPath = shared.VarPath("snapshots", fmt.Sprintf("%s.lv", cName))
+		} else {
+			lvLinkPath = shared.VarPath("containers", fmt.Sprintf("%s.lv", cName))
+		}
+
+		if !shared.PathExists(lvLinkPath) {
+			continue
+		}
+
+		newLVName := strings.Replace(cName, "-", "--", -1)
+		newLVName = strings.Replace(newLVName, shared.SnapshotDelimiter, "-", -1)
+
+		if cName == newLVName {
+			logger.Debug("No need to rename, skipping", log.Ctx{"cName": cName, "newLVName": newLVName})
+			continue
+		}
+
+		logger.Debug("About to rename cName in lv upgrade", log.Ctx{"lvLinkPath": lvLinkPath, "cName": cName, "newLVName": newLVName})
+
+		output, err := shared.RunCommand("lvrename", vgName, cName, newLVName)
+		if err != nil {
+			return fmt.Errorf("Could not rename LV '%s' to '%s': %v\noutput:%s", cName, newLVName, err, output)
+		}
+
+		if err := os.Remove(lvLinkPath); err != nil {
+			return fmt.Errorf("Couldn't remove lvLinkPath '%s'", lvLinkPath)
+		}
+		newLinkDest := fmt.Sprintf("/dev/%s/%s", vgName, newLVName)
+		if err := os.Symlink(newLinkDest, lvLinkPath); err != nil {
+			return fmt.Errorf("Couldn't recreate symlink '%s'->'%s'", lvLinkPath, newLinkDest)
+		}
+	}
+
+	return nil
+}
diff --git a/lxd/db.go b/lxd/db.go
index 1185998..974e483 100644
--- a/lxd/db.go
+++ b/lxd/db.go
@@ -276,42 +276,6 @@ func dbGetLatestSchema() int {
 	return dbUpdates[len(dbUpdates)-1].version
 }
 
-// Create a database connection object and return it.
-func initializeDbObject(d *Daemon, path string) (err error) {
-	var openPath string
-
-	timeout := 5 // TODO - make this command-line configurable?
-
-	// These are used to tune the transaction BEGIN behavior instead of using the
-	// similar "locking_mode" pragma (locking for the whole database connection).
-	openPath = fmt.Sprintf("%s?_busy_timeout=%d&_txlock=exclusive", path, timeout*1000)
-
-	// Open the database. If the file doesn't exist it is created.
-	d.db, err = sql.Open("sqlite3_with_fk", openPath)
-	if err != nil {
-		return err
-	}
-
-	// Create the DB if it doesn't exist.
-	err = createDb(d.db)
-	if err != nil {
-		return fmt.Errorf("Error creating database: %s", err)
-	}
-
-	// Detect LXD downgrades
-	if dbGetSchema(d.db) > dbGetLatestSchema() {
-		return fmt.Errorf("The database schema is more recent than LXD's schema.")
-	}
-
-	// Apply any update
-	err = dbUpdatesApplyAll(d)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
 func isDbLockedError(err error) bool {
 	if err == nil {
 		return false
diff --git a/lxd/db_test.go b/lxd/db_test.go
index b917796..288c875 100644
--- a/lxd/db_test.go
+++ b/lxd/db_test.go
@@ -223,7 +223,7 @@ INSERT INTO containers_config (container_id, key, value) VALUES (1, 'thekey', 't
 	s.Nil(err)
 
 	// Run the upgrade from V6 code
-	err = dbUpdateFromV6(5, 6, d)
+	err = dbUpdateFromV6(5, 6, d.db)
 	s.Nil(err)
 
 	// Make sure the inserted data is still there.
@@ -325,7 +325,7 @@ INSERT INTO containers_config (container_id, key, value) VALUES (1, 'thekey', 't
 	d.db = db
 	daemonConfigInit(db)
 
-	err = dbUpdatesApplyAll(d)
+	err = dbUpdatesApplyAll(d.db, false, nil)
 	s.Nil(err)
 
 	result := dbGetSchema(db)
diff --git a/lxd/db_update.go b/lxd/db_update.go
index 3929be4..6d13090 100644
--- a/lxd/db_update.go
+++ b/lxd/db_update.go
@@ -1,6 +1,7 @@
 package main
 
 import (
+	"database/sql"
 	"encoding/hex"
 	"fmt"
 	"io/ioutil"
@@ -74,20 +75,20 @@ var dbUpdates = []dbUpdate{
 
 type dbUpdate struct {
 	version int
-	run     func(previousVersion int, version int, d *Daemon) error
+	run     func(previousVersion int, version int, db *sql.DB) error
 }
 
-func (u *dbUpdate) apply(currentVersion int, d *Daemon) error {
+func (u *dbUpdate) apply(currentVersion int, db *sql.DB) error {
 	// Get the current schema version
 
 	logger.Debugf("Updating DB schema from %d to %d", currentVersion, u.version)
 
-	err := u.run(currentVersion, u.version, d)
+	err := u.run(currentVersion, u.version, db)
 	if err != nil {
 		return err
 	}
 
-	_, err = d.db.Exec("INSERT INTO schema (version, updated_at) VALUES (?, strftime(\"%s\"));", u.version)
+	_, err = db.Exec("INSERT INTO schema (version, updated_at) VALUES (?, strftime(\"%s\"));", u.version)
 	if err != nil {
 		return err
 	}
@@ -95,8 +96,12 @@ func (u *dbUpdate) apply(currentVersion int, d *Daemon) error {
 	return nil
 }
 
-func dbUpdatesApplyAll(d *Daemon) error {
-	currentVersion := dbGetSchema(d.db)
+// Apply all possible database patches. If "doBackup" is true, the
+// sqlite file will be backed up before any update is applied. If
+// "postApply" it's passed, it will be called after each database update
+// gets successfully applied, and be passed the its version.
+func dbUpdatesApplyAll(db *sql.DB, doBackup bool, postApply func(int) error) error {
+	currentVersion := dbGetSchema(db)
 
 	backup := false
 	for _, update := range dbUpdates {
@@ -104,7 +109,7 @@ func dbUpdatesApplyAll(d *Daemon) error {
 			continue
 		}
 
-		if !d.MockMode && !backup {
+		if doBackup && !backup {
 			logger.Infof("Updating the LXD database schema. Backup made as \"lxd.db.bak\"")
 			err := shared.FileCopy(shared.VarPath("lxd.db"), shared.VarPath("lxd.db.bak"))
 			if err != nil {
@@ -114,10 +119,16 @@ func dbUpdatesApplyAll(d *Daemon) error {
 			backup = true
 		}
 
-		err := update.apply(currentVersion, d)
+		err := update.apply(currentVersion, db)
 		if err != nil {
 			return err
 		}
+		if postApply != nil {
+			err = postApply(update.version)
+			if err != nil {
+				return err
+			}
+		}
 
 		currentVersion = update.version
 	}
@@ -126,7 +137,7 @@ func dbUpdatesApplyAll(d *Daemon) error {
 }
 
 // Schema updates begin here
-func dbUpdateFromV35(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV35(currentVersion int, version int, db *sql.DB) error {
 	stmts := `
 CREATE TABLE tmp (
     id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -147,11 +158,11 @@ ALTER TABLE storage_pools ADD COLUMN description TEXT;
 ALTER TABLE storage_volumes ADD COLUMN description TEXT;
 ALTER TABLE containers ADD COLUMN description TEXT;
 `
-	_, err := d.db.Exec(stmts)
+	_, err := db.Exec(stmts)
 	return err
 }
 
-func dbUpdateFromV34(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV34(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 CREATE TABLE IF NOT EXISTS storage_pools (
     id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -183,11 +194,11 @@ CREATE TABLE IF NOT EXISTS storage_volumes_config (
     UNIQUE (storage_volume_id, key),
     FOREIGN KEY (storage_volume_id) REFERENCES storage_volumes (id) ON DELETE CASCADE
 );`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV33(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV33(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 CREATE TABLE IF NOT EXISTS networks (
     id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -202,16 +213,16 @@ CREATE TABLE IF NOT EXISTS networks_config (
     UNIQUE (network_id, key),
     FOREIGN KEY (network_id) REFERENCES networks (id) ON DELETE CASCADE
 );`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV32(currentVersion int, version int, d *Daemon) error {
-	_, err := d.db.Exec("ALTER TABLE containers ADD COLUMN last_use_date DATETIME;")
+func dbUpdateFromV32(currentVersion int, version int, db *sql.DB) error {
+	_, err := db.Exec("ALTER TABLE containers ADD COLUMN last_use_date DATETIME;")
 	return err
 }
 
-func dbUpdateFromV31(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV31(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 CREATE TABLE IF NOT EXISTS patches (
     id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -219,11 +230,11 @@ CREATE TABLE IF NOT EXISTS patches (
     applied_at DATETIME NOT NULL,
     UNIQUE (name)
 );`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV30(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV30(currentVersion int, version int, db *sql.DB) error {
 	entries, err := ioutil.ReadDir(shared.VarPath("containers"))
 	if err != nil {
 		/* If the directory didn't exist before, the user had never
@@ -262,7 +273,7 @@ func dbUpdateFromV30(currentVersion int, version int, d *Daemon) error {
 	return nil
 }
 
-func dbUpdateFromV29(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV29(currentVersion int, version int, db *sql.DB) error {
 	if shared.PathExists(shared.VarPath("zfs.img")) {
 		err := os.Chmod(shared.VarPath("zfs.img"), 0600)
 		if err != nil {
@@ -273,22 +284,22 @@ func dbUpdateFromV29(currentVersion int, version int, d *Daemon) error {
 	return nil
 }
 
-func dbUpdateFromV28(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV28(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 INSERT INTO profiles_devices (profile_id, name, type) SELECT id, "aadisable", 2 FROM profiles WHERE name="docker";
 INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "source", "/dev/null" FROM profiles_devices LEFT JOIN profiles WHERE profiles_devices.profile_id = profiles.id AND profiles.name = "docker" AND profiles_devices.name = "aadisable";
 INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "path", "/sys/module/apparmor/parameters/enabled" FROM profiles_devices LEFT JOIN profiles WHERE profiles_devices.profile_id = profiles.id AND profiles.name = "docker" AND profiles_devices.name = "aadisable";`
-	d.db.Exec(stmt)
+	db.Exec(stmt)
 
 	return nil
 }
 
-func dbUpdateFromV27(currentVersion int, version int, d *Daemon) error {
-	_, err := d.db.Exec("UPDATE profiles_devices SET type=3 WHERE type='unix-char';")
+func dbUpdateFromV27(currentVersion int, version int, db *sql.DB) error {
+	_, err := db.Exec("UPDATE profiles_devices SET type=3 WHERE type='unix-char';")
 	return err
 }
 
-func dbUpdateFromV26(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV26(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 ALTER TABLE images ADD COLUMN auto_update INTEGER NOT NULL DEFAULT 0;
 CREATE TABLE IF NOT EXISTS images_source (
@@ -300,58 +311,58 @@ CREATE TABLE IF NOT EXISTS images_source (
     alias VARCHAR(255) NOT NULL,
     FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE
 );`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV25(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV25(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 INSERT INTO profiles (name, description) VALUES ("docker", "Profile supporting docker in containers");
 INSERT INTO profiles_config (profile_id, key, value) SELECT id, "security.nesting", "true" FROM profiles WHERE name="docker";
 INSERT INTO profiles_config (profile_id, key, value) SELECT id, "linux.kernel_modules", "overlay, nf_nat" FROM profiles WHERE name="docker";
 INSERT INTO profiles_devices (profile_id, name, type) SELECT id, "fuse", "unix-char" FROM profiles WHERE name="docker";
 INSERT INTO profiles_devices_config (profile_device_id, key, value) SELECT profiles_devices.id, "path", "/dev/fuse" FROM profiles_devices LEFT JOIN profiles WHERE profiles_devices.profile_id = profiles.id AND profiles.name = "docker";`
-	d.db.Exec(stmt)
+	db.Exec(stmt)
 
 	return nil
 }
 
-func dbUpdateFromV24(currentVersion int, version int, d *Daemon) error {
-	_, err := d.db.Exec("ALTER TABLE containers ADD COLUMN stateful INTEGER NOT NULL DEFAULT 0;")
+func dbUpdateFromV24(currentVersion int, version int, db *sql.DB) error {
+	_, err := db.Exec("ALTER TABLE containers ADD COLUMN stateful INTEGER NOT NULL DEFAULT 0;")
 	return err
 }
 
-func dbUpdateFromV23(currentVersion int, version int, d *Daemon) error {
-	_, err := d.db.Exec("ALTER TABLE profiles ADD COLUMN description TEXT;")
+func dbUpdateFromV23(currentVersion int, version int, db *sql.DB) error {
+	_, err := db.Exec("ALTER TABLE profiles ADD COLUMN description TEXT;")
 	return err
 }
 
-func dbUpdateFromV22(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV22(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 DELETE FROM containers_devices_config WHERE key='type';
 DELETE FROM profiles_devices_config WHERE key='type';`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV21(currentVersion int, version int, d *Daemon) error {
-	_, err := d.db.Exec("ALTER TABLE containers ADD COLUMN creation_date DATETIME NOT NULL DEFAULT 0;")
+func dbUpdateFromV21(currentVersion int, version int, db *sql.DB) error {
+	_, err := db.Exec("ALTER TABLE containers ADD COLUMN creation_date DATETIME NOT NULL DEFAULT 0;")
 	return err
 }
 
-func dbUpdateFromV20(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV20(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 UPDATE containers_devices SET name='__lxd_upgrade_root' WHERE name='root';
 UPDATE profiles_devices SET name='__lxd_upgrade_root' WHERE name='root';
 
 INSERT INTO containers_devices (container_id, name, type) SELECT id, "root", 2 FROM containers;
 INSERT INTO containers_devices_config (container_device_id, key, value) SELECT id, "path", "/" FROM containers_devices WHERE name='root';`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 
 	return err
 }
 
-func dbUpdateFromV19(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV19(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 DELETE FROM containers_config WHERE container_id NOT IN (SELECT id FROM containers);
 DELETE FROM containers_devices_config WHERE container_device_id NOT IN (SELECT id FROM containers_devices WHERE container_id IN (SELECT id FROM containers));
@@ -359,16 +370,16 @@ DELETE FROM containers_devices WHERE container_id NOT IN (SELECT id FROM contain
 DELETE FROM containers_profiles WHERE container_id NOT IN (SELECT id FROM containers);
 DELETE FROM images_aliases WHERE image_id NOT IN (SELECT id FROM images);
 DELETE FROM images_properties WHERE image_id NOT IN (SELECT id FROM images);`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV18(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV18(currentVersion int, version int, db *sql.DB) error {
 	var id int
 	var value string
 
 	// Update container config
-	rows, err := dbQueryScan(d.db, "SELECT id, value FROM containers_config WHERE key='limits.memory'", nil, []interface{}{id, value})
+	rows, err := dbQueryScan(db, "SELECT id, value FROM containers_config WHERE key='limits.memory'", nil, []interface{}{id, value})
 	if err != nil {
 		return err
 	}
@@ -391,21 +402,21 @@ func dbUpdateFromV18(currentVersion int, version int, d *Daemon) error {
 		_, err = shared.ParseByteSizeString(value)
 		if err != nil {
 			logger.Debugf("Invalid container memory limit, id=%d value=%s, removing.", id, value)
-			_, err = d.db.Exec("DELETE FROM containers_config WHERE id=?;", id)
+			_, err = db.Exec("DELETE FROM containers_config WHERE id=?;", id)
 			if err != nil {
 				return err
 			}
 		}
 
 		// Set the new value
-		_, err = d.db.Exec("UPDATE containers_config SET value=? WHERE id=?", value, id)
+		_, err = db.Exec("UPDATE containers_config SET value=? WHERE id=?", value, id)
 		if err != nil {
 			return err
 		}
 	}
 
 	// Update profiles config
-	rows, err = dbQueryScan(d.db, "SELECT id, value FROM profiles_config WHERE key='limits.memory'", nil, []interface{}{id, value})
+	rows, err = dbQueryScan(db, "SELECT id, value FROM profiles_config WHERE key='limits.memory'", nil, []interface{}{id, value})
 	if err != nil {
 		return err
 	}
@@ -428,14 +439,14 @@ func dbUpdateFromV18(currentVersion int, version int, d *Daemon) error {
 		_, err = shared.ParseByteSizeString(value)
 		if err != nil {
 			logger.Debugf("Invalid profile memory limit, id=%d value=%s, removing.", id, value)
-			_, err = d.db.Exec("DELETE FROM profiles_config WHERE id=?;", id)
+			_, err = db.Exec("DELETE FROM profiles_config WHERE id=?;", id)
 			if err != nil {
 				return err
 			}
 		}
 
 		// Set the new value
-		_, err = d.db.Exec("UPDATE profiles_config SET value=? WHERE id=?", value, id)
+		_, err = db.Exec("UPDATE profiles_config SET value=? WHERE id=?", value, id)
 		if err != nil {
 			return err
 		}
@@ -444,79 +455,30 @@ func dbUpdateFromV18(currentVersion int, version int, d *Daemon) error {
 	return nil
 }
 
-func dbUpdateFromV17(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV17(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 DELETE FROM profiles_config WHERE key LIKE 'volatile.%';
 UPDATE containers_config SET key='limits.cpu' WHERE key='limits.cpus';
 UPDATE profiles_config SET key='limits.cpu' WHERE key='limits.cpus';`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV16(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV16(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 UPDATE config SET key='storage.lvm_vg_name' WHERE key = 'core.lvm_vg_name';
 UPDATE config SET key='storage.lvm_thinpool_name' WHERE key = 'core.lvm_thinpool_name';`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV15(currentVersion int, version int, d *Daemon) error {
-	// munge all LVM-backed containers' LV names to match what is
-	// required for snapshot support
-
-	cNames, err := dbContainersList(d.db, cTypeRegular)
-	if err != nil {
-		return err
-	}
-
-	err = daemonConfigInit(d.db)
-	if err != nil {
-		return err
-	}
-
-	vgName := daemonConfig["storage.lvm_vg_name"].Get()
-
-	for _, cName := range cNames {
-		var lvLinkPath string
-		if strings.Contains(cName, shared.SnapshotDelimiter) {
-			lvLinkPath = shared.VarPath("snapshots", fmt.Sprintf("%s.lv", cName))
-		} else {
-			lvLinkPath = shared.VarPath("containers", fmt.Sprintf("%s.lv", cName))
-		}
-
-		if !shared.PathExists(lvLinkPath) {
-			continue
-		}
-
-		newLVName := strings.Replace(cName, "-", "--", -1)
-		newLVName = strings.Replace(newLVName, shared.SnapshotDelimiter, "-", -1)
-
-		if cName == newLVName {
-			logger.Debug("No need to rename, skipping", log.Ctx{"cName": cName, "newLVName": newLVName})
-			continue
-		}
-
-		logger.Debug("About to rename cName in lv upgrade", log.Ctx{"lvLinkPath": lvLinkPath, "cName": cName, "newLVName": newLVName})
-
-		output, err := shared.RunCommand("lvrename", vgName, cName, newLVName)
-		if err != nil {
-			return fmt.Errorf("Could not rename LV '%s' to '%s': %v\noutput:%s", cName, newLVName, err, output)
-		}
-
-		if err := os.Remove(lvLinkPath); err != nil {
-			return fmt.Errorf("Couldn't remove lvLinkPath '%s'", lvLinkPath)
-		}
-		newLinkDest := fmt.Sprintf("/dev/%s/%s", vgName, newLVName)
-		if err := os.Symlink(newLinkDest, lvLinkPath); err != nil {
-			return fmt.Errorf("Couldn't recreate symlink '%s'->'%s'", lvLinkPath, newLinkDest)
-		}
-	}
-
+func dbUpdateFromV15(currentVersion int, version int, db *sql.DB) error {
+	// NOTE: this database update contained daemon-level logic which
+	//       was been moved to daemonUpdateFromV15.
 	return nil
 }
 
-func dbUpdateFromV14(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV14(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 PRAGMA foreign_keys=OFF; -- So that integrity doesn't get in the way for now
 
@@ -545,27 +507,27 @@ DROP TABLE containers;
 ALTER TABLE tmp RENAME TO containers;
 
 PRAGMA foreign_keys=ON; -- Make sure we turn integrity checks back on.`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV13(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV13(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 UPDATE containers_config SET key='volatile.base_image' WHERE key = 'volatile.baseImage';`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV12(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV12(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 ALTER TABLE images ADD COLUMN cached INTEGER NOT NULL DEFAULT 0;
 ALTER TABLE images ADD COLUMN last_use_date DATETIME;`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV11(currentVersion int, version int, d *Daemon) error {
-	cNames, err := dbContainersList(d.db, cTypeSnapshot)
+func dbUpdateFromV11(currentVersion int, version int, db *sql.DB) error {
+	cNames, err := dbContainersList(db, cTypeSnapshot)
 	if err != nil {
 		return err
 	}
@@ -632,22 +594,13 @@ func dbUpdateFromV11(currentVersion int, version int, d *Daemon) error {
 	return nil
 }
 
-func dbUpdateFromV10(currentVersion int, version int, d *Daemon) error {
-	if shared.PathExists(shared.VarPath("lxc")) {
-		err := os.Rename(shared.VarPath("lxc"), shared.VarPath("containers"))
-		if err != nil {
-			return err
-		}
-
-		logger.Debugf("Restarting all the containers following directory rename")
-		containersShutdown(d)
-		containersRestart(d)
-	}
-
+func dbUpdateFromV10(currentVersion int, version int, db *sql.DB) error {
+	// NOTE: this database update contained daemon-level logic which
+	//       was been moved to daemonUpdateFromV10.
 	return nil
 }
 
-func dbUpdateFromV9(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV9(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 CREATE TABLE tmp (
     id INTEGER primary key AUTOINCREMENT NOT NULL,
@@ -686,26 +639,26 @@ UPDATE profiles_devices SET type=3 WHERE id IN (SELECT id FROM tmp WHERE type="u
 UPDATE profiles_devices SET type=4 WHERE id IN (SELECT id FROM tmp WHERE type="unix-block");
 
 DROP TABLE tmp;`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV8(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV8(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 UPDATE certificates SET fingerprint = replace(fingerprint, " ", "");`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV7(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV7(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 UPDATE config SET key='core.trust_password' WHERE key IN ('password', 'trust_password', 'trust-password', 'core.trust-password');
 DELETE FROM config WHERE key != 'core.trust_password';`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV6(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV6(currentVersion int, version int, db *sql.DB) error {
 	// This update recreates the schemas that need an ON DELETE CASCADE foreign
 	// key.
 	stmt := `
@@ -830,13 +783,13 @@ INSERT INTO profiles_devices_config SELECT * FROM tmp;
 DROP TABLE tmp;
 
 PRAGMA foreign_keys=ON; -- Make sure we turn integrity checks back on.`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	if err != nil {
 		return err
 	}
 
 	// Get the rows with broken foreign keys an nuke them
-	rows, err := d.db.Query("PRAGMA foreign_key_check;")
+	rows, err := db.Query("PRAGMA foreign_key_check;")
 	if err != nil {
 		return err
 	}
@@ -858,7 +811,7 @@ PRAGMA foreign_keys=ON; -- Make sure we turn integrity checks back on.`
 	rows.Close()
 
 	for i := range tablestodelete {
-		_, err = d.db.Exec(fmt.Sprintf("DELETE FROM %s WHERE rowid = %d;", tablestodelete[i], rowidtodelete[i]))
+		_, err = db.Exec(fmt.Sprintf("DELETE FROM %s WHERE rowid = %d;", tablestodelete[i], rowidtodelete[i]))
 		if err != nil {
 			return err
 		}
@@ -867,15 +820,15 @@ PRAGMA foreign_keys=ON; -- Make sure we turn integrity checks back on.`
 	return err
 }
 
-func dbUpdateFromV5(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV5(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 ALTER TABLE containers ADD COLUMN power_state INTEGER NOT NULL DEFAULT 0;
 ALTER TABLE containers ADD COLUMN ephemeral INTEGER NOT NULL DEFAULT 0;`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV4(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV4(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 CREATE TABLE IF NOT EXISTS config (
     id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -884,7 +837,7 @@ CREATE TABLE IF NOT EXISTS config (
     UNIQUE (key)
 );`
 
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	if err != nil {
 		return err
 	}
@@ -903,7 +856,7 @@ CREATE TABLE IF NOT EXISTS config (
 		oldPassword = hex.EncodeToString(buff)
 		stmt := `INSERT INTO config (key, value) VALUES ("core.trust_password", ?);`
 
-		_, err := d.db.Exec(stmt, oldPassword)
+		_, err := db.Exec(stmt, oldPassword)
 		if err != nil {
 			return err
 		}
@@ -914,14 +867,14 @@ CREATE TABLE IF NOT EXISTS config (
 	return nil
 }
 
-func dbUpdateFromV3(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV3(currentVersion int, version int, db *sql.DB) error {
 	// Attempt to create a default profile (but don't fail if already there)
-	d.db.Exec("INSERT INTO profiles (name) VALUES (\"default\");")
+	db.Exec("INSERT INTO profiles (name) VALUES (\"default\");")
 
 	return nil
 }
 
-func dbUpdateFromV2(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV2(currentVersion int, version int, db *sql.DB) error {
 	stmt := `
 CREATE TABLE IF NOT EXISTS containers_devices (
     id INTEGER primary key AUTOINCREMENT NOT NULL,
@@ -977,11 +930,11 @@ CREATE TABLE IF NOT EXISTS profiles_devices_config (
     UNIQUE (profile_device_id, key),
     FOREIGN KEY (profile_device_id) REFERENCES profiles_devices (id)
 );`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV1(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV1(currentVersion int, version int, db *sql.DB) error {
 	// v1..v2 adds images aliases
 	stmt := `
 CREATE TABLE IF NOT EXISTS images_aliases (
@@ -992,11 +945,11 @@ CREATE TABLE IF NOT EXISTS images_aliases (
     FOREIGN KEY (image_id) REFERENCES images (id) ON DELETE CASCADE,
     UNIQUE (name)
 );`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }
 
-func dbUpdateFromV0(currentVersion int, version int, d *Daemon) error {
+func dbUpdateFromV0(currentVersion int, version int, db *sql.DB) error {
 	// v0..v1 adds schema table
 	stmt := `
 CREATE TABLE IF NOT EXISTS schema (
@@ -1005,6 +958,6 @@ CREATE TABLE IF NOT EXISTS schema (
     updated_at DATETIME NOT NULL,
     UNIQUE (version)
 );`
-	_, err := d.db.Exec(stmt)
+	_, err := db.Exec(stmt)
 	return err
 }


More information about the lxc-devel mailing list