fix: add install container and copy config

This commit is contained in:
NickVs2015
2026-02-05 10:29:18 +03:00
parent 2c85e99129
commit c83e748def
4 changed files with 190 additions and 25 deletions
@@ -6,6 +6,8 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QUrl> #include <QUrl>
#include <QProcess>
#include <QSet>
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
#include <QJniObject> #include <QJniObject>
#include "platforms/android/android_controller.h" #include "platforms/android/android_controller.h"
@@ -601,6 +603,82 @@ void ServersBackupController::uploadBackupWithStrings(const QString &hostname,
uploadBackup(credentials, localPath, replaceMode); uploadBackup(credentials, localPath, replaceMode);
} }
QStringList ServersBackupController::scanBackupForContainers(const QString &localPath)
{
QStringList containers;
qDebug() << "Scanning backup file for containers:" << localPath;
// Для Android URI или обычного пути используем tar для просмотра содержимого
#ifdef Q_OS_ANDROID
QString actualPath = localPath;
if (localPath.startsWith("content://")) {
// Для Android URI нужно сначала прочитать файл
int fd = AndroidController::instance()->getFd(localPath);
if (fd < 0) {
qWarning() << "Failed to get file descriptor for Android URI";
return containers;
}
QFile file;
if (!file.open(fd, QIODevice::ReadOnly)) {
qWarning() << "Failed to open file from descriptor";
AndroidController::instance()->closeFd();
return containers;
}
QByteArray data = file.readAll();
file.close();
AndroidController::instance()->closeFd();
// Сохраняем во временный файл
actualPath = QDir::temp().filePath("backup_scan_temp.tgz");
QFile tempFile(actualPath);
if (!tempFile.open(QIODevice::WriteOnly)) {
qWarning() << "Failed to create temp file for scanning";
return containers;
}
tempFile.write(data);
tempFile.close();
}
#else
QString actualPath = localPath;
#endif
// Выполняем команду tar для просмотра содержимого
QProcess process;
process.start("tar", QStringList() << "-tzf" << actualPath);
process.waitForFinished(5000);
if (process.exitCode() != 0) {
qWarning() << "Failed to read backup archive:" << process.readAllStandardError();
return containers;
}
QString output = process.readAllStandardOutput();
QStringList lines = output.split('\n', Qt::SkipEmptyParts);
// Ищем директории контейнеров (amnezia-*)
QSet<QString> foundContainers;
for (const QString &line : lines) {
if (line.contains("amnezia-")) {
// Извлекаем имя контейнера из пути
QStringList parts = line.split('/');
for (const QString &part : parts) {
if (part.startsWith("amnezia-")) {
foundContainers.insert(part);
break;
}
}
}
}
containers = foundContainers.values();
qDebug() << "Found containers in backup:" << containers;
return containers;
}
void ServersBackupController::deleteBackup(const ServerCredentials &credentials, void ServersBackupController::deleteBackup(const ServerCredentials &credentials,
const QString &backupFilename) const QString &backupFilename)
{ {
@@ -131,6 +131,13 @@ public slots:
const QString &secretData, const QString &secretData,
const QString &localPath, const QString &localPath,
bool replaceMode = false); bool replaceMode = false);
/**
* @brief Сканировать backup файл и определить какие контейнеры в нем есть
* @param localPath Путь к локальному backup файлу
* @return Список имен контейнеров найденных в backup
*/
Q_INVOKABLE QStringList scanBackupForContainers(const QString &localPath);
/** /**
* @brief Удалить backup с сервера * @brief Удалить backup с сервера
@@ -178,22 +178,22 @@ PageType {
function onBackupRestored() { function onBackupRestored() {
// После успешного восстановления сканируем сервер для обновления информации о контейнерах console.log(" onBackupRestored, isFromSetupWizard:", isFromSetupWizard)
PageController.showBusyIndicator(false)
// Для setup wizard устанавливаем default container и сервер
if (isFromSetupWizard && ServersModel.getServersCount() > 0) { if (isFromSetupWizard && ServersModel.getServersCount() > 0) {
var serverIdx = ServersModel.getServersCount() - 1 var serverIdx = ServersModel.getServersCount() - 1
console.log(" Setting server as default:", serverIdx) console.log(" Setting server as default:", serverIdx)
ServersModel.setDefaultServerIndex(serverIdx) ServersModel.setDefaultServerIndex(serverIdx)
ServersModel.processedIndex = serverIdx ServersModel.processedIndex = serverIdx
// Сканируем сервер для обновления информации о контейнерах // Запускаем timer для установки default container
console.log(" Scanning server for installed containers...") // Контейнеры уже установлены через InstallController, просто ждем обновления модели
PageController.showNotificationMessage(qsTr("Updating container information...")) setDefaultContainerTimer.start()
InstallController.scanServerForInstalledContainers()
// Timer запустится автоматически после получения сигнала scanServerFinished
} else { } else {
console.log(" Skipping default container setup (not from wizard or no servers)") // Для обычного режима сразу переходим
PageController.showBusyIndicator(false)
navigateToRestoredPage() navigateToRestoredPage()
} }
} }
@@ -204,19 +204,7 @@ PageType {
} }
} }
Connections { // Удаляем Connections для scanServerFinished - больше не нужен
target: InstallController
function onScanServerFinished(isInstalledContainerFound) {
console.log("Scan finished, containers found:", isInstalledContainerFound)
// Если это setup wizard и сканирование завершено
if (isFromSetupWizard) {
// Запускаем timer для установки default container
setDefaultContainerTimer.start()
}
}
}
function navigateToRestoredPage() { function navigateToRestoredPage() {
// Переход на страницу успешного восстановления // Переход на страницу успешного восстановления
+95 -3
View File
@@ -25,19 +25,97 @@ PageType {
property string restoreSecretData: "" property string restoreSecretData: ""
property bool waitingForServerToAdd: false property bool waitingForServerToAdd: false
// Для установки контейнеров из backup
property var containersToInstall: []
property int currentContainerIndex: 0
property bool isInstallingContainers: false
// Connections для отслеживания добавления сервера // Connections для отслеживания добавления сервера
Connections { Connections {
target: InstallController target: InstallController
function onInstallServerFinished(finishedMessage) { function onInstallServerFinished(finishedMessage) {
if (root.waitingForServerToAdd && root.isRestoreFromBackup && root.backupFilePath.length > 0) { if (root.waitingForServerToAdd && root.isRestoreFromBackup && root.backupFilePath.length > 0) {
console.log("Server added successfully, now showing restore mode page") console.log("Server added successfully, now installing containers from backup...")
root.waitingForServerToAdd = false root.waitingForServerToAdd = false
// Запускаем переход на страницу восстановления // Сервер уже создан, устанавливаем флаг в false
navigationTimer.start() InstallController.setShouldCreateServer(false)
// Начинаем установку контейнеров
root.isInstallingContainers = true
installNextContainer()
} }
} }
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
if (root.isInstallingContainers) {
console.log("Container installed:", finishedMessage)
// Переходим к следующему контейнеру
root.currentContainerIndex++
if (root.currentContainerIndex < root.containersToInstall.length) {
// Устанавливаем следующий контейнер
installNextContainer()
} else {
// Все контейнеры установлены, теперь делаем restore
console.log("All containers installed, starting restore...")
root.isInstallingContainers = false
// ВАЖНО: Выключаем busy indicator перед переходом
PageController.showBusyIndicator(false)
// Запускаем переход на страницу выбора режима restore
navigationTimer.start()
}
}
}
}
// Функция для установки следующего контейнера из списка
function installNextContainer() {
if (root.currentContainerIndex >= root.containersToInstall.length) {
return
}
var containerName = root.containersToInstall[root.currentContainerIndex]
console.log("Installing container:", containerName, "(", root.currentContainerIndex + 1, "/", root.containersToInstall.length, ")")
// Конвертируем имя контейнера в DockerContainer enum
var dockerContainer = ContainerProps.containerFromString(containerName)
if (dockerContainer === 0) { // None
console.log("Unknown container:", containerName, "skipping...")
root.currentContainerIndex++
installNextContainer()
return
}
// Получаем default настройки для контейнера
var defaultProtocol = ContainerProps.defaultProtocol(dockerContainer)
var defaultPort = ProtocolProps.getPortForInstall(defaultProtocol)
var defaultTransport = ProtocolProps.defaultTransportProto(defaultProtocol)
// Показываем индикатор загрузки с сообщением
PageController.showBusyIndicator(true)
PageController.showNotificationMessage(qsTr("Installing %1 (%2/%3)...")
.arg(containerName)
.arg(root.currentContainerIndex + 1)
.arg(root.containersToInstall.length))
// Убеждаемся что credentials установлены
console.log("Setting credentials for container installation...")
InstallController.setProcessedServerCredentials(root.restoreHostname, root.restoreUsername, root.restoreSecretData)
// Устанавливаем индекс сервера
var serverIdx = ServersModel.getServersCount() - 1
ServersModel.processedIndex = serverIdx
// Устанавливаем контейнер
console.log("Calling InstallController.install for docker container:", dockerContainer)
ContainersModel.setProcessedContainerIndex(dockerContainer)
InstallController.install(dockerContainer, defaultPort, defaultTransport)
} }
// Таймер для перехода на страницу выбора режима после выбора файла // Таймер для перехода на страницу выбора режима после выбора файла
@@ -304,6 +382,20 @@ PageType {
root.backupFilePath = localPath root.backupFilePath = localPath
root.isRestoreFromBackup = true root.isRestoreFromBackup = true
// Сканируем backup для определения контейнеров
console.log("Scanning backup for containers...")
var foundContainers = ServersBackupController.scanBackupForContainers(localPath)
console.log("Found containers:", foundContainers)
if (foundContainers.length === 0) {
PageController.showErrorMessage(qsTr("No containers found in backup file"))
root.isRestoreFromBackup = false
return
}
root.containersToInstall = foundContainers
root.currentContainerIndex = 0
// Получаем credentials из PageSetupWizardCredentials через поиск в StackView // Получаем credentials из PageSetupWizardCredentials через поиск в StackView
var credentialsPage = null var credentialsPage = null
var item = root var item = root