Skip to content

Commit 424f5ea

Browse files
Mateusz PiestaSP2FET
Mateusz Piesta
authored andcommitted
[MOS-855] Restore process update
Fixed issues with restoring from legacy backups and cases when the database set fetched from backup package is different than the system one.
1 parent ca7de85 commit 424f5ea

File tree

12 files changed

+145
-85
lines changed

12 files changed

+145
-85
lines changed

.gitignore

+8-2
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,16 @@ test/test_env
6868
image/luts.bin
6969
image/assets/fonts/*
7070

71+
scripts/lua/migration/test/databases/*
72+
scripts/lua/migration/test/migrations/*
7173
scripts/lua/test/assets*
72-
scripts/lua/test/update/user/temp/*
74+
scripts/lua/test/device/user/temp/recovery_status.json
75+
scripts/lua/test/update/user/*
7376
scripts/lua/test/update/target/*
7477
scripts/lua/test/update/system/*
75-
scripts/lua/test/update_udm/user/temp/*
78+
scripts/lua/test/update_udm/user/*
7679
scripts/lua/test/update_udm/target/*
7780
scripts/lua/test/update_udm/system/*
81+
scripts/lua/test/restore/user/*
82+
scripts/lua/test/restore/target/*
83+
scripts/lua/test/restore/system/*

scripts/lua/entry.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ local function generate_report_file(boot_reason_str, success, message)
3737
local body = string.format(
3838
"{\"version\": \"%s\",\"branch\": \"%s\",\"revision\": \"%s\",\"operation\": \"%s\",\"successful\": %s,\"message\": \"%s\"}",
3939
rec.version(), rec.branch(), rec.revision(), boot_reason_str, tostring(success), message)
40-
local fd = io.open(file_path, 'w')
40+
local fd = assert(io.open(file_path, 'w'))
4141
fd:write(body)
4242
fd:close()
4343
end

scripts/lua/migration/migration.lua

+15-8
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ local function build_database_path(path, db_name)
3737
end
3838

3939
local function db_exec(file, script, version)
40-
local db = assert(sqlite3.open(file), string.format("file: %s", file))
41-
assert(db:exec(script) == sqlite3.OK, string.format("script:\n%s\n", script))
40+
local db = assert(sqlite3.open(file))
41+
assert(db:exec(script) == sqlite3.OK, string.format("Script execution failed:\n%s\n", script))
4242
assert(db:exec(string.format("PRAGMA user_version=%u;", version)) == sqlite3.OK,
43-
string.format("version: %d", version))
43+
string.format("Setting database version: %d failed", version))
4444
db:close()
4545
end
4646

@@ -90,26 +90,33 @@ local function db_migrate_down(db_path, scripts, target_version)
9090
end
9191

9292
local function print_db_set(db_set)
93-
print("database set:")
93+
print("Database set(name,version):")
9494
for name, version in pairs(db_set) do
95-
print(string.format("'%s':%d",name,version))
95+
print(string.format(" '%s':%d", name, version))
9696
end
9797
end
9898

9999
local function validate_inputs(migration_dir, db_dir)
100-
assert(helpers.exists(migration_dir), "Migrations directory does not exist")
100+
assert(helpers.exists(migration_dir), "Migration directory does not exist")
101101
assert(helpers.exists(db_dir), "Databases directory does not exist")
102102
return true
103103
end
104104

105105
local function migrate(db_path, scripts_up, scripts_down, target_version)
106106
local db_version = read_db_version(db_path)
107+
107108
if db_version > target_version then
109+
print(string.format("Performing migration-down of '%s' from version %d to %d", db_path, db_version,
110+
target_version))
108111
return migration.down(db_path, scripts_down, target_version)
109112
end
110113
if db_version < target_version then
114+
print(
115+
string.format("Performing migration-up of '%s' from version %d to %d", db_path, db_version, target_version))
111116
return migration.up(db_path, scripts_up, target_version)
112117
end
118+
119+
print(string.format("Migration not needed, '%s' is already the newest version", db_path))
113120
return migration.retcode.OK
114121
end
115122

@@ -148,8 +155,8 @@ end
148155
-- @param db_set array of {<"database_name"> = <db_target_version>} entries
149156
-- @return @{retcode}
150157
function migration.migrate(db_dir, scripts_dir, db_set)
151-
print(string.format("migrations scripts directory: '%s'", scripts_dir))
152-
print(string.format("databases directory: '%s'", db_dir))
158+
print(string.format("Migration scripts directory: '%s'", scripts_dir))
159+
print(string.format("Databases directory: '%s'", db_dir))
153160
print_db_set(db_set)
154161

155162
for name, version in pairs(db_set) do

scripts/lua/migration/test/test.lua

+37-31
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
--Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
2-
--For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
3-
1+
-- Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
2+
-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
43
package.path = package.path .. ";../?.lua;../../share/?.lua;../../share/?/?.lua"
54
local lu = require("luaunit")
65
local sqlite = require("lsqlite3complete")
@@ -41,35 +40,35 @@ function test_migration_up_success()
4140
scripts[5] = "ALTER TABLE test_1 ADD new_column5 TEXT;"
4241

4342
--- Migrate from version 0 to 1
44-
spawn_db("test_1.sql", 0, test_db_schema)
45-
lu.assertEquals(migration.up("test_1.sql", scripts, 1), migration.retcode.OK)
46-
lu.assertEquals(migration.get_db_version("test_1.sql"), 1)
43+
spawn_db("databases/test_1.sql", 0, test_db_schema)
44+
lu.assertEquals(migration.up("databases/test_1.sql", scripts, 1), migration.retcode.OK)
45+
lu.assertEquals(migration.get_db_version("databases/test_1.sql"), 1)
4746

4847
-- Migrate from version 1 to 2
49-
lu.assertEquals(migration.up("test_1.sql", scripts, 2), migration.retcode.OK)
50-
lu.assertEquals(migration.get_db_version("test_1.sql"), 2)
48+
lu.assertEquals(migration.up("databases/test_1.sql", scripts, 2), migration.retcode.OK)
49+
lu.assertEquals(migration.get_db_version("databases/test_1.sql"), 2)
5150

5251
--- Migrate from version 0 to 5
53-
spawn_db("test_1.sql", 0, test_db_schema)
54-
lu.assertEquals(migration.up("test_1.sql", scripts, 5), migration.retcode.OK)
55-
lu.assertEquals(migration.get_db_version("test_1.sql"), 5)
52+
spawn_db("databases/test_1.sql", 0, test_db_schema)
53+
lu.assertEquals(migration.up("databases/test_1.sql", scripts, 5), migration.retcode.OK)
54+
lu.assertEquals(migration.get_db_version("databases/test_1.sql"), 5)
5655
end
5756

5857
function test_migration_up_db_errors()
5958
scripts = {}
6059

6160
--- Trigger DB error by trying to operate on empty database
62-
spawn_db("test_1.sql", 1, "")
61+
spawn_db("databases/test_1.sql", 1, "")
6362
scripts[1] = "ALTER TABLE test_1 ADD new_column TEXT;"
64-
lu.assertError(migration.up, "test_1.sql", scripts, 2)
63+
lu.assertError(migration.up, "databases/test_1.sql", scripts, 2)
6564

6665
--- Target version set to the same value as the current DB version
67-
spawn_db("test_1.sql", 1, test_db_schema)
68-
lu.assertEquals(migration.up("test_1.sql", scripts, 1), migration.retcode.ALREADY_UP_TO_DATE)
66+
spawn_db("databases/test_1.sql", 1, test_db_schema)
67+
lu.assertEquals(migration.up("databases/test_1.sql", scripts, 1), migration.retcode.ALREADY_UP_TO_DATE)
6968

7069
--- Target version set to the lower number than the current DB version
71-
spawn_db("test_1.sql", 2, test_db_schema)
72-
lu.assertEquals(migration.up("test_1.sql", scripts, 1), migration.retcode.WRONG_TARGET_VERSION)
70+
spawn_db("databases/test_1.sql", 2, test_db_schema)
71+
lu.assertEquals(migration.up("databases/test_1.sql", scripts, 1), migration.retcode.WRONG_TARGET_VERSION)
7372
end
7473

7574
function test_migration_down_success()
@@ -81,35 +80,35 @@ function test_migration_down_success()
8180
scripts[5] = "ALTER TABLE test_1 ADD new_column5 TEXT;"
8281

8382
--- Migrate from version 2 to 1
84-
spawn_db("test_1.sql", 2, test_db_schema)
85-
lu.assertEquals(migration.down("test_1.sql", scripts, 1), migration.retcode.OK)
86-
lu.assertEquals(migration.get_db_version("test_1.sql"), 1)
83+
spawn_db("databases/test_1.sql", 2, test_db_schema)
84+
lu.assertEquals(migration.down("databases/test_1.sql", scripts, 1), migration.retcode.OK)
85+
lu.assertEquals(migration.get_db_version("databases/test_1.sql"), 1)
8786

8887
-- Migrate from version 1 to 0
89-
lu.assertEquals(migration.down("test_1.sql", scripts, 0), migration.retcode.OK)
90-
lu.assertEquals(migration.get_db_version("test_1.sql"), 0)
88+
lu.assertEquals(migration.down("databases/test_1.sql", scripts, 0), migration.retcode.OK)
89+
lu.assertEquals(migration.get_db_version("databases/test_1.sql"), 0)
9190

9291
--- Migrate from version 5 to 0
93-
spawn_db("test_1.sql", 5, test_db_schema)
94-
lu.assertEquals(migration.down("test_1.sql", scripts, 0), migration.retcode.OK)
95-
lu.assertEquals(migration.get_db_version("test_1.sql"), 0)
92+
spawn_db("databases/test_1.sql", 5, test_db_schema)
93+
lu.assertEquals(migration.down("databases/test_1.sql", scripts, 0), migration.retcode.OK)
94+
lu.assertEquals(migration.get_db_version("databases/test_1.sql"), 0)
9695
end
9796

9897
function test_migration_down_errors()
9998
scripts = {}
10099

101100
--- Trigger DB error by trying to operate on empty database
102-
spawn_db("test_1.sql", 2, "")
101+
spawn_db("databases/test_1.sql", 2, "")
103102
scripts[1] = "ALTER TABLE test_1 ADD new_column TEXT;"
104-
lu.assertError(migration.down, "test_1.sql", scripts, 1)
103+
lu.assertError(migration.down, "databases/test_1.sql", scripts, 1)
105104

106105
--- Target version set to the same value as the current DB version
107-
spawn_db("test_1.sql", 1, test_db_schema)
108-
lu.assertEquals(migration.down("test_1.sql", scripts, 1), migration.retcode.ALREADY_UP_TO_DATE)
106+
spawn_db("databases/test_1.sql", 1, test_db_schema)
107+
lu.assertEquals(migration.down("databases/test_1.sql", scripts, 1), migration.retcode.ALREADY_UP_TO_DATE)
109108

110109
--- Target version set to the higher number than the current DB version
111-
spawn_db("test_1.sql", 2, test_db_schema)
112-
lu.assertEquals(migration.down("test_1.sql", scripts, 3), migration.retcode.WRONG_TARGET_VERSION)
110+
spawn_db("databases/test_1.sql", 2, test_db_schema)
111+
lu.assertEquals(migration.down("databases/test_1.sql", scripts, 3), migration.retcode.WRONG_TARGET_VERSION)
113112
end
114113

115114
function test_automatic_migration()
@@ -124,6 +123,13 @@ function test_automatic_migration()
124123
spawn_script("down.sql", "migrations", "test_2", 1, "delete from test_1 where _id=1;")
125124
spawn_script("down.sql", "migrations", "test_2", 2, "delete from test_1 where _id=2;")
126125

126+
migration.migrate("databases", "migrations", {
127+
test_1 = 0,
128+
test_2 = 0
129+
})
130+
lu.assertEquals(migration.get_db_version("databases/test_1.db"), 0)
131+
lu.assertEquals(migration.get_db_version("databases/test_2.db"), 0)
132+
127133
migration.migrate("databases", "migrations", {
128134
test_1 = 2,
129135
test_2 = 2

scripts/lua/restore.lua

+30-34
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ local migration = require('migration')
99
local restore = {}
1010

1111
local unpacked_backup_dir = paths.temp_dir .. "/backup"
12-
local version_file = unpacked_backup_dir .. "/" .. consts.version_file
13-
local legacy_version_file = unpacked_backup_dir .. "/" .. consts.legacy_version_file
1412

1513
restore.script_name = "restore.lua"
1614
restore.img_in_progress = "assets/gui_image_restore_in_progress.bin"
@@ -37,7 +35,7 @@ local function unpack_backup()
3735
ltar.unpack(paths.backup_file, unpacked_backup_dir)
3836
end
3937

40-
local function build_db_set(file)
38+
local function get_db_array_from_file(file)
4139
local contents = helpers.read_whole_file(file)
4240
local root = json.decode(contents)
4341
local set = {}
@@ -47,50 +45,48 @@ local function build_db_set(file)
4745
return set
4846
end
4947

50-
local function get_legacy_db_set()
51-
local set = {
52-
["calllog"] = 0,
53-
["sms"] = 0,
54-
["events"] = 0,
55-
["settings_v2"] = 0,
56-
["notes"] = 0,
57-
["custom_quotes"] = 0,
58-
["predefined_quotes"] = 0,
59-
["contacts"] = 0,
60-
["alarms"] = 0,
61-
["notifications"] = 0,
62-
["multimedia"] = 0
63-
}
48+
local function get_db_array_from_path(path)
49+
local set = {}
50+
for file in lfs.dir(path) do
51+
local file_path = path .. "/" .. file
52+
if file ~= "." and file ~= ".." then
53+
if lfs.attributes(file_path, "mode") == "file" then
54+
set[helpers.strip_from_extension(file)] = true;
55+
end
56+
end
57+
end
58+
return set
59+
end
60+
61+
local function build_db_set()
62+
local system_db_set = get_db_array_from_file(paths.version_file)
63+
local backup_db_set = get_db_array_from_path(unpacked_backup_dir)
64+
local set = {}
65+
for name, version in pairs(system_db_set) do
66+
if backup_db_set[name] then
67+
set[name] = tonumber(version)
68+
end
69+
end
6470
return set
6571
end
6672

6773
local function perform_db_migration()
6874
print("Performing database migration")
69-
local dbset = {}
70-
if helpers.exists(version_file) then
71-
dbset = build_db_set(version_file)
72-
else
73-
assert(helpers.exists(legacy_version_file))
74-
print("Legacy backup file, assuming legacy databases set")
75-
dbset = get_legacy_db_set()
76-
end
7775

78-
local result = migration.migrate(unpacked_backup_dir, paths.migration_scripts_dir, dbset)
76+
local result = migration.migrate(unpacked_backup_dir, paths.migration_scripts_dir, build_db_set())
7977
assert(result == migration.retcode.OK, string.format("Database migration process failed with %d", result))
8078
end
8179

8280
local function sync_databases()
8381
print("Syncing databases:")
84-
print(string.format("Replacing old databases: '%s' with the ones from '%s'", paths.db_dir, unpacked_backup_dir))
85-
86-
helpers.rm_files_from_dir(paths.db_dir)
87-
helpers.copy_dir(unpacked_backup_dir, paths.db_dir)
8882

89-
local version_file_path = paths.db_dir .. "/" .. consts.version_file
90-
if not helpers.exists(version_file_path) then
91-
version_file_path = paths.db_dir .. "/" .. consts.legacy_version_file
83+
for name, _ in pairs(build_db_set()) do
84+
local destination = paths.db_dir .. "/" .. name .. ".db"
85+
local source = unpacked_backup_dir .. "/" .. name .. ".db"
86+
print(string.format("Replacing '%s' with '%s'", destination, source));
87+
assert(os.remove(destination))
88+
helpers.copy_file(source, destination)
9289
end
93-
assert(os.remove(version_file_path))
9490
end
9591

9692
local function remove_cache()

scripts/lua/share/consts.lua

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
local consts = {}
22

33
consts.version_file = "version.json"
4-
consts.legacy_version_file = "backup.json" -- Pre-UDM backup package had version.json file named as backup.json
54
consts.indexer_cache_file = ".directory_is_indexed"
65

6+
local match = {}
7+
8+
-- Match only files with '.db' extensions and omit such files inside subdirectories
9+
match.only_db_files = '^[^%/]*%.db$'
10+
11+
consts.match = match
712
return consts

scripts/lua/share/helpers.lua

+9-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ function helpers.move_dir(from, where)
152152
if attr.mode == "directory" then
153153
assert(lfs.mkdir(build_path(where, name)))
154154
else
155-
assert(os.rename(build_path(from, name),build_path(where, name)))
155+
assert(os.rename(build_path(from, name), build_path(where, name)))
156156
end
157157
end
158158
end
@@ -235,6 +235,14 @@ function helpers.get_file_extension(file)
235235
return file:match("^.+(%..+)$")
236236
end
237237

238+
--- Strips file name from its extension
239+
-- @function strip_from_extension
240+
-- @param file file path
241+
-- @return file name without extension
242+
function helpers.strip_from_extension(file)
243+
return file:match("^(.*)%..*$")
244+
end
245+
238246
--- Create directory and all required subdirectories
239247
-- @function mkdirp
240248
-- @param file file path

scripts/lua/test/device/user/temp/recovery_status.json

-1
This file was deleted.

scripts/lua/test/restore/restore1.tar

1.74 MB
Binary file not shown.

scripts/lua/test/restore/restore2.tar

1.35 MB
Binary file not shown.

0 commit comments

Comments
 (0)