From c503750e903cfc6b8fa2c8e4e3281408a511feaa Mon Sep 17 00:00:00 2001 From: Gerhard Hoffmann Date: Mon, 17 Jul 2023 16:43:05 +0200 Subject: [PATCH] Simplified interface of ctor. onHandleChangedFiles(): split handling of opkg_commands-file and downloading of DC/JSON-Files. rsync to file-system only once these operations were successful. --- worker.cpp | 254 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 174 insertions(+), 80 deletions(-) diff --git a/worker.cpp b/worker.cpp index 762ff17..049795b 100644 --- a/worker.cpp +++ b/worker.cpp @@ -18,25 +18,67 @@ #include "ismas/ismas_client.h" #include "apism/apism_client.h" -Worker::Worker(hwinf *hw, QString update_ctrl_file, QString repositoryPath, - QString customerId, QString branchName, QString workingDirectory, bool maintenanceMode, - bool testMode, bool executeScriptOnly, bool dryRun, QObject *parent, - char const *serialInterface, char const *baudrate) +int Worker::read1stLineOfFile(QString fileName) { + QFile f(fileName); + if (f.exists()) { + if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&f); + in.setCodec("UTF-8"); + while(!in.atEnd()) { + return in.readLine().toInt(); + } + } + } + return -1; +} + +Worker::Worker(hwinf *hw, + int customerNr, + int machineNr, + int zoneNr, + QString branchName, + QString workingDirectory, + bool maintenanceMode, + bool dryRun, + QObject *parent, + char const *serialInterface, + char const *baudrate) : m_workerThread("workerThread") , m_apismClient(0, 0, 0, this) // TODO - , m_gc(repositoryPath, customerId, workingDirectory, branchName, this) - , m_customerId(customerId) + , m_customerNr(customerNr) + , m_customerNrStr(QString("customer_") + QString::number(m_customerNr).rightJustified(3, '0')) + , m_machineNr(machineNr) + , m_zoneNr(zoneNr) , m_workingDirectory(workingDirectory) , m_branchName(branchName) - , m_customerRepository(QDir::cleanPath(m_workingDirectory - + QDir::separator() - + m_customerId)) + , m_customerRepository(QDir::cleanPath(m_workingDirectory + QDir::separator() + m_customerNrStr)) + , m_gc(m_customerNrStr, m_customerRepository, m_workingDirectory, m_branchName, this) , m_maintenanceMode(maintenanceMode) + , m_osVersion(getOsVersion()) , m_ismasUpdateRequests(ISMAS_UPDATE_REQUESTS) , m_waitForNewUpdates(this) { - this->moveToThread(&m_workerThread); - //m_apismClient.moveToThread(&m_workerThread); + QDir::setCurrent(m_workingDirectory); + + qInfo() << "CURRENT TIME ..............." << QDateTime::currentDateTime().toString(Qt::ISODate); + qInfo() << "OS VERSION ................." << m_osVersion; + qInfo() << "CUSTOMER_NR ................" << m_customerNr; + qInfo() << "CUSTOMER_NR_STR ............" << m_customerNrStr; + qInfo() << "CUSTOMER_REPOSITORY_PATH ..." << QString("https://git.mimbach49.de/GerhardHoffmann/%1.git").arg(m_customerNrStr); + qInfo() << "CUSTOMER_REPOSITORY ........" << m_customerRepository; + qInfo() << "MACHINE_NR ................." << m_machineNr; + qInfo() << "ZONE_NR ...................." << m_zoneNr; + qInfo() << "BRANCH_NAME ................" << m_branchName; + qInfo() << "WORKING_DIRECTORY .........." << m_workingDirectory; + + QProcess p; + p.start("/bin/systemctl", {"restart", "apism"}); + if (!p.waitForStarted(5000) || !p.waitForFinished(5000)) { + qCritical() << "APISM-RESTART-FAILURE"; + return; + } + + this->moveToThread(&m_workerThread); m_workerThread.start(); int cnt = 0; @@ -48,18 +90,8 @@ Worker::Worker(hwinf *hw, QString update_ctrl_file, QString repositoryPath, QThread::sleep(1); } - m_update = new Update(hw, update_ctrl_file, repositoryPath, customerId, - branchName, workingDirectory, - maintenanceMode, testMode, executeScriptOnly, dryRun, - parent, serialInterface, baudrate); - connect(&m_apismClient, SIGNAL(ismasResponseAvailable(QJsonObject)), this, SLOT(onIsmasResponseReceived(QJsonObject))); - - connect(this, SIGNAL(executeOpkgCommands(QStringList)), this, - SLOT(onExecuteOpkgCommands(QStringList)), Qt::QueuedConnection); - connect(this, SIGNAL(executeOpkgCommand(QString)), this, - SLOT(onExecuteOpkgCommand(QString)), Qt::QueuedConnection); connect(this, SIGNAL(summarizeRepositoryStatus()), this, SLOT(onSummarizeRepositoryStatus()), Qt::QueuedConnection); connect(this, SIGNAL(sendCmdSendVersionToIsmas()), this, @@ -73,16 +105,24 @@ Worker::Worker(hwinf *hw, QString update_ctrl_file, QString repositoryPath, connect(this, SIGNAL(terminateUpdateProcess()), this, SLOT(onTerminateUpdateProcess()), Qt::QueuedConnection); - //connect(this, SIGNAL(workNow()), this, SLOT(work()), Qt::QueuedConnection); - connect(&m_startUpdateProcess, SIGNAL(timeout()), this, SLOT(askIsmasForNewData()), Qt::QueuedConnection); - m_startUpdateProcess.setSingleShot(true); - m_startUpdateProcess.start(1000); + QDir customerRepository(m_customerRepository); + if (!customerRepository.exists()) { + if (m_gc.gitCloneAndCheckoutBranch()) { + // do nothing else, not even executing opkg-commands + onFinishUpdateProcess(false); + } + } else { + m_update = new Update(hw, m_customerRepository, m_customerNrStr, + m_branchName, m_workingDirectory, + dryRun, parent, serialInterface, baudrate); - connect(&m_waitForNewUpdates, SIGNAL(timeout()), this, SLOT(askIsmasForNewData()), Qt::QueuedConnection); - m_waitForNewUpdates.setSingleShot(false); + connect(&m_startUpdateProcess, SIGNAL(timeout()), this, SLOT(askIsmasForNewData()), Qt::QueuedConnection); + m_startUpdateProcess.setSingleShot(true); + m_startUpdateProcess.start(1000); - m_machineNr = 996; - m_customerNr = 281; + connect(&m_waitForNewUpdates, SIGNAL(timeout()), this, SLOT(askIsmasForNewData()), Qt::QueuedConnection); + m_waitForNewUpdates.setSingleShot(false); + } } Worker::~Worker() { @@ -101,39 +141,81 @@ Worker::~Worker() { } } +QString Worker::getOsVersion() const { + QString const cmd = QString("echo -n $(cat /etc/os-release | head -n 1 | cut -d'\"' -f2 | tr -d '\"')"); + Command c("bash"); + if (c.execute(m_workingDirectory, QStringList() << "-c" << cmd)) { + return c.getCommandResult(); + } + return "N/A"; +} + void Worker::onHandleChangedFiles(QStringList changedFiles) { qCritical() << QDir::currentPath() << "ON HANDLE CHANGED FILES" << changedFiles; - if (QDir(m_customerRepository).exists()) { - if (QDir::setCurrent(m_customerRepository)) { - QString const params("--recursive " - "--progress " - "--checksum " - "--exclude=.* " - "--include=*.bin " - "--include=*.json " - "--include=opkg_commands " - "--include=*.ini"); - QStringList cmds; - cmds << QString("rsync ") + params.simplified() + " etc/ /etc"; - cmds << QString("rsync ") + params.simplified() + " opt/ /opt"; - QString cmd; - bool error = false; - foreach (cmd, cmds) { - if (!error) { - Command c("bash"); - qInfo() << "EXCUTING CMD..." << cmd; - if (c.execute(m_customerRepository, QStringList() << "-c" << cmd)) { - qDebug() << c.getCommandResult(); - } else { - qCritical() << "CMD" << cmd << "FAILED"; - error = true; - } + QString opkg_commands; + static const QRegularExpression re("^.*opkg_commands\\s*$"); + static const QRegularExpression comment("^\\s*#.*$"); + int idx = changedFiles.indexOf(re); + if (idx != -1) { + m_updateStatus = UPDATE_STATUS::EXEC_OPKG_COMMANDS_REQUEST; + m_statusDescription = "EXECUTE OPKG COMMANDS"; + + opkg_commands = changedFiles.takeAt(idx); + + QFile f(opkg_commands); + if (f.open(QIODevice::ReadOnly)) { + QTextStream in(&f); + while (!in.atEnd()) { + QString line = in.readLine(); + if (line.indexOf(comment, 0) == -1) { + // found opkg command + QString opkgCommand = line.trimmed(); + executeOpkgCommand(opkgCommand); } } - if (!error) { - onFinishUpdateProcess(true); - return; + } + + // m_updateStatus = UPDATE_STATUS::EXEC_OPKG_COMMANDS_SUCCESS; + // m_statusDescription = QString("EXECUTE OPKG COMMANDS %1 OK").arg(opkgCommands.join('\n')); + + f.close(); + } + + if (m_update->doUpdate(changedFiles)) { // first update the hardware + // then sync the file-system + if (QDir(m_customerRepository).exists()) { + if (QDir::setCurrent(m_customerRepository)) { + QString const params("--recursive " + "--progress " + "--checksum " + "--exclude=.* " + "--include=*.bin " + "--include=*.json " + "--include=opkg_commands " + "--include=*.ini"); + QStringList cmds; + cmds << QString("rsync ") + params.simplified() + " etc/ /etc"; + cmds << QString("rsync ") + params.simplified() + " opt/ /opt"; + + QString cmd; + bool error = false; + foreach (cmd, cmds) { + if (!error) { + Command c("bash"); + qInfo() << "EXCUTING CMD..." << cmd; + if (c.execute(m_customerRepository, QStringList() << "-c" << cmd)) { + qDebug() << c.getCommandResult(); + } else { + qCritical() << "CMD" << cmd << "FAILED"; + error = true; + } + } + } + if (!error) { + onFinishUpdateProcess(true); + return; + } } } } @@ -191,24 +273,22 @@ void Worker::onSummarizeRepositoryStatus() { */ } -void Worker::onExecuteOpkgCommands(QStringList opkgCommands) { - QString opkgCommand; - foreach (opkgCommand, opkgCommands) { - emit this->executeOpkgCommand(opkgCommand); - } -} - -void Worker::onExecuteOpkgCommand(QString opkgCommand) { +void Worker::executeOpkgCommand(QString opkgCommand) { Command c(opkgCommand); if (c.execute(m_workingDirectory)) { QString const r = c.getCommandResult(); - qDebug() << opkgCommand << ": RESULT" << r; + m_updateStatus = UPDATE_STATUS::EXEC_OPKG_COMMAND_SUCCESS; + m_statusDescription = QString("EXECUTE OPKG COMMAND %1 OK").arg(opkgCommand); + } else { + m_updateStatus = UPDATE_STATUS::EXEC_OPKG_COMMAND_FAILURE; + m_statusDescription = QString("EXECUTE OPKG COMMAND %1 FAILED").arg(opkgCommand); + onTerminateUpdateProcess(); + return; } } // sollte ParameterResponse heissen void Worker::onIsmasResponseReceived(QJsonObject ismasResponse) { - if (!ismasResponse.isEmpty()) { QStringList const keys = ismasResponse.keys(); static QRegularExpression re("^REQ_ISMASPARAMETER.*"); @@ -225,32 +305,44 @@ void Worker::onIsmasResponseReceived(QJsonObject ismasResponse) { int customerNr = c.toInt(-1); int machineNr = m.toInt(-1); if (customerNr != m_customerNr) { - qCritical() << "CUSTOMER-NR (" << customerNr << ") !=" - << "LOCAL CUSTOMER-NR (" << m_customerNr << ")"; - m_updateStatus = UPDATE_STATUS::ERROR_BACKEND; + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_FAILURE; + m_statusDescription + = QString("CUSTOMER-NR (%1) != LOCAL CUSTOMER-NR (%2)") + .arg(customerNr).arg(m_customerNr); return; } if (machineNr != m_machineNr) { - qCritical() << "MACHINE-NR (" << machineNr << ") !=" - << "LOCAL MACHINE-NR (" << m_machineNr << ")"; - m_updateStatus = UPDATE_STATUS::ERROR_BACKEND; + m_statusDescription + = QString("MACHINE-NR (%1) != LOCAL MACHINE-NR (%2)") + .arg(machineNr).arg(m_machineNr); + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_FAILURE; return; } } } + // TODO: check if zone_nr is correct + if (keys.contains("Fileupload", Qt::CaseInsensitive)) { QJsonObject fileUpload = ismasResponse["Fileupload"].toObject(); QJsonValue v = fileUpload.value("TRG"); if (!v.isNull() && !v.isUndefined()) { QString const s = v.toString(""); if (s == "WAIT") { + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_SUCCESS; m_ismasUpdateRequests = ISMAS_UPDATE_REQUESTS; - qCritical() << "ISMAS UPDATES AVAILABLE"; + m_statusDescription = "ISMAS UPDATES AVAILABLE"; emit m_gc.ismasUpdatesAvailable(); } } + } else { + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_FAILURE; + m_statusDescription = "NO FILEUPLOAD KEY AVAILABLE"; + return; } } + } else { + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_FAILURE; + m_statusDescription = "NO ISMAS RESPONSE AVAILABLE (EMPTY)"; } } @@ -274,7 +366,7 @@ void Worker::onSendCmdSendVersionToIsmas() { int tariffZone = 1; QString const tariffInfo = "test_tariff_info"; QString const tariffLoadTime = QDateTime::currentDateTime().toString(Qt::ISODateWithMs); - QString const linuxVersion = "test_linux_version"; + // QString const linuxVersion = "test_linux_version"; QString const cpuSerial = "test_cpu_serial"; QString const deviceControllerVersion = "test_dc_version"; QString const deviceControllerGitBlob = "test_dc_blob_2a3b4f50"; @@ -296,7 +388,7 @@ void Worker::onSendCmdSendVersionToIsmas() { tariffZone, tariffInfo, tariffLoadTime, - linuxVersion, + m_osVersion, cpuSerial, deviceControllerVersion, deviceControllerGitBlob, @@ -317,17 +409,19 @@ void Worker::onSendCmdSendVersionToIsmas() { void Worker::askIsmasForNewData() { if (m_maintenanceMode) { + m_updateStatus = UPDATE_STATUS::ISMAS_EMULATE_DATA_AVAILABLE; QString data = m_ismasClient.setUpdatesAvailable(); - m_apismClient.sendUpdateInfoToIsmas(data); + m_apismClient.emulateUpdatesAvailable(data); } + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_PENDING; m_apismClient.requestAvailableIsmasUpdates(); if (--m_ismasUpdateRequests > 0) { // if the timer is already running, it will be stopped and restarted. m_waitForNewUpdates.start(10000); + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_PENDING; } else { - qCritical() << "REQUESTING ISMAS FOR UPDATES TIMED OUT"; - m_workerThread.quit(); - QApplication::quit(); + m_updateStatus = UPDATE_STATUS::ISMAS_UPDATE_REQUEST_TIMEOUT; + onTerminateUpdateProcess(); } }