mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-23 02:00:20 +07:00
fix: add install container and copy config
This commit is contained in:
@@ -6,6 +6,8 @@
|
||||
#include <QStandardPaths>
|
||||
#include <QTemporaryFile>
|
||||
#include <QUrl>
|
||||
#include <QProcess>
|
||||
#include <QSet>
|
||||
#ifdef Q_OS_ANDROID
|
||||
#include <QJniObject>
|
||||
#include "platforms/android/android_controller.h"
|
||||
@@ -601,6 +603,82 @@ void ServersBackupController::uploadBackupWithStrings(const QString &hostname,
|
||||
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,
|
||||
const QString &backupFilename)
|
||||
{
|
||||
|
||||
@@ -131,6 +131,13 @@ public slots:
|
||||
const QString &secretData,
|
||||
const QString &localPath,
|
||||
bool replaceMode = false);
|
||||
|
||||
/**
|
||||
* @brief Сканировать backup файл и определить какие контейнеры в нем есть
|
||||
* @param localPath Путь к локальному backup файлу
|
||||
* @return Список имен контейнеров найденных в backup
|
||||
*/
|
||||
Q_INVOKABLE QStringList scanBackupForContainers(const QString &localPath);
|
||||
|
||||
/**
|
||||
* @brief Удалить backup с сервера
|
||||
|
||||
@@ -178,22 +178,22 @@ PageType {
|
||||
|
||||
function onBackupRestored() {
|
||||
|
||||
// После успешного восстановления сканируем сервер для обновления информации о контейнерах
|
||||
console.log(" onBackupRestored, isFromSetupWizard:", isFromSetupWizard)
|
||||
|
||||
PageController.showBusyIndicator(false)
|
||||
|
||||
// Для setup wizard устанавливаем default container и сервер
|
||||
if (isFromSetupWizard && ServersModel.getServersCount() > 0) {
|
||||
var serverIdx = ServersModel.getServersCount() - 1
|
||||
console.log(" Setting server as default:", serverIdx)
|
||||
ServersModel.setDefaultServerIndex(serverIdx)
|
||||
ServersModel.processedIndex = serverIdx
|
||||
|
||||
// Сканируем сервер для обновления информации о контейнерах
|
||||
console.log(" Scanning server for installed containers...")
|
||||
PageController.showNotificationMessage(qsTr("Updating container information..."))
|
||||
InstallController.scanServerForInstalledContainers()
|
||||
|
||||
// Timer запустится автоматически после получения сигнала scanServerFinished
|
||||
// Запускаем timer для установки default container
|
||||
// Контейнеры уже установлены через InstallController, просто ждем обновления модели
|
||||
setDefaultContainerTimer.start()
|
||||
} else {
|
||||
console.log(" Skipping default container setup (not from wizard or no servers)")
|
||||
PageController.showBusyIndicator(false)
|
||||
// Для обычного режима сразу переходим
|
||||
navigateToRestoredPage()
|
||||
}
|
||||
}
|
||||
@@ -204,19 +204,7 @@ PageType {
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: InstallController
|
||||
|
||||
function onScanServerFinished(isInstalledContainerFound) {
|
||||
console.log("Scan finished, containers found:", isInstalledContainerFound)
|
||||
|
||||
// Если это setup wizard и сканирование завершено
|
||||
if (isFromSetupWizard) {
|
||||
// Запускаем timer для установки default container
|
||||
setDefaultContainerTimer.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
// Удаляем Connections для scanServerFinished - больше не нужен
|
||||
|
||||
function navigateToRestoredPage() {
|
||||
// Переход на страницу успешного восстановления
|
||||
|
||||
@@ -25,19 +25,97 @@ PageType {
|
||||
property string restoreSecretData: ""
|
||||
property bool waitingForServerToAdd: false
|
||||
|
||||
// Для установки контейнеров из backup
|
||||
property var containersToInstall: []
|
||||
property int currentContainerIndex: 0
|
||||
property bool isInstallingContainers: false
|
||||
|
||||
// Connections для отслеживания добавления сервера
|
||||
Connections {
|
||||
target: InstallController
|
||||
|
||||
function onInstallServerFinished(finishedMessage) {
|
||||
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
|
||||
|
||||
// Запускаем переход на страницу восстановления
|
||||
navigationTimer.start()
|
||||
// Сервер уже создан, устанавливаем флаг в false
|
||||
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.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
|
||||
var credentialsPage = null
|
||||
var item = root
|
||||
|
||||
Reference in New Issue
Block a user