From bef0d4fe12932160dbb51f69fb39c70ad3097480 Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Mon, 30 Oct 2023 15:25:49 +0100 Subject: [PATCH] Refactor the update process: streamline code. When WAIT button is not active, the a clone or a fix of a defunct repository is possible, but not more. If WAIT button is active, the at least the opkg_commnds are executed. If there are chenged files, they are handkled as wll. --- worker.cpp | 315 ++++++++++++++++++++++++++--------------------------- 1 file changed, 152 insertions(+), 163 deletions(-) diff --git a/worker.cpp b/worker.cpp index 19f8b7b..a1ac0ef 100644 --- a/worker.cpp +++ b/worker.cpp @@ -234,19 +234,23 @@ bool Worker::isRepositoryCorrupted() { bool Worker::repairCorruptedRepository() { QDir customerRepository(m_customerRepository); if (!customerRepository.removeRecursively()) { + Utils::printCriticalErrorMsg("ERROR REMOVING CORR. CUST-REPOSITORY"); - m_updateStatus = UpdateStatus(UPDATE_STATUS::REMOVE_GIT_REPOSITORY_FAILED, - QString("REMOVAL OF GIT-REPOSITORY %1 FAILED").arg(m_customerRepository)); - IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, - QString("#M=APISM#C=CMD_EVENT#J=") + - m_ismasClient.sanityCheckFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR, - m_updateStatus.m_statusDescription)); - emit showErrorMessage("apism sanity check", m_updateStatus.m_statusDescription); + + //m_updateStatus = UpdateStatus(UPDATE_STATUS::REMOVE_GIT_REPOSITORY_FAILED, + // QString("REMOVAL OF GIT-REPOSITORY %1 FAILED").arg(m_customerRepository)); + //IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, + // QString("#M=APISM#C=CMD_EVENT#J=") + + // m_ismasClient.sanityCheckFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR, + // m_updateStatus.m_statusDescription)); + //emit showErrorMessage("apism sanity check", m_updateStatus.m_statusDescription); + return false; } return true; } +#if 0 int Worker::sendCloneAndCheckoutFailure() { m_updateStatus = UpdateStatus(UPDATE_STATUS::GIT_CLONE_AND_CHECKOUT_FAILURE, QString("CLONE OR CHECKOUT FAILED: ") + m_customerRepository); @@ -360,20 +364,21 @@ int Worker::sendFoundFilesToUpdateSuccess() { } int Worker::sendUpdateSucceededAndActivated() { - IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, - QString("#M=APISM#C=CMD_EVENT#J=") + - m_ismasClient.updateOfPSASucceeded("")); + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::UPDATE_SUCCEEDED)); + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::UPDATE_ACTIVATED)); + //IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, + // QString("#M=APISM#C=CMD_EVENT#J=") + + // m_ismasClient.updateOfPSASucceeded("")); //m_ismasClient.setProgressInPercent(100); // mark update as activated -> this resets the WAIT button - IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, - QString("#M=APISM#C=CMD_EVENT#J=") + - m_ismasClient.updateOfPSAActivated()); + //IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, + // QString("#M=APISM#C=CMD_EVENT#J=") + + // m_ismasClient.updateOfPSAActivated()); return UPDATE_SUCCESS_AND_ACTIVATED; } - int Worker::sendFinalResult() { m_updateStatus = UpdateStatus(UPDATE_STATUS::UPDATE_PROCESS_SUCCESS, QString("Update process succeeded. Reset WAIT.")); @@ -386,49 +391,61 @@ int Worker::sendFinalResult() { return 0; } +#endif + void Worker::privateUpdate() { if (!m_mainWindow) { Utils::printCriticalErrorMsg("m_mainWindow NOT SET"); return; } + QString func(__PRETTY_FUNCTION__); + GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::STARTED)); - m_updateProcessRunning = true; - bool sentIsmasLastVersionNotification = false; - - emit disableExit(); - - m_returnCode = -1; - startProgressLoop(); + QScopedPointer upr(new UpdateProcessRunning(this)); QDir customerRepository(m_customerRepository); QDir customerRepositoryEtc(QDir::cleanPath(m_customerRepository + QDir::separator() + "etc/")); CONSOLE() << UPDATE_STEP::CHECK_SANITY; - bool initialClone = false; // the customer repository is cloned without - // checking the ISMAS-trigger (WAIT-)button. - // but if there was a sane repository - // available, then the trigger-button must + m_clone = false; + m_repairClone = false; + m_initialClone = false; + // the customer repository is cloned or + // repaired/re-cloned without checking the + // ISMAS-trigger (WAIT-)button. + + // Case 1: no existing repository: + + // if there was a sane repository + // available, then the trigger-button is + // checked: + // 1: trigger == WAIT: then // have been activated in ISMAS. bool continueUpdate = true; // check if git-clone command has timed-out, // resulting in a corrupted git-repository, which // does not contain an ./etc-directory - if (isRepositoryCorrupted()) { + + if (isRepositoryCorrupted()) { // a not-existing repository is not meant + // to be corrupted CONSOLE() << UPDATE_STEP::CHECK_SANITY_FAILURE; if ((continueUpdate = repairCorruptedRepository()) == true) { + m_repairClone = true; CONSOLE() << UPDATE_STEP::REPOSITORY_RECOVERED_SUCCESS; } else { - CONSOLE() << UPDATE_STEP::REPOSITORY_RECOVERED_FAILURE; + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::REPOSITORY_RECOVERED_FAILURE)); + return; } - } else { - CONSOLE() << UPDATE_STEP::CHECK_SANITY_SUCCESS; } + CONSOLE() << UPDATE_STEP::CHECK_SANITY_SUCCESS; + if (continueUpdate) { if ((continueUpdate = customerRepository.exists()) == false) { + m_initialClone = (m_repairClone == false); GUI() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY); for (int i = 0; i < 5; ++i) { // try to checkout git repository setProgress(i); // and switch to branch @@ -436,7 +453,7 @@ void Worker::privateUpdate() { if (!isRepositoryCorrupted()) { GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY_SUCCESS)); continueUpdate = true; - initialClone = true; + m_clone = true; break; } } @@ -444,155 +461,127 @@ void Worker::privateUpdate() { } if (continueUpdate == false) { - GUI() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY_FAILURE); + GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CLONE_REPOSITORY_FAILURE)); + return; } + Q_ASSERT_X(m_clone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "clone failed"); + } else { + Q_ASSERT_X(!m_clone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "m_clone not false"); + Q_ASSERT_X(!m_initialClone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "m_initialClone not false"); + Q_ASSERT_X(!m_repairClone, (func + QString(":%1").arg(__LINE__)).toStdString().c_str(), "m_repairClone not false"); + CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY; if (isRepositoryCorrupted()) { - CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY_FAILURE; - continueUpdate = false; - } else { - CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY_SUCCESS; + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY_FAILURE)); + return; } } - } // repository is existent and not corrupted. - // check now if the ISMAS-trigger (WAIT-button) - if (continueUpdate) { // is activated even in case of initial checkout - if ((continueUpdate = updateTriggerSet()) == false) { - // if (initialClone) { - // - //} - m_returnCode = sendIsmasTriggerFailure(); - } - if (continueUpdate) { // configure customer environment -> checkout - // branch in case someone has change the zone_nr - //qDebug() << UPDATE_STEP::CHECK_ISMAS_TRIGGER; - if ((continueUpdate = customerEnvironment(30)) == false) { - m_returnCode = sendCustomerEnvironmentConfigurationFailed(); - } // determine which files has to be updated: - } // either sent to the hardware or rsynced with - if (continueUpdate) { // the filesystem in case of tariff-files - //qDebug() << UPDATE_STEP::CHECKED_OUT_BRANCH; - if ((continueUpdate = filesToUpdate(50)) == false) { - m_returnCode = sendPullFailure(); - } - } // send message to ISMAS about files which have - if (continueUpdate) { // been checked in into git repository - //qDebug() << UPDATE_STEP::COMPUTE_FILES_TO_UPDATE; - sendFoundFilesToUpdateSuccess(); - if ((continueUpdate = updateFiles(60)) == false) { - m_returnCode = sendFileUpdateFailure(); - } - } - if (continueUpdate) { // rsync (changed) files to file system - //qDebug() << UPDATE_STEP::DOWNLOAD_FILES_TO_UPDATE; - // TODO: rsync das komplette repository - if ((continueUpdate = syncCustomerRepositoryAndFS(70)) == false) { - m_returnCode = sendRsyncFailure(); - } - } - if (continueUpdate) { // send message to ISMAS about installed versions - //qDebug() << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY; - if ((continueUpdate = sendIsmasLastVersionNotification(80)) == false) { - m_returnCode = sendLastVersionFailure(); - } - } - if (continueUpdate) { // future use: save logs of update process - sentIsmasLastVersionNotification = true; - if ((continueUpdate = saveLogFile(90)) == false) { - m_returnCode = sendSaveLogFilesFailure(); - } - } // send message to ISMAS that update process - if (continueUpdate) { // succeeded - //qDebug() << UPDATE_STEP::UPDATE_SUCCESS; - sendUpdateSucceededAndActivated(); - m_returnCode = UPDATE_SUCCESS_AND_ACTIVATED; - } - - setProgress(100); - - if (m_returnCode != 0) { - stopProgressLoop(); - emit appendText(QString("UPDATE "), UPDATE_STEP_FAIL); - } else { - emit appendText(QString("UPDATE "), UPDATE_STEP_SUCCESS); - sendFinalResult(); - } } + CONSOLE() << UPDATE_STEP::CHECK_REPOSITORY_SUCCESS; - if (!sentIsmasLastVersionNotification) { - // try even if the backend is not connected - sendIsmasLastVersionNotification(100); - } - stopProgressLoop(); - - m_updateProcessRunning = false; - emit enableExit(); - emit restartExitTimer(); -} - -std::optional Worker::getApismVersion() { - for (int repeat = 0; repeat < 10; ++repeat) { - qInfo() << "REPEAT" << repeat << "In getApismVersion() -> #M=APISM#C=REQ_SELF#J={}"; - std::optional result - = IsmasClient::sendRequestReceiveResponse( - IsmasClient::APISM::DIRECT_PORT, "#M=APISM#C=REQ_SELF#J={}"); - if (result) { - QString msg = result.value(); - qInfo() << "In getApismVersion() -> APISM response" << msg; - QJsonParseError parseError; - QJsonDocument document(QJsonDocument::fromJson(msg.toUtf8(), &parseError)); - if (parseError.error != QJsonParseError::NoError) { - qCritical() << "(1) INVALID JSON MSG: PARSING FAILED (msg=" << msg << "):" - << parseError.error << parseError.errorString(); - m_updateStatus = UpdateStatus(UPDATE_STATUS::JSON_PARSE_FAILURE, - QString("(2) INVALID JSON %1 %2 %3") - .arg(msg) - .arg(parseError.error) - .arg(parseError.errorString())); - IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, - QString("#M=APISM#C=CMD_EVENT#J=") + - m_ismasClient.jsonParseFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR, - m_updateStatus.m_statusDescription)); - return std::nullopt; - } - if (!document.isObject()) { - qCritical() << "FILE IS NOT A JSON OBJECT!"; - m_updateStatus = UpdateStatus(UPDATE_STATUS::JSON_PARSE_FAILURE, - QString("NOT A JSON-OBJECT %1").arg(msg)); - IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, - QString("#M=APISM#C=CMD_EVENT#J=") + - m_ismasClient.jsonParseFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR, - m_updateStatus.m_statusDescription)); - return std::nullopt; - } - QJsonObject obj = document.object(); - QStringList keys = obj.keys().filter("CMD_GET_APISMSTATUS_RESPONSE"); - if (keys.size() != 1) { - m_updateStatus = UpdateStatus(UPDATE_STATUS::BACKEND_CHECK_FAILURE, - "CMD_GET_APISMSTATUS_RESPONSE KEY NOT AVAILABLE"); - IsmasClient::sendRequestReceiveResponse(IsmasClient::APISM::DB_PORT, - QString("#M=APISM#C=CMD_EVENT#J=") + - m_ismasClient.sanityCheckFailed(IsmasClient::RESULT_CODE::INSTALL_ERROR, - m_updateStatus.m_statusDescription)); - emit showErrorMessage("apism response", m_updateStatus.m_statusDescription); - return std::nullopt; - } else { - QString const key = keys.at(0); - QJsonValue v = obj.value(key); - return v.toObject().value("Version").toString(); - } - } else { - QThread::sleep(1); + //////////////////////////////////////////////////////////////////////////// + // + // CHECK UPDATE TRIGGER + // + //////////////////////////////////////////////////////////////////////////// + m_ismasTriggerActive = false; + if ((continueUpdate = updateTriggerSet()) == false) { + if (m_initialClone) { + GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::INITIAL_CLONE_WITHOUT_ACTIVE_ISMAS_TRIGGER)); } + return; + } else { + GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::INITIAL_CLONE_WITH_ACTIVE_ISMAS_TRIGGER)); } - return std::nullopt; + if (m_ismasTriggerActive == false) {// make it explicit again: only if the + // ismas trigger is active ('WAIT'), + // then proceed + return; + } + GUI() << (ISMAS() << (CONSOLE() << UPDATE_STEP::CHECK_ISMAS_TRIGGER_SUCCESS)); + + + //////////////////////////////////////////////////////////////////////////// + // + // CHECK-OUT BRANCH + // + //////////////////////////////////////////////////////////////////////////// + if ((continueUpdate = customerEnvironment()) == false) { + return; + } + CONSOLE() << UPDATE_STEP::CHECKOUT_BRANCH_SUCCESS; + + + //////////////////////////////////////////////////////////////////////////// + // + // COMPUTE CHANGED FILES OF CUSTOMER REPOSITORY + // + //////////////////////////////////////////////////////////////////////////// + if ((continueUpdate = filesToUpdate()) == false) { + return; + } + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::UPDATE_REPOSITORY_SUCCESS)); + + + //////////////////////////////////////////////////////////////////////////// + // + // UPDATE THE PSA USING THE CHANGED FILES + // + //////////////////////////////////////////////////////////////////////////// + if ((continueUpdate = updateFiles()) == false) { + return; + } + GUI() << (CONSOLE() << UPDATE_STEP::APPLY_REPOSITORY_CHANGES_SUCCESS); + + + //////////////////////////////////////////////////////////////////////////// + // + // (R)SYNC THE REPOSITORY WITH THE LOCAL FILEYSTEM + // + //////////////////////////////////////////////////////////////////////////// + if ((continueUpdate = syncCustomerRepositoryAndFS()) == false) { + return; + } + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::SYNC_CUSTOMER_REPOSITORY_SUCCESS)); + + + //////////////////////////////////////////////////////////////////////////// + // + // FUTURE: SAVE LOG FILES + // + //////////////////////////////////////////////////////////////////////////// + if ((continueUpdate = saveLogFile()) == false) { + return; + } + // ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::SAVE_LOGS_SUCCESS)); + + + //////////////////////////////////////////////////////////////////////////// + // + // FINAL MESSAGES (PART 1) + // + //////////////////////////////////////////////////////////////////////////// + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::UPDATE_SUCCEEDED)); + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::UPDATE_ACTIVATED)); + ISMAS() << (GUI() << (CONSOLE() << UPDATE_STEP::FINISHED)); + + + //////////////////////////////////////////////////////////////////////////// + // + // FINAL MESSAGES (PART 2): SEND-LAST-VERSION + // (destructor of struct UpdateProcessRunning) + // + //////////////////////////////////////////////////////////////////////////// } bool Worker::updateTriggerSet() { + // repository is existent and not corrupted. check now if the ISMAS-trigger + // (WAIT-button) is activated even in case of initial checkout + static const QString func = "UPDATE-TRIGGER-SET"; if (m_withoutIsmasDirectPort) { // useful for testing return true;