[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