Skip to content

Commit acb72f6

Browse files
committed
migration: check db versions before migrating any db
1 parent 076ade5 commit acb72f6

File tree

2 files changed

+72
-28
lines changed

2 files changed

+72
-28
lines changed

cmd_migrate_db.go

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ var (
177177
lncfg.NSWalletDB,
178178
lncfg.NSNeutrinoDB,
179179
}
180+
181+
// databasesWithMigrations are the databases that have new versions
182+
// introduced during their lifetime and therefore need to be up to
183+
// date before we can start the migration to SQL backends.
184+
databasesWithMigrations = []string{
185+
lncfg.NSChannelDB,
186+
lncfg.NSTowerClientDB,
187+
}
180188
)
181189

182190
func (x *migrateDBCommand) Execute(_ []string) error {
@@ -205,6 +213,60 @@ func (x *migrateDBCommand) Execute(_ []string) error {
205213
// interceptor.
206214
ctx := getContext()
207215

216+
// Before starting any migration, make sure that all existing dbs have
217+
// the latest migrations applied so that we do only migrate when all
218+
// dbs are up to date. For example it might happen that a user run a
219+
// watchtower client earlier and has it switched off since new
220+
// migrations have been introduced. In that case we do not start the
221+
// migration but first let the user either delete the outdated db or
222+
// migrate it by activating the watchtower client again.
223+
for _, prefix := range databasesWithMigrations {
224+
logger.Infof("Checking db version of database %s", prefix)
225+
226+
// Check if the database file exists before trying to open it.
227+
dbPath := getBoltDBPath(x.Source, prefix, x.Network)
228+
if dbPath == "" {
229+
return fmt.Errorf("unknown prefix: %s", prefix)
230+
}
231+
232+
// Open and check the database version.
233+
srcDb, err := openSourceDb(x.Source, prefix, x.Network, true)
234+
if err == kvdb.ErrDbDoesNotExist {
235+
// Only skip if it's an optional because it's not
236+
// required to run a wtclient or wtserver for example.
237+
if optionalDBs[prefix] {
238+
logger.Warnf("Skipping checking db version "+
239+
"of optional DB %s: not found", prefix)
240+
241+
continue
242+
}
243+
}
244+
if err != nil {
245+
return fmt.Errorf("failed to open source db with "+
246+
"prefix `%s` for version check: %w", prefix,
247+
err)
248+
}
249+
250+
switch prefix {
251+
case lncfg.NSChannelDB:
252+
err := checkChannelDBMigrationsApplied(srcDb)
253+
if err != nil {
254+
srcDb.Close()
255+
return err
256+
}
257+
258+
case lncfg.NSTowerClientDB:
259+
err := checkWTClientDBMigrationsApplied(srcDb)
260+
if err != nil {
261+
srcDb.Close()
262+
return err
263+
}
264+
}
265+
266+
srcDb.Close()
267+
logger.Infof("Version check passed for database %s", prefix)
268+
}
269+
208270
for _, prefix := range allDBPrefixes {
209271
logger.Infof("Attempting to migrate DB with prefix `%s`", prefix)
210272

@@ -344,31 +406,6 @@ func (x *migrateDBCommand) Execute(_ []string) error {
344406
prefix, sourceMarker, destMarker)
345407
}
346408

347-
// Check that the source DB has had all its schema migrations
348-
// applied before we migrate any of its data. Currently only
349-
// migration of the channel.db and the watchtower.db exist.
350-
// Check channel.db migrations.
351-
if prefix == lncfg.NSChannelDB {
352-
logger.Info("Checking DB version of source DB " +
353-
"(channel.db)")
354-
355-
err := checkChannelDBMigrationsApplied(srcDb)
356-
if err != nil {
357-
return err
358-
}
359-
}
360-
361-
// Check watchtower client DB migrations.
362-
if prefix == lncfg.NSTowerClientDB {
363-
logger.Info("Checking DB version of source DB " +
364-
"(wtclient.db)")
365-
366-
err := checkWTClientDBMigrationsApplied(srcDb)
367-
if err != nil {
368-
return err
369-
}
370-
}
371-
372409
// In case we want to start a new migration we delete the
373410
// migration meta db if it exits. This can only be done if
374411
// the db is not already successfully migrated otherwise
@@ -826,7 +863,9 @@ func checkWTClientDBMigrationsApplied(db kvdb.Backend) error {
826863
return fmt.Errorf("refusing to migrate source database with "+
827864
"version %d while latest known DB version is %d; "+
828865
"please upgrade the DB before using the data "+
829-
"migration tool", version, wtdb.LatestDBMigrationVersion())
866+
"migration tool or delete the wtclient.db manually "+
867+
"in case you don't plan to use the watchtower client "+
868+
"anymore", version, wtdb.LatestDBMigrationVersion())
830869
}
831870

832871
return nil

docs/data-migration.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ e.g. 200MB
6969
This version introduced an optimized revocation log storage system that
7070
reduces the storage footprint. All channels will be automatically migrated
7171
to this new format when the setting is enabled.
72-
6. Start `lnd` normally, using the flags mentioned above but not yet changing
72+
6. If you have ever run the watchtower client you need to make sure before
73+
starting the migration that you either activate it again and restart LND so
74+
that the db is up to date (the newest migrations have been applied) or you
75+
delete the `wtclient.db` manually so that the migration can proceed
76+
successfully because you do not plan to use the wtclient anymore.
77+
7. Start `lnd` normally, using the flags mentioned above but not yet changing
7378
any database backend related configuration options. Check the log that the
7479
database schema was migrated successfully, for example: `Checking for
7580
schema update: latest_version=XX, db_version=XX`. This relates to the
@@ -79,7 +84,7 @@ e.g. 200MB
7984
that all LND nodes which want to migrate to the SQL world have the latest db
8085
modifications in place before migrating to a different DB type. If that is
8186
not the case the migration will be refused.
82-
7. Stop `lnd` again and make sure it isn't started again by accident during the
87+
8. Stop `lnd` again and make sure it isn't started again by accident during the
8388
data migration (e.g. disable any `systemd` or other scripts that start/stop
8489
`lnd`).
8590

0 commit comments

Comments
 (0)