diff --git a/client/core/defs.h b/client/core/defs.h index 3f8614012..2a0f9191a 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -32,6 +32,7 @@ enum ErrorCode ServerContainerMissingError, ServerDockerFailedError, ServerCancelInstallation, + ServerUserNotInSudo, // Ssh connection errors SshSocketError, SshTimeoutError, SshProtocolError, diff --git a/client/core/errorstrings.cpp b/client/core/errorstrings.cpp index 1e7eb3958..274e0efd8 100644 --- a/client/core/errorstrings.cpp +++ b/client/core/errorstrings.cpp @@ -16,6 +16,7 @@ QString errorString(ErrorCode code){ case(ServerContainerMissingError): return QObject::tr("Server error: Docker container missing"); case(ServerDockerFailedError): return QObject::tr("Server error: Docker failed"); case(ServerCancelInstallation): return QObject::tr("Installation canceled by user"); + case(ServerUserNotInSudo): return QObject::tr("The user does not have permission to use sudo"); // Ssh connection errors case(SshSocketError): return QObject::tr("Ssh connection error"); diff --git a/client/core/scripts_registry.cpp b/client/core/scripts_registry.cpp index d33881a24..1b379ea13 100644 --- a/client/core/scripts_registry.cpp +++ b/client/core/scripts_registry.cpp @@ -32,6 +32,7 @@ QString amnezia::scriptName(SharedScriptType type) case SharedScriptType::setup_host_firewall: return QLatin1String("setup_host_firewall.sh"); case SharedScriptType::check_connection: return QLatin1String("check_connection.sh"); case SharedScriptType::check_server_is_busy: return QLatin1String("check_server_is_busy.sh"); + case SharedScriptType::check_user_in_sudo: return QLatin1String("check_user_in_sudo.sh"); } } diff --git a/client/core/scripts_registry.h b/client/core/scripts_registry.h index 9528d763c..b30be2ff9 100644 --- a/client/core/scripts_registry.h +++ b/client/core/scripts_registry.h @@ -16,7 +16,8 @@ enum SharedScriptType { remove_all_containers, setup_host_firewall, check_connection, - check_server_is_busy + check_server_is_busy, + check_user_in_sudo }; enum ProtocolScriptType { // Protocol scripts diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index c0f6adae7..35b150f2d 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -416,11 +416,19 @@ ErrorCode ServerController::setupContainer(const ServerCredentials &credentials, //qDebug().noquote() << QJsonDocument(config).toJson(); ErrorCode e = ErrorCode::NoError; + disconnectFromHost(credentials); + + e = isUserInSudo(credentials, container); + if (e) return e; + if (!isUpdate) { e = isServerPortBusy(credentials, container, config); if (e) return e; } + e = isServerDpkgBusy(credentials, container); + if (e) return e; + e = installDockerWorker(credentials, container); if (e) return e; qDebug().noquote() << "ServerController::setupContainer installDockerWorker finished"; @@ -536,37 +544,6 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent stdOut += data + "\n"; }; - QFutureWatcher watcher; - - QFuture future = QtConcurrent::run([this, &stdOut, &cbReadStdOut, &cbReadStdErr, &credentials]() { - do { - if (m_cancelInstallation) { - return ErrorCode::ServerCancelInstallation; - } - stdOut.clear(); - runScript(credentials, - replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), - genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); - if (!stdOut.isEmpty() || stdOut.contains("Unable to acquire the dpkg frontend lock")) { - emit serverIsBusy(true); - QThread::msleep(1000); - } - } while (!stdOut.isEmpty()); - return ErrorCode::NoError; - }); - - QEventLoop wait; - QObject::connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); - watcher.setFuture(future); - wait.exec(); - - m_cancelInstallation = false; - emit serverIsBusy(false); - - if (future.result() != ErrorCode::NoError) { - return future.result(); - } - ErrorCode error = runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); @@ -895,6 +872,64 @@ ErrorCode ServerController::isServerPortBusy(const ServerCredentials &credential return ErrorCode::NoError; } +ErrorCode ServerController::isUserInSudo(const ServerCredentials &credentials, DockerContainer container) +{ + QString stdOut; + auto cbReadStdOut = [&](const QString &data, QSharedPointer proc) { + stdOut += data + "\n"; + }; + auto cbReadStdErr = [&](const QString &data, QSharedPointer ) { + stdOut += data + "\n"; + }; + + const QString scriptData = amnezia::scriptData(SharedScriptType::check_user_in_sudo); + ErrorCode error = runScript(credentials, replaceVars(scriptData, genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); + + if (!stdOut.contains("sudo")) return ErrorCode::ServerUserNotInSudo; + + return error; +} + +ErrorCode ServerController::isServerDpkgBusy(const ServerCredentials &credentials, DockerContainer container) +{ + QString stdOut; + auto cbReadStdOut = [&](const QString &data, QSharedPointer proc) { + stdOut += data + "\n"; + }; + auto cbReadStdErr = [&](const QString &data, QSharedPointer ) { + stdOut += data + "\n"; + }; + + QFutureWatcher watcher; + + QFuture future = QtConcurrent::run([this, &stdOut, &cbReadStdOut, &cbReadStdErr, &credentials]() { + do { + if (m_cancelInstallation) { + return ErrorCode::ServerCancelInstallation; + } + stdOut.clear(); + runScript(credentials, + replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), + genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); + if (!stdOut.isEmpty() || stdOut.contains("Unable to acquire the dpkg frontend lock")) { + emit serverIsBusy(true); + QThread::msleep(1000); + } + } while (!stdOut.isEmpty()); + return ErrorCode::NoError; + }); + + QEventLoop wait; + QObject::connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); + watcher.setFuture(future); + wait.exec(); + + m_cancelInstallation = false; + emit serverIsBusy(false); + + return future.result(); +} + ErrorCode ServerController::getAlreadyInstalledContainers(const ServerCredentials &credentials, QMap &installedContainers) { QString stdOut; diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index 94ab4efc2..156959b8f 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -84,7 +84,10 @@ private: ErrorCode runContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); ErrorCode configureContainerWorker(const ServerCredentials &credentials, DockerContainer container, QJsonObject &config); ErrorCode startupContainerWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config = QJsonObject()); + ErrorCode isServerPortBusy(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config); + ErrorCode isUserInSudo(const ServerCredentials &credentials, DockerContainer container); + ErrorCode isServerDpkgBusy(const ServerCredentials &credentials, DockerContainer container); std::shared_ptr m_settings; std::shared_ptr m_configurator; diff --git a/client/resources.qrc b/client/resources.qrc index 67937bdaf..924e1406a 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -165,5 +165,6 @@ ui/qml/Controls/PopupWithQuestion.qml ui/qml/Pages/PageAdvancedServerSettings.qml ui/qml/Controls/PopupWarning.qml + server_scripts/check_user_in_sudo.sh diff --git a/client/server_scripts/check_user_in_sudo.sh b/client/server_scripts/check_user_in_sudo.sh new file mode 100644 index 000000000..e7ee953cd --- /dev/null +++ b/client/server_scripts/check_user_in_sudo.sh @@ -0,0 +1,2 @@ +CUR_USER=$(whoami);\ +groups $CUR_USER \ No newline at end of file