[lxc-devel] [lxd/master] Cope with broken foreign key references when upgrading

freeekanayaka on Github lxc-bot at linuxcontainers.org
Thu Mar 8 13:23:40 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 361 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180308/ba549243/attachment.bin>
-------------- next part --------------
From 29f0cd16953a2a791449038538491e0ab3c35d17 Mon Sep 17 00:00:00 2001
From: Free Ekanayaka <free.ekanayaka at canonical.com>
Date: Thu, 8 Mar 2018 13:00:07 +0000
Subject: [PATCH] Cope with broken foreign key references when upgrading

Signed-off-by: Free Ekanayaka <free.ekanayaka at canonical.com>
---
 lxd/daemon.go       | 14 ++++++++++++++
 lxd/db/migration.go | 20 ++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/lxd/daemon.go b/lxd/daemon.go
index d8ebcace7..25ee1aae8 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -487,6 +487,20 @@ func (d *Daemon) init() error {
 		logger.Infof("Migrating data from lxd.db to db.bin")
 		err = d.cluster.ImportPreClusteringData(dump)
 		if err != nil {
+			// Restore the local sqlite3 backup and wipe the raft
+			// directory, so users can fix problems and retry.
+			path := filepath.Join(d.os.VarDir, "lxd.db")
+			copyErr := shared.FileCopy(path+".bak", path)
+			if copyErr != nil {
+				// Ignore errors here, there's not much we can do
+				logger.Errorf("Failed to restore lxd.db: %v", copyErr)
+			}
+			rmErr := os.RemoveAll(filepath.Join(d.os.VarDir, "raft"))
+			if rmErr != nil {
+				// Ignore errors here, there's not much we can do
+				logger.Errorf("Failed to cleanup raft db: %v", rmErr)
+			}
+
 			return fmt.Errorf("Failed to migrate data to db.bin: %v", err)
 		}
 	}
diff --git a/lxd/db/migration.go b/lxd/db/migration.go
index 4d3d20a07..47c305fdb 100644
--- a/lxd/db/migration.go
+++ b/lxd/db/migration.go
@@ -19,6 +19,26 @@ import (
 // clustering, since in those version all data lives in the cluster database
 // (regardless of whether clustering is actually on or off).
 func LoadPreClusteringData(tx *sql.Tx) (*Dump, error) {
+	// Sanitize broken foreign key references that might be around from the
+	// time where we didn't enforce foreign key constraints.
+	_, err := tx.Exec(`
+DELETE FROM containers_config WHERE container_id NOT IN (SELECT id FROM containers);
+DELETE FROM containers_devices WHERE container_id NOT IN (SELECT id FROM containers);
+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);
+DELETE FROM images_source WHERE image_id NOT IN (SELECT id FROM images);
+DELETE FROM networks_config WHERE network_id NOT IN (SELECT id FROM networks);
+DELETE FROM profiles_config WHERE profile_id NOT IN (SELECT id FROM profiles);
+DELETE FROM profiles_devices WHERE profile_id NOT IN (SELECT id FROM profiles);
+DELETE FROM storage_pools_config WHERE storage_pool_id NOT IN (SELECT id FROM storage_pools);
+DELETE FROM storage_volumes WHERE storage_pool_id NOT IN (SELECT id FROM storage_pools);
+DELETE FROM config WHERE NOT key='core.https_address';
+`)
+	if err != nil {
+		return nil, errors.Wrap(err, "failed to sanitize broken foreign key references")
+	}
+
 	// Dump all tables.
 	dump := &Dump{
 		Schema: map[string][]string{},


More information about the lxc-devel mailing list