/* * @RDE_HEADER@ * Copy exercise from server to evaluation server * $Id$ * $HeadURL$ * $Author$ * Created by Christian Ehrlicher, NLSE, 2018-07-31 */ #include "copy_database.h" #include #include #include #include #include #include #include #include namespace OcBaseDownload { CopyDatabase::CopyDatabase(NGL::INGLLogger &logger, QObject *parent) : QObject(parent) , m_proc(nullptr) , m_logger(logger) {} bool CopyDatabase::init(const QString &dbHost, const QString &srcDbName, const QString &dstDbName) { m_dbHost = dbHost; m_srcDbName = srcDbName; m_dstDbName = dstDbName; return true; } bool CopyDatabase::doCopy() { if (!runPgDump()) { ERROR_LOG(m_logger) << "Error running pg_dump"; emit copyDbFailed(); return false; } return true; } bool CopyDatabase::dropDatabase(const QString &dbName) { return runDropDb(dbName); } bool CopyDatabase::runDropDb(const QString &dbName) { const QStringList args({QStringLiteral("-U"), QStringLiteral("postgres"), QStringLiteral("--if-exists"), QStringLiteral("-h"), m_dbHost, dbName}); handleProcInit(executablePath(QStringLiteral("dropdb")), args); connect(m_proc, QOverload::of(&QProcess::finished), this, &CopyDatabase::onDropDbFinished); m_proc->start(); return true; } void CopyDatabase::onDropDbFinished(int exitCode, QProcess::ExitStatus exitStatus) { NOTICE_LOG(m_logger) << "onDropDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus; if (exitCode > 0) { ERROR_LOG(m_logger) << "DropDb failed"; emit dropDatabaseFailed(); return; } emit dropDatabaseFinished(); } bool CopyDatabase::runPgDump() { // start process const QStringList args( { QStringLiteral("--column-inserts"), QStringLiteral("-U"), QStringLiteral("postgres"), QStringLiteral("-f"), getDumpFile(), QStringLiteral("-h"), m_dbHost, m_srcDbName }); handleProcInit(executablePath(QStringLiteral("pg_dump")), args); connect(m_proc, QOverload::of(&QProcess::finished), this, &CopyDatabase::onPgDumpFinished); m_proc->start(); return true; } void CopyDatabase::onPgDumpFinished(int exitCode, QProcess::ExitStatus exitStatus) { NOTICE_LOG(m_logger) << "onProcessFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus; runCreatedb(); } void CopyDatabase::runCreatedb() { const QStringList args({QStringLiteral("-U"), QStringLiteral("postgres"), QStringLiteral("-h"), m_dbHost, m_dstDbName}); handleProcInit(executablePath(QStringLiteral("createdb")), args); connect(m_proc, QOverload::of(&QProcess::finished), this, &CopyDatabase::onCreateDbFinished); m_proc->start(); } void CopyDatabase::onCreateDbFinished(int exitCode, QProcess::ExitStatus exitStatus) { NOTICE_LOG(m_logger) << "onCreateDbFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus; if (exitCode > 0) { ERROR_LOG(m_logger) << "CreateDB failed"; emit copyDbFailed(); return; } runGrant(); //runPgLoad(); } void CopyDatabase::runGrant() { const QString command = QStringLiteral("-c 'GRANT ALL ON DATABASE %1 to ets_exm'").arg(m_dstDbName); const QStringList args({ QStringLiteral("-U"), QStringLiteral("postgres"), command, QStringLiteral("-h"), m_dbHost, m_dstDbName }); handleProcInit(executablePath(QStringLiteral("psql")), args); connect(m_proc, QOverload::of(&QProcess::finished), this, &CopyDatabase::runPgLoad); m_proc->start(); } void CopyDatabase::runPgLoad() { const QStringList args({QStringLiteral("-U"), QStringLiteral("postgres"), QStringLiteral("-f"), getDumpFile(), QStringLiteral("-h"), m_dbHost, m_dstDbName}); handleProcInit(executablePath(QStringLiteral("psql")), args); connect(m_proc, QOverload::of(&QProcess::finished), this, &CopyDatabase::onPgLoadFinished); m_proc->start(); } void CopyDatabase::onPgLoadFinished(int exitCode, QProcess::ExitStatus exitStatus) { NOTICE_LOG(m_logger) << "onPsqlFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus; if (exitStatus == QProcess::ExitStatus::NormalExit) QFile::remove(getDumpFile()); if (exitCode > 0) { ERROR_LOG(m_logger) << "Loading db failed"; emit copyDbFailed(); return; } runPgSetGrant(); } void CopyDatabase::runPgSetGrant() { const QStringList args({QStringLiteral("-U"), QStringLiteral("postgres"), QStringLiteral("-c"), QStringLiteral("GRANT ALL ON DATABASE %1 to ets_admin").arg(m_dstDbName), QStringLiteral("-h"), m_dbHost, m_dstDbName}); handleProcInit(executablePath(QStringLiteral("psql")), args); connect(m_proc, QOverload::of(&QProcess::finished), this, &CopyDatabase::onPgSetGrantFinished); m_proc->start(); } void CopyDatabase::onPgSetGrantFinished(int exitCode, QProcess::ExitStatus exitStatus) { NOTICE_LOG(m_logger) << "onPsqlFinished: exitCode: " << exitCode << ", exitStatus: " << exitStatus; if (exitCode > 0) { ERROR_LOG(m_logger) << "Set grants to ets_admin failed"; emit copyDbFailed(); return; } emit copyDbFinished(); } void CopyDatabase::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, &CopyDatabase::onErrorOccured); } void CopyDatabase::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus) { 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; } m_proc->disconnect(this); m_proc->deleteLater(); m_proc = nullptr; } void CopyDatabase::onErrorOccured(QProcess::ProcessError error) { ERROR_LOG(m_logger) << "error: " << error << ", " << m_proc->readAllStandardOutput() << ", " << m_proc->readAllStandardError(); } QString CopyDatabase::getDumpFile() const { return QDir::tempPath() + QLatin1Char('/') + m_srcDbName + QStringLiteral(".dump"); } QString CopyDatabase::executablePath(const QString &program) { QString errStr; const QString ret = NGL::postgresExecutablePath(program, errStr); if (!errStr.isEmpty()) WARNING_LOG(m_logger) << errStr; return ret; } } // namespace DBAdministration