Skip to content

Commit

Permalink
Merge pull request #2139 from pi-hole/fix/migration
Browse files Browse the repository at this point in the history
Add new explicit migration command
  • Loading branch information
DL6ER authored Jan 9, 2025
2 parents 41db148 + 98494d1 commit f2c82da
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 79 deletions.
6 changes: 5 additions & 1 deletion src/api/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "config/password.h"
// database session functions
#include "database/session-table.h"
// FTLDBerror()
#include "database/common.h"

static uint16_t max_sessions = 0;
static struct session *auth_data = NULL;
Expand All @@ -51,7 +53,9 @@ void init_api(void)
log_crit("Could not allocate memory for API sessions, check config value of webserver.api.max_sessions");
exit(EXIT_FAILURE);
}
restore_db_sessions(auth_data, max_sessions);

if(!FTLDBerror())
restore_db_sessions(auth_data, max_sessions);
}

void free_api(void)
Expand Down
8 changes: 8 additions & 0 deletions src/api/teleporter.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,11 @@ static bool import_json_table(cJSON *json, struct teleporter_files *file)
return false;
}

// Set busy timeout to 1 second to access the database in a
// multi-threaded environment
if(sqlite3_busy_timeout(db, 1000) != SQLITE_OK)
log_warn("import_json_table(%s): Unable to set busy timeout: %s", file->filename, sqlite3_errmsg(db));

// Disable foreign key constraints
if(sqlite3_exec(db, "PRAGMA foreign_keys = OFF;", NULL, NULL, NULL) != SQLITE_OK)
{
Expand Down Expand Up @@ -834,6 +839,9 @@ static int process_received_tar_gz(struct ftl_conn *api, struct upload_data *dat
// Free allocated memory
free_upload_data(data);

// Migrate the config to v6
migrate_config_v6();

// Signal FTL we want to restart for re-import
api->ftl.restart_reason = "Teleporter (TAR.GZ) import";
api->ftl.restart = true;
Expand Down
11 changes: 9 additions & 2 deletions src/args.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ void parse_args(int argc, char *argv[])
}
}


// Set config option through CLI
if(argc == 2 && strcmp(argv[1], "--totp") == 0)
{
Expand All @@ -321,7 +320,6 @@ void parse_args(int argc, char *argv[])
exit(printTOTP());
}


// Create teleporter archive through CLI
if(argc == 2 && strcmp(argv[1], "--teleporter") == 0)
{
Expand Down Expand Up @@ -602,6 +600,15 @@ void parse_args(int argc, char *argv[])
exit(EXIT_SUCCESS);
}


// Set config option through CLI
if(argc == 3 && strcmp(argv[1], "migrate") == 0 && strcmp(argv[2], "v6") == 0)
{
cli_mode = true;
log_ctrl(false, true);
exit(migrate_config_v6() ? EXIT_SUCCESS : EXIT_FAILURE);
}

// start from 1, as argv[0] is the executable name
for(int i = 1; i < argc; i++)
{
Expand Down
160 changes: 100 additions & 60 deletions src/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1611,6 +1611,103 @@ static void reset_config_default(struct conf_item *conf_item)
}
}


/**
* @brief Determine and set default webserver ports if not imported from setupVars.conf.
*
* @param conf Pointer to the configuration structure.
*/
static void get_web_port(struct config *conf)
{
// Determine default webserver ports if not imported from setupVars.conf
if(config.webserver.port.f & FLAG_CONF_IMPORTED)
{
log_info("Webserver ports already imported from setupVars.conf, skipping default port detection");
return;
}

// else:
// Check if ports 80/TCP and 443/TCP are already in use
const in_port_t http_port = port_in_use(80) ? 8080 : 80;
const in_port_t https_port = port_in_use(443) ? 8443 : 443;

// Create a string with the default ports
// Allocate memory for the string
char *ports = calloc(32, sizeof(char));
if(ports == NULL)
{
log_err("Unable to allocate memory for default ports string");
return;
}
// Create the string
snprintf(ports, 32, "%d,%ds", http_port, https_port);

// Append IPv6 ports if IPv6 is enabled
const bool have_ipv6 = ipv6_enabled();
if(have_ipv6)
snprintf(ports + strlen(ports), 32 - strlen(ports),
",[::]:%d,[::]:%ds", http_port, https_port);

// Set default values for webserver ports
if(conf->webserver.port.t == CONF_STRING_ALLOCATED)
free(conf->webserver.port.v.s);
conf->webserver.port.v.s = ports;
conf->webserver.port.t = CONF_STRING_ALLOCATED;

log_info("Config initialized with webserver ports %d (HTTP) and %d (HTTPS), IPv6 support is %s",
http_port, https_port, have_ipv6 ? "enabled" : "disabled");
}

bool migrate_config_v6(void)
{
// Check if MIGRATION_TARGET_V6 exists and is a directory
// Ideally, this directory should be created by the installer but users
// may have deleted it manually and it is necessary for restoring
// Teleporter files
create_migration_target_v6();

// If the migration target does not exist, we need to migrate the config
log_info("Migrating config to Pi-hole v6.0 format");

// Initialize config with default values
initConfig(&config);

// If no previous config file could be read, we are likely either running
// for the first time or we are upgrading from a version prior to v6.0
// In this case, we try to read the legacy config files
const char *path = "";
if((path = readFTLlegacy(&config)) != NULL)
{
const char *target = MIGRATION_TARGET_V6"/pihole-FTL.conf";
log_info("Moving %s to %s", path, target);
if(rename(path, target) != 0)
log_warn("Unable to move %s to %s: %s", path, target, strerror(errno));
}
else
log_info("No legacy config file found, using defaults");

// Import bits and pieces from legacy config files
// setupVars.conf
importsetupVarsConf();
// 04-pihole-static-dhcp.conf
read_legacy_dhcp_static_config();
// 05-pihole-custom-cname.conf
read_legacy_cnames_config();
// custom.list
read_legacy_custom_hosts_config();

// Determine and set default webserver ports if not imported from
// setupVars.conf
get_web_port(&config);

// Initialize the TOML config file
writeFTLtoml(true);
write_dnsmasq_config(&config, false, NULL);
write_custom_list();

return true;
}

bool readFTLconf(struct config *conf, const bool rewrite)
{
// Initialize config with default values
Expand Down Expand Up @@ -1649,33 +1746,6 @@ bool readFTLconf(struct config *conf, const bool rewrite)
if(!rewrite)
return false;

// Check if MIGRATION_TARGET_V6 exists and is a directory
// Ideally, this directory should be created by the installer but users
// may have deleted it manually and it is necessary for restoring
// Teleporter files
create_migration_target_v6();

// If no previous config file could be read, we are likely either running
// for the first time or we are upgrading from a version prior to v6.0
// In this case, we try to read the legacy config files
const char *path = "";
if((path = readFTLlegacy(conf)) != NULL)
{
const char *target = MIGRATION_TARGET_V6"/pihole-FTL.conf";
log_info("Moving %s to %s", path, target);
if(rename(path, target) != 0)
log_warn("Unable to move %s to %s: %s", path, target, strerror(errno));
}
// Import bits and pieces from legacy config files
// setupVars.conf
importsetupVarsConf();
// 04-pihole-static-dhcp.conf
read_legacy_dhcp_static_config();
// 05-pihole-custom-cname.conf
read_legacy_cnames_config();
// custom.list
read_legacy_custom_hosts_config();

// When we reach this point but the FTL TOML config file exists, it may
// contain errors such as syntax errors, etc. We move it into a
// ".broken" location so it can be revisited later
Expand All @@ -1686,39 +1756,9 @@ bool readFTLconf(struct config *conf, const bool rewrite)
rename(GLOBALTOMLPATH, new_name);
}

// Determine default webserver ports if not imported from setupVars.conf
if(!(config.webserver.port.f & FLAG_CONF_IMPORTED))
{
// Check if ports 80/TCP and 443/TCP are already in use
const in_port_t http_port = port_in_use(80) ? 8080 : 80;
const in_port_t https_port = port_in_use(443) ? 8443 : 443;

// Create a string with the default ports
// Allocate memory for the string
char *ports = calloc(32, sizeof(char));
if(ports == NULL)
{
log_err("Unable to allocate memory for default ports string");
return false;
}
// Create the string
snprintf(ports, 32, "%d,%ds", http_port, https_port);

// Append IPv6 ports if IPv6 is enabled
const bool have_ipv6 = ipv6_enabled();
if(have_ipv6)
snprintf(ports + strlen(ports), 32 - strlen(ports),
",[::]:%d,[::]:%ds", http_port, https_port);

// Set default values for webserver ports
if(conf->webserver.port.t == CONF_STRING_ALLOCATED)
free(conf->webserver.port.v.s);
conf->webserver.port.v.s = ports;
conf->webserver.port.t = CONF_STRING_ALLOCATED;

log_info("Config initialized with webserver ports %d (HTTP) and %d (HTTPS), IPv6 support is %s",
http_port, https_port, have_ipv6 ? "enabled" : "disabled");
}
// Determine and set default webserver ports if not imported from
// setupVars.conf
get_web_port(&config);

// Initialize the TOML config file
writeFTLtoml(true);
Expand Down
1 change: 1 addition & 0 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ extern struct config config;
// Defined in config.c
void set_debug_flags(struct config *conf);
void set_all_debug(struct config *conf, const bool status);
bool migrate_config_v6(void);
bool readFTLconf(struct config *conf, const bool rewrite);
bool getLogFilePath(void);
struct conf_item *get_conf_item(struct config *conf, const unsigned int n);
Expand Down
Loading

0 comments on commit f2c82da

Please sign in to comment.