From f6628b1b0ba4281cfe6362da393f21560cf360ac Mon Sep 17 00:00:00 2001 From: Oliver Kraitschy Date: Mon, 15 Oct 2018 16:02:57 +0200 Subject: [PATCH] [update-config] Store and restore original UCI configuration Fixes #72 --- .../files/sbin/openwisp-update-config.lua | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/openwisp-config/files/sbin/openwisp-update-config.lua b/openwisp-config/files/sbin/openwisp-update-config.lua index 66daab8..f8825f7 100755 --- a/openwisp-config/files/sbin/openwisp-update-config.lua +++ b/openwisp-config/files/sbin/openwisp-update-config.lua @@ -27,11 +27,13 @@ test_root_dir = working_dir .. '/update-test' remote_dir = openwisp_dir .. '/remote' remote_config_dir = remote_dir .. '/etc/config' stored_dir = openwisp_dir .. '/stored' +stored_config_dir = stored_dir .. '/etc/config' added_file = openwisp_dir .. '/added.list' modified_file = openwisp_dir .. '/modified.list' get_standard = function() return uci.cursor(standard_config_dir) end get_remote = function() return uci.cursor(remote_config_dir, '/tmp/openwisp/.uci') end get_check = function() return uci.cursor(check_config_dir, '/tmp/openwisp/.uci') end +get_stored = function() return uci.cursor(stored_config_dir, '/tmp/openwisp/.uci') end -- uci cursors standard = get_standard() @@ -62,24 +64,46 @@ end -- update UCI configuration -- (overwrite or merge) +stored = get_stored() -- remove config items added via openwisp-config if lfs.attributes(remote_config_dir, 'mode') == 'directory' then for file in lfs.dir(remote_config_dir) do local standard_path = standard_config_dir .. '/' .. file if lfs.attributes(standard_path, 'mode') == 'file' then for key, section in pairs(remote:get_all(file)) do - -- search section in the downloaded configuration - local section_check = check:get(file, section['.name']) - -- remove section from current configuration if not in downloaded configuration - if section_check == nil then - utils.remove_uci_options(standard, file, section) + -- if section has been removed in the new configuration + if check:get(file, section['.name']) == nil then + -- search section in the backup configuration + local section_stored = stored:get_all(file, section['.name']) + -- section is not in the backup configuration -> remove + if section_stored == nil then + utils.remove_uci_options(standard, file, section) + -- section is in the backup configuration -> restore + -- delete all options first + else + for option, value in pairs(section) do + if not utils.starts_with_dot(option) then + standard:delete(file, section['.name'], option) + end + end + utils.write_uci_section(standard, file, section_stored) + end + -- if section still exists in the new configuration else - -- compare each option in current and downloaded configuration + -- compare each option in current with new configuration for option, value in pairs(section) do if not utils.starts_with_dot(option) then - -- remove option from current configuration if not in downloaded configuration + -- if option has been removed in the new configuration if check:get(file, section['.name'], option) == nil then - standard:delete(file, section['.name'], option) + -- search option in the backup configuration + local value_stored = stored:get(file, section['.name'], option) + if value_stored == nil then + -- option is not in the backup configuration -> remove + standard:delete(file, section['.name'], option) + else + -- option is in the backup configuration -> restore + standard:set(file, section['.name'], option, value_stored) + end end end end @@ -105,6 +129,7 @@ os.execute('rm -rf '..check_dir) os.execute('rm -rf '..remote_dir) os.execute('mkdir -p '..remote_dir) os.execute('tar -zxf '..downloaded_conf..' -C '..remote_dir) +os.execute('mkdir -p '..stored_config_dir) -- reload uci cursors standard = get_standard() remote = get_remote() @@ -114,8 +139,13 @@ if lfs.attributes(remote_config_dir, 'mode') == 'directory' then for file in lfs.dir(remote_config_dir) do local standard_path = standard_config_dir .. '/' .. file local remote_path = remote_config_dir .. '/' .. file + local stored_path = stored_config_dir .. '/' .. file -- ensure we are acting on a file if lfs.attributes(remote_path, 'mode') == 'file' then + -- if there's no backup of the file yet, create one + if not utils.file_exists(stored_path) then + os.execute('cp '..standard_path..' '..stored_path) + end -- MERGE mode if MERGE then -- avoid "file does not exist" error