442 lines
14 KiB
C++
Executable File
442 lines
14 KiB
C++
Executable File
/*
|
|
* @RDE_HEADER@
|
|
* <short description>
|
|
* $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 <ngldb/dbconnection.h>
|
|
#include <ngldb/nsqlquery.h>
|
|
#include <nglsettings/nglsettings_settings.h>
|
|
#include <ngltools/ngltools_filesystem.h>
|
|
|
|
#include <QMessageBox>
|
|
#include <QTimer>
|
|
#include <QMenu>
|
|
#include <QSettings>
|
|
#include <QDir>
|
|
#include <QNetworkInterface>
|
|
#include <QHostInfo>
|
|
|
|
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<int, QProcess::ExitStatus>::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<QSettings> 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<int, QProcess::ExitStatus>::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<int, QProcess::ExitStatus>::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<int, QProcess::ExitStatus>::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<int, QProcess::ExitStatus>::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<QPushButton*> l = findChildren<QPushButton*>();
|
|
for (QPushButton *pb : l)
|
|
pb->setEnabled(bEnable);
|
|
}
|
|
{
|
|
const QList<QAction*> l = findChildren<QAction*>();
|
|
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<QHostAddress> 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
|