/* * @RDE_HEADER@ * * $Id$ * $HeadURL$ * $Author$ * Created by Malte Schröder, SLSE, 2016-06-08 */ #include "db_administration.h" #include "ui_db_administration.h" #include "server_databases_model.h" #include "local_databases_model.h" #include "settings.h" #include #include #include #include #include #include #include #include #include #include #include namespace DBAdministration { DBAdministration::DBAdministration(QWidget *parent) : QMainWindow(parent) , m_ui(new Ui::DBAdministration) , m_proc(nullptr) , m_progressDialog(nullptr) , m_timer(nullptr) , m_menuBar(new QMenuBar(this)) , m_showLog(new ShowLogFile) , m_copyExercise(new CopyExercise(getLogger("CopyExercise"), CopyExercise::CopyForEvaluation, this)) , m_bRunsOnEvaluationServer(checkRunsOnEvaluationServer()) , m_logger(getLogger("DBAdministration")) { m_ui->setupUi(this); m_serverDatabasesModel = new ServerDatabasesModel(this); m_proxyModelServer = new ServerDatabasesProxyModel(this); m_proxyModelServer->setSourceModel(m_serverDatabasesModel); m_ui->tableViewServerDatabases->setModel(m_proxyModelServer); m_localDatabasesModel = new LocalDatabasesModel(this); m_proxyModelLocal = new LocalDatabasesProxyModel(this); m_proxyModelLocal->setSourceModel(m_localDatabasesModel); m_ui->tableViewLocalDatabases->setModel(m_proxyModelLocal); connect(m_ui->pbCopy, &QPushButton::clicked, this, &DBAdministration::onCopyButtonClicked); connect(m_ui->pbClose, &QPushButton::clicked, this, &DBAdministration::onClosedClicked); connect(m_ui->pbRemove, &QPushButton::clicked, this, &DBAdministration::onRemoveClicked); connect(m_ui->pbActivate, &QPushButton::clicked, this, &DBAdministration::onActivateClicked); connect(m_ui->tableViewServerDatabases->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DBAdministration::enaDisa); connect(m_ui->tableViewLocalDatabases->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DBAdministration::enaDisa); setWindowTitle(QLatin1String("DBAdministration")); connect(m_ui->actionShow, &QAction::triggered, this, &DBAdministration::onShowLogFile); connect(m_ui->actionStart, &QAction::triggered, this, &DBAdministration::onStartApp); connect(m_ui->actionStop, &QAction::triggered, this, &DBAdministration::onStopApp); connect(m_copyExercise, &CopyExercise::copyDbFailed, this, &DBAdministration::onCopyDbFailed); connect(m_copyExercise, &CopyExercise::copyDbFinished, this, &DBAdministration::onCopyDbFinished); m_ui->actionStart->setEnabled(m_bRunsOnEvaluationServer); m_ui->actionStop->setEnabled(m_bRunsOnEvaluationServer); m_ui->menuService_Management->setEnabled(m_bRunsOnEvaluationServer); enaDisa(); } DBAdministration::~DBAdministration() { delete m_ui; delete m_serverDatabasesModel; delete m_progressDialog; delete m_timer; delete m_menuBar; delete m_showLog; if (m_proc) m_proc->deleteLater(); } bool DBAdministration::init() { if (!m_copyExercise->init(0, Settings::serverDatabaseHost(), Settings::serverDatabaseName(), Settings::evaluationDatabaseHost(), Settings::evaluationDatabaseName())) return false; m_serverDatabasesModel->initModel(m_copyExercise->serverDb()); m_localDatabasesModel->initModel(m_copyExercise->evaluationDb()); m_ui->tableViewServerDatabases->resizeColumnsToContents(); m_ui->tableViewLocalDatabases->resizeColumnsToContents(); return true; } void DBAdministration::onClosedClicked() { close(); } void DBAdministration::onRemoveClicked() { disableButtons(); m_localDatabaseToRemove = m_localDatabasesModel->getRowData(m_ui->tableViewLocalDatabases->currentIndex().row()); QString strMsg = QStringLiteral("Do you really want to remove the database '%1'?").arg (m_localDatabaseToRemove.dbName); int result = QMessageBox::question(this, tr("Remove Database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (result == QMessageBox::No) { enableButtons(); return; } DEBUG_LOG(m_logger) << "onRemoveClicked: dbName = " << m_localDatabaseToRemove.dbName; const QStringList args({QStringLiteral("-U"), QStringLiteral("postgres"), QStringLiteral("-h"), Settings::evaluationDatabaseHost(), m_localDatabaseToRemove.dbName }); QString errStr; const QString exePath = NGL::postgresExecutablePath(QStringLiteral("dropdb"), errStr); if (!errStr.isEmpty()) WARNING_LOG(m_logger) << errStr; handleProcInit(exePath, args); connect(m_proc, QOverload::of(&QProcess::finished), this, &DBAdministration::onDropDbFinished); // start process m_proc->start(); } void DBAdministration::onActivateClicked() { LocalExercise le = m_localDatabasesModel->getRowData(m_ui->tableViewLocalDatabases->currentIndex().row()); QString strMsg = QStringLiteral("Do you really want to active database '%1'?").arg(le.dbName); int result = QMessageBox::question(this, tr("Activate Database"), strMsg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (result == QMessageBox::No) return; DEBUG_LOG(m_logger) << "onActivateClicked: dbName = " << le.dbName; QString configFileName = QStringLiteral("/lts-cc.conf"); QString filename; QScopedPointer settings; filename = QDir::homePath() + configFileName; if (QFile::exists(filename)) { settings.reset(new QSettings(filename, QSettings::Format::IniFormat)); } else { #ifdef Q_OS_UNIX filename = QStringLiteral("/etc") + configFileName; #else filename = QCoreApplication::applicationDirPath() + QLatin1String("\\") + configFileName; #endif if (QFile::exists(filename)) { settings.reset(new QSettings(filename, QSettings::Format::IniFormat)); } else // fallback settings.reset(new QSettings(QLatin1String("RDE"), QLatin1String("LTS-CC"))); } ERROR_LOG(m_logger) << "FileName: " << filename; settings->setValue(QStringLiteral("Global") + QStringLiteral("/DatabaseName"), le.dbName); } void DBAdministration::enaDisa() { if (!m_ui) return; int selected = m_ui->tableViewServerDatabases->selectionModel()->selectedRows().size(); m_ui->pbCopy->setEnabled(selected > 0); selected = m_ui->tableViewLocalDatabases->selectionModel()->selectedRows().size(); m_ui->pbRemove->setEnabled(selected > 0); m_ui->pbActivate->setEnabled(selected > 0 && m_bRunsOnEvaluationServer); } void DBAdministration::onCopyButtonClicked() { disableButtons(); auto exercise = m_serverDatabasesModel->getRowData(m_proxyModelServer->mapToSource(m_ui->tableViewServerDatabases->currentIndex()).row()); m_copyExercise->doCopy(exercise.id); if (!m_progressDialog) m_progressDialog = new QProgressDialog(this); m_progressDialog->setLabelText(tr("Copying database...")); m_progressDialog->setMinimum(0); m_progressDialog->setMaximum(0); m_progressDialog->show(); } void DBAdministration::onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus) { INFO_LOG(m_logger) << "onDropDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus; bool bRemoveLocal = true; if (exitCode > 0) { const QString str = QString::fromLocal8Bit(m_proc->readAllStandardError()) + QLatin1Char('\n') + QString::fromLocal8Bit(m_proc->readAllStandardOutput()); ERROR_LOG(m_logger) << "Can not drop database: " << str; QString db0 = QLatin1String("ERROR: database \"")+m_localDatabaseToRemove.dbName+QLatin1String("\" does not exist"); if (!str.contains(db0)) { bRemoveLocal = false; QMessageBox::critical(this, tr ("Remove Database"), tr("Database cannot be removed:\n%1.").arg(str), QMessageBox::Ok); } } if (bRemoveLocal) { NSqlQuery q(m_copyExercise->evaluationDb()); QString stmt = QStringLiteral("DELETE FROM local_databases WHERE id = ") + QString::number(m_localDatabaseToRemove.id); if (!q.exec(stmt)) QMessageBox::critical(this, tr ("Remove Database"), tr("Database entry cannot be removed."), QMessageBox::Ok); else { m_localDatabasesModel->initModel(m_copyExercise->evaluationDb()); m_ui->tableViewLocalDatabases->resizeColumnsToContents(); } m_localDatabaseToRemove = LocalExercise(); } enableButtons(); } void DBAdministration::onErrorOccured(QProcess::ProcessError error) { ERROR_LOG(m_logger) << "error: " << error; } void DBAdministration::incrementProgressBar() { m_progressDialog->setValue(m_progressDialog->value()+1); } void DBAdministration::onShowLogFile() { ERROR_LOG(m_logger) << "IN onShowLogFile"; if (!m_showLog->init()) { QMessageBox::critical(this, tr ("Show Logfile"), tr("Logfile does not exist."), QMessageBox::Ok); return; } m_showLog->show(); } void DBAdministration::onStartApp() { if (!m_bRunsOnEvaluationServer) return; handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")}); connect(m_proc, QOverload::of(&QProcess::finished), this, &DBAdministration::onPsauxFinished); m_proc->start(); } void DBAdministration::onPsauxFinished() { enableButtons(); QByteArray output = m_proc->readAllStandardOutput(); if (output.contains("svcServiceManagement")) { ERROR_LOG(m_logger) << "ServiceManagement already started"; QMessageBox::critical(this, tr ("Service Management"), tr("Service Management already started."), QMessageBox::Ok); } else { ERROR_LOG(m_logger) << "Start svcServiceManagement"; handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-z")}); connect(m_proc, QOverload::of(&QProcess::finished), this, &DBAdministration::onStartAppFinished); m_proc->start(); } } void DBAdministration::onStartAppFinished(int exitCode, QProcess::ExitStatus exitStatus) { handleProcFinished(exitCode, exitStatus); } void DBAdministration::onStopApp() { if (!m_bRunsOnEvaluationServer) return; disableButtons(); handleProcInit(QStringLiteral("ps"), {QStringLiteral("aux")}); connect(m_proc, QOverload::of(&QProcess::finished), this, &DBAdministration::onPsauxStopFinished); m_proc->start(); } void DBAdministration::onPsauxStopFinished() { enableButtons(); QByteArray output = m_proc->readAllStandardOutput(); if (output.contains("svcServiceManagement")) { ERROR_LOG(m_logger) << "ServiceManagement started - stopping"; handleProcInit(QCoreApplication::applicationDirPath() + QStringLiteral("/svcServiceManagement"), {QStringLiteral("-s")}); connect(m_proc, QOverload::of(&QProcess::finished), this, &DBAdministration::onStopAppFinished); m_proc->start(); } else { QMessageBox::critical(this, tr("Service Management"), tr("Service Management already stopped."), QMessageBox::Ok); ERROR_LOG(m_logger) << "ServiceManagement already stopped"; } } void DBAdministration::onStopAppFinished(int exitCode, QProcess::ExitStatus exitStatus) { handleProcFinished(exitCode, exitStatus); } void DBAdministration::onCopyDbFailed() { QMessageBox::critical(this, tr ("Exercise"), tr("Could not copy exercise - maybe the exercise already exists."), QMessageBox::Ok); enableButtons(); m_progressDialog->hide(); } void DBAdministration::onCopyDbFinished() { m_localDatabasesModel->initModel(m_copyExercise->evaluationDb()); m_ui->tableViewLocalDatabases->resizeColumnsToContents(); enableButtons(); m_progressDialog->hide(); } void DBAdministration::handleProcInit(const QString &program, const QStringList &args) { if (m_proc) { m_proc->disconnect(this); m_proc->deleteLater(); } m_proc = new QProcess(this); NOTICE_LOG(m_logger) << "Starting process '" << program << "' with args '" << args.join(QLatin1Char(' ')) << "'"; m_proc->setProgram(program); m_proc->setArguments(args); connect(m_proc, &QProcess::errorOccurred, this, &DBAdministration::onErrorOccured); disableButtons(); } void DBAdministration::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus) { enableButtons(); if (!m_proc) return; if (exitCode != 0 || exitStatus != 0) { QByteArray out = m_proc->readAllStandardError(); if (!out.isEmpty()) out += '\n'; out += m_proc->readAllStandardOutput(); ERROR_LOG(m_logger) << "Process finished - exitCode: " << exitCode << ", exitStatus = " << exitStatus << ", " << out; QMessageBox::critical(this, tr ("Execute process"), tr("Error executing process, exitCode: %1, exitStatus: %2, output: %3") .arg(exitCode).arg(exitStatus).arg(QString::fromLocal8Bit(out)), QMessageBox::Ok); } m_proc->disconnect(this); m_proc->deleteLater(); m_proc = nullptr; } void DBAdministration::enaDisaButtons(bool bEnable) { { const QList l = findChildren(); for (QPushButton *pb : l) pb->setEnabled(bEnable); } { const QList l = findChildren(); for (QAction *a : l) a->setEnabled(bEnable); } if (bEnable) enaDisa(); } bool DBAdministration::checkRunsOnEvaluationServer() const { const QHostInfo hostInfoEvaluationDb = QHostInfo::fromName(Settings::evaluationDatabaseHost()); const auto evaluationDbAddresses = hostInfoEvaluationDb.addresses(); if (hostInfoEvaluationDb.addresses().isEmpty()) return false; // we don't know better ... const QList addresses = QNetworkInterface::allAddresses(); for (const QHostAddress &address : addresses) { if (address.isLoopback() || address.isNull()) continue; if (address.protocol() != QAbstractSocket::IPv4Protocol) continue; for (const QHostAddress &evaluationAddress : evaluationDbAddresses) if (address.isEqual(evaluationAddress)) return true; } return false; } } // namespace DBAdministration