diff --git a/sources/queued-daemon/src/QueuedApplication.cpp b/sources/queued-daemon/src/QueuedApplication.cpp index 86b0646..79eb7d0 100644 --- a/sources/queued-daemon/src/QueuedApplication.cpp +++ b/sources/queued-daemon/src/QueuedApplication.cpp @@ -19,7 +19,7 @@ #include #include -#include "queued/Queued.h" +#include #include "QueuedApplicationInterface.h" @@ -28,10 +28,7 @@ QueuedApplication::QueuedApplication(QObject *parent, const QVariantHash &args) : QObject(parent) , m_configuration(args) { - qSetMessagePattern(QueuedDebug::LOG_FORMAT); qCDebug(LOG_APP) << __PRETTY_FUNCTION__; - for (auto &metadata : QueuedDebug::getBuildData()) - qCDebug(LOG_APP) << metadata; init(); initDBus(); diff --git a/sources/queued-daemon/src/QueuedApplicationInterface.cpp b/sources/queued-daemon/src/QueuedApplicationInterface.cpp index 120ef08..5f8d0b6 100644 --- a/sources/queued-daemon/src/QueuedApplicationInterface.cpp +++ b/sources/queued-daemon/src/QueuedApplicationInterface.cpp @@ -18,7 +18,7 @@ #include -#include "queued/Queued.h" +#include #include "QueuedApplication.h" diff --git a/sources/queued-daemon/src/main.cpp b/sources/queued-daemon/src/main.cpp index 1ac26c0..a9c7b91 100644 --- a/sources/queued-daemon/src/main.cpp +++ b/sources/queued-daemon/src/main.cpp @@ -21,6 +21,8 @@ #include +#include + #include "QueuedApplication.h" #include "version.h" @@ -51,7 +53,9 @@ int main(int argc, char *argv[]) if (std::string(argv[i]) != "--daemon") continue; ::daemon(0, 0); + break; } + QueuedDebug::applyLogFormat(); QCoreApplication app(argc, argv); app.setApplicationName(NAME); @@ -93,13 +97,13 @@ int main(int argc, char *argv[]) if (parser.isSet(infoOption)) { auto metadata = QueuedDebug::getBuildData(); for (auto &string : metadata) - QDebug(QtMsgType::QtInfoMsg).noquote() << string; + std::cout << qPrintable(string) << std::endl; return 0; } // check if exists if (existingSessionOperation(QString("Active"))) { - qWarning() << "Another session is active"; + qCWarning(LOG_APP) << "Another session is active"; return 1; } diff --git a/sources/queued/QueuedConfig.h.in b/sources/queued/QueuedConfig.h.in index 37bd626..8ad13a6 100644 --- a/sources/queued/QueuedConfig.h.in +++ b/sources/queued/QueuedConfig.h.in @@ -25,7 +25,7 @@ #define QUEUEDCONFIG_H /** - * @defgroup QueuedConfig + * @addtogroup QueuedConfig * @brief Queued configuration constants */ namespace QueuedConfig @@ -37,68 +37,60 @@ namespace QueuedConfig */ #define DBUS_SERVICE_NAME "org.queued.core" /** - * @ingroup QueuedConfig * @brief DBus service name for library and application */ const char DBUS_SERVICE[] = DBUS_SERVICE_NAME; /** - * @ingroup QueuedConfig * @brief DBus object path for applicaiton */ const char DBUS_APPLICATION_PATH[] = "/application"; /** - * @ingroup QueuedConfig * @brief DBus object path for library */ const char DBUS_OBJECT_PATH[] = "/queued"; /** - * @ingroup QueuedConfig - * @brief DBus properties path for library + * @brief DBus properties path for properties library */ const char DBUS_PROPERTY_PATH[] = "/property"; +/** + * @brief DBus properties path for reports library + */ +const char DBUS_REPORTS_PATH[] = "/report"; // path configuration // common paths /** - * @ingroup QueuedConfig * @brief installation directory for executables */ const char BIN_INSTALL_DIR[] = "@BIN_INSTALL_DIR@"; /** - * @ingroup QueuedConfig * @brief installation directory for data */ const char DATA_INSTALL_DIR[] = "@DATA_INSTALL_DIR@"; /** - * @ingroup QueuedConfig * @brief installation directory for headers */ const char INCLUDE_INSTALL_DIR[] = "@INCLUDE_INSTALL_DIR@"; /** - * @ingroup QueuedConfig * @brief installation directory for libraries */ const char LIB_INSTALL_DIR[] = "@LIB_INSTALL_DIR@"; /** - * @ingroup QueuedConfig * @brief the same as CMAKE_INSTALL_PREFIX */ const char ROOT_INSTALL_DIR[] = "@CMAKE_INSTALL_PREFIX@"; // application specific /** - * @def HOME_PATH - * path to queued home directory + * @brief path to queued home directory */ const char HOME_PATH[] = "queued"; /** - * @def PLUGIN_PATH - * path to plugins inside @ref HOME_PATH + * @brief path to plugins inside @ref HOME_PATH */ const char PLUGIN_PATH[] = "plugins"; // internal configuration /** - * @ingroup QueuedConfig * @brief version of internal storage */ const int DATABASE_VERSION = 1; @@ -111,7 +103,6 @@ const int DATABASE_VERSION = 1; #define PLUGIN_INTERFACE_NAME \ "queued.plugin/@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@" /** - * @ingroup QueuedConfig * @brief plugin interface name */ const char PLUGIN_INTERFACE[] = PLUGIN_INTERFACE_NAME; diff --git a/sources/queued/include/queued/Queued.h b/sources/queued/include/queued/Queued.h index 5982ab0..d95f3b6 100644 --- a/sources/queued/include/queued/Queued.h +++ b/sources/queued/include/queued/Queued.h @@ -28,7 +28,6 @@ #include "QueuedCore.h" #include "QueuedCoreAdaptor.h" #include "QueuedCoreInterface.h" -#include "QueuedCorePropertiesInterface.h" #include "QueuedDatabase.h" #include "QueuedDatabaseManager.h" #include "QueuedDebug.h" @@ -40,6 +39,8 @@ #include "QueuedPluginManagerInterface.h" #include "QueuedProcess.h" #include "QueuedProcessManager.h" +#include "QueuedPropertyInterface.h" +#include "QueuedReportInterface.h" #include "QueuedReportManager.h" #include "QueuedSettings.h" #include "QueuedStaticConfig.h" diff --git a/sources/queued/include/queued/QueuedCore.h b/sources/queued/include/queued/QueuedCore.h index 525a65e..34003aa 100644 --- a/sources/queued/include/queued/QueuedCore.h +++ b/sources/queued/include/queued/QueuedCore.h @@ -187,6 +187,21 @@ public: * @return option value or empty QVariant */ QVariant option(const QString &_key); + /** + * @brief usage report + * @param _from + * start report date + * @param _to + * stop report date + * @param _core + * pointer to core object + * @param _token + * user auth token + * @return performance table + */ + QList performanceReport(const QDateTime &_from, + const QDateTime &_to, + const QString &_token) const; /** * @brief get plugin settings * @param _plugin @@ -227,21 +242,49 @@ public: * task ID * @return task object or nullptr if no task found */ - const QueuedProcess *task(const long long _id); + const QueuedProcess *task(const long long _id) const; + /** + * list of tasks which match criteria + * @param _user + * task user ID filter + * @param _from + * minimal start time + * @param _to + * maximal end time + * @param _token + * user auth token + * @return list of tasks in database format + */ + QList taskReport(const long long _user, + const QDateTime &_from, const QDateTime &_to, + const QString &_token) const; /** * @brief get user by ID * @param _id * user ID * @return user object or nullptr if no user found */ - const QueuedUser *user(const long long _id); + const QueuedUser *user(const long long _id) const; /** * @brief get user by name * @param _name * user name * @return user object or nullptr if no user found */ - const QueuedUser *user(const QString &_name); + const QueuedUser *user(const QString &_name) const; + /** + * list of users which match criteria + * @param _lastLogged + * last logged minimal date + * @param _permission + * user permission filter + * @param _token + * user auth token + * @return list of users in database format + */ + QList userReport(const QDateTime &_lastLogged, + const QueuedEnums::Permission _permission, + const QString &_token) const; // control methods /** * @brief deinit subclasses diff --git a/sources/queued/include/queued/QueuedCoreAdaptor.h b/sources/queued/include/queued/QueuedCoreAdaptor.h index 5a2aa56..1f297f6 100644 --- a/sources/queued/include/queued/QueuedCoreAdaptor.h +++ b/sources/queued/include/queued/QueuedCoreAdaptor.h @@ -183,6 +183,18 @@ bool sendUserPermissionRemove(const long long _id, * @return option value */ QVariant getOption(const QString &_property); +/** + * @brief performance report + * @param _from + * minimal start task time + * @param _to + * maximal stop task time + * @param _token + * user auth token + * @return list of user with used resources + */ +QList getPerformance(const QDateTime &_from, const QDateTime &_to, + const QString &_token); /** * @brief get task property * @param _id @@ -192,6 +204,20 @@ QVariant getOption(const QString &_property); * @return task property value */ QVariant getTask(const long long _id, const QString &_property); +/** + * @brief get tasks list + * @param _user + * task user ID + * @param _from + * minimal start time + * @param _to + * maximal end time + * @param _token + * user auth token + * @return list of task in database representation + */ +QList getTasks(const long long _user, const QDateTime &_from, + const QDateTime &_to, const QString &_token); /** * @brief get user property * @param _id @@ -201,6 +227,19 @@ QVariant getTask(const long long _id, const QString &_property); * @return user property value */ QVariant getUser(const long long _id, const QString &_property); +/** + * @brief get users list + * @param _lastLogged + * minimal last logged in time + * @param _permission + * permission to search + * @param _token + * user auth token + * @return list of users in database representation + */ +QList getUsers(const QDateTime &_lastLogged, + const QueuedEnums::Permission _permission, + const QString &_token); /** * @brief get user ID * @param _name diff --git a/sources/queued/include/queued/QueuedDebug.h b/sources/queued/include/queued/QueuedDebug.h index 67a8a5e..afc8cb3 100644 --- a/sources/queued/include/queued/QueuedDebug.h +++ b/sources/queued/include/queued/QueuedDebug.h @@ -66,6 +66,10 @@ const char LOG_FORMAT[] = "[%{time " "{if-warning}WW%{endif}%{if-critical}CC%{endif}%{if-" "fatal}FF%{endif}][%{category}][%{function}] " "%{message}"; +/** + * @brief method to apply log format + */ +void applyLogFormat(); /** * @brief method to enable debug messages */ diff --git a/sources/queued/include/queued/QueuedLimits.h b/sources/queued/include/queued/QueuedLimits.h index c49770b..4997f39 100644 --- a/sources/queued/include/queued/QueuedLimits.h +++ b/sources/queued/include/queued/QueuedLimits.h @@ -118,6 +118,21 @@ struct Limits { , gpumemory(_gpumemory) , storage(_storage) , valid(true){}; + /** + * @brief *= operator overload + * @param _count + * multiplier + * @return multiplied values + */ + Limits &operator*=(const long long _count) + { + cpu *= _count; + gpu *= _count; + memory *= _count; + gpumemory *= _count; + + return *this; + }; }; /** * @brief convert QString memory value to integer diff --git a/sources/queued/include/queued/QueuedCorePropertiesInterface.h b/sources/queued/include/queued/QueuedPropertyInterface.h similarity index 84% rename from sources/queued/include/queued/QueuedCorePropertiesInterface.h rename to sources/queued/include/queued/QueuedPropertyInterface.h index 6bcd754..fcd10ac 100644 --- a/sources/queued/include/queued/QueuedCorePropertiesInterface.h +++ b/sources/queued/include/queued/QueuedPropertyInterface.h @@ -13,7 +13,7 @@ * all copies or substantial portions of the Software. */ /** - * @file QueuedCorePropertiesInterface.h + * @file QueuedPropertyInterface.h * Header of Queued library * @author Evgeniy Alekseev * @copyright MIT @@ -21,8 +21,8 @@ */ -#ifndef QUEUEDCOREPROPERTIESINTERFACE_H -#define QUEUEDCOREPROPERTIESINTERFACE_H +#ifndef QUEUEDPROPERTYINTERFACE_H +#define QUEUEDPROPERTYINTERFACE_H #include #include @@ -35,22 +35,22 @@ class QueuedCore; /** * @brief DBus interface for QueuedCore class */ -class QueuedCorePropertiesInterface : public QDBusAbstractAdaptor +class QueuedPropertyInterface : public QDBusAbstractAdaptor { Q_OBJECT Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME) public: /** - * @brief QueuedCorePropertiesInterface class constructor + * @brief QueuedPropertyInterface class constructor * @param parent * pointer to QueuedCore object */ - explicit QueuedCorePropertiesInterface(QueuedCore *parent); + explicit QueuedPropertyInterface(QueuedCore *parent); /** - * @brief QueuedCorePropertiesInterface class destructor + * @brief QueuedPropertyInterface class destructor */ - virtual ~QueuedCorePropertiesInterface(); + virtual ~QueuedPropertyInterface(); public slots: /** @@ -103,4 +103,4 @@ private: }; -#endif /* QUEUEDCOREPROPERTIESINTERFACE_H */ +#endif /* QUEUEDPROPERTYINTERFACE_H */ diff --git a/sources/queued/include/queued/QueuedReportInterface.h b/sources/queued/include/queued/QueuedReportInterface.h new file mode 100644 index 0000000..0d74df9 --- /dev/null +++ b/sources/queued/include/queued/QueuedReportInterface.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +/** + * @file QueuedReportInterface.h + * Header of Queued library + * @author Evgeniy Alekseev + * @copyright MIT + * @bug https://github.com/arcan1s/queued/issues + */ + + +#ifndef QUEUEDREPORTINTERFACE_H +#define QUEUEDREPORTINTERFACE_H + +#include +#include + +#include "QueuedConfig.h" + + +class QueuedCore; + +/** + * @brief DBus interface for QueuedReportManager class + */ +class QueuedReportInterface : public QDBusAbstractAdaptor +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", DBUS_SERVICE_NAME) + +public: + /** + * @brief QueuedReportInterface class constructor + * @param parent + * pointer to QueuedCore object + */ + explicit QueuedReportInterface(QueuedCore *parent); + /** + * @brief QueuedReportInterface class destructor + */ + virtual ~QueuedReportInterface(); + +public slots: + /** + * @brief performance report + * @param from + * start report date + * @param to + * stop report date + * @param token + * user auth token + * @return + */ + QDBusVariant Performance(const QString &from, const QString &to, + const QString &token); + /** + * @brief tasks list + * @param user + * user ID to select + * @param from + * minimal task start time + * @param to + * maximal task end time + * @param token + * user auth token + * @return list of tasks match to query + */ + QDBusVariant Tasks(const qlonglong user, const QString &from, + const QString &to, const QString &token); + /** + * @brief users list + * @param lastLogged + * minimal last logged + * @param permission + * permission to search + * @param token + * user auth token + * @return list of users match to query + */ + QDBusVariant Users(const QString &lastLogged, const uint permission, + const QString &token); + +private: + /** + * @brief pointer to database object + */ + QueuedCore *m_core = nullptr; +}; + + +#endif /* QUEUEDREPORTINTERFACE_H */ diff --git a/sources/queued/include/queued/QueuedReportManager.h b/sources/queued/include/queued/QueuedReportManager.h index 4e31e2b..c5fbbaf 100644 --- a/sources/queued/include/queued/QueuedReportManager.h +++ b/sources/queued/include/queued/QueuedReportManager.h @@ -24,9 +24,13 @@ #ifndef QUEUEDREPORTMANAGER_H #define QUEUEDREPORTMANAGER_H +#include #include +#include + +class QueuedCore; class QueuedDatabase; /** @@ -49,6 +53,43 @@ public: * @brief QueuedReportManager class destructor */ virtual ~QueuedReportManager(); + /** + * @brief usage report + * @param _from + * start report date + * @param _to + * stop report date + * @param _core + * pointer to core object + * @return performance table + */ + QList performance(const QueuedCore *_core, + const QDateTime &_from = QDateTime(), + const QDateTime &_to = QDateTime()) const; + /** + * list of tasks which match criteria + * @param _user + * task user ID filter + * @param _from + * minimal start time + * @param _to + * maximal end time + * @return list of tasks in database format + */ + QList tasks(const long long _user = -1, + const QDateTime &_from = QDateTime(), + const QDateTime &_to = QDateTime()) const; + /** + * list of users which match criteria + * @param _lastLogged + * last logged minimal date + * @param _permission + * user permission filter + * @return list of users in database format + */ + QList users(const QDateTime &_lastLogged = QDateTime(), + const QueuedEnums::Permission _permission + = QueuedEnums::Permission::Invalid) const; private: /** diff --git a/sources/queued/src/QueuedAdvancedSettings.cpp b/sources/queued/src/QueuedAdvancedSettings.cpp index f4e7ec3..b903c57 100644 --- a/sources/queued/src/QueuedAdvancedSettings.cpp +++ b/sources/queued/src/QueuedAdvancedSettings.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include /** diff --git a/sources/queued/src/QueuedCore.cpp b/sources/queued/src/QueuedCore.cpp index af79f59..9ac6020 100644 --- a/sources/queued/src/QueuedCore.cpp +++ b/sources/queued/src/QueuedCore.cpp @@ -21,12 +21,12 @@ */ -#include "queued/Queued.h" +#include #include #include -#include "queued/QueuedDatabaseSchema.h" +#include /** @@ -162,10 +162,11 @@ QString QueuedCore::authorization(const QString &_name, QString token = m_users->authorize(_name, _password); if (!token.isEmpty()) { - QVariantHash payload = { - {"token", token}, - {"user", _name}, - {"validUntil", m_users->checkToken(token).toString(Qt::ISODate)}}; + QVariantHash payload + = {{"token", token}, + {"user", _name}, + {"validUntil", + m_users->checkToken(token).toString(Qt::ISODateWithMs)}}; m_database->add(QueuedDB::TOKENS_TABLE, payload); } @@ -325,6 +326,39 @@ QVariant QueuedCore::option(const QString &_key) } +/** + * @fn performanceReport + */ +QList QueuedCore::performanceReport(const QDateTime &_from, + const QDateTime &_to, + const QString &_token) const +{ + qCDebug(LOG_LIB) << "Get performance report for" << _from << _to; + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QList(); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); + + if (isAdmin) { + return m_reports->performance(this, _from, _to); + } else { + auto data = m_reports->performance(this, _from, _to); + QList output; + for (auto &userData : data) { + if (userData["_id"].toLongLong() != userAuthId) + continue; + output.append(userData); + } + return output; + } +} + + /** * @fn pluginSettings */ @@ -435,7 +469,7 @@ bool QueuedCore::stopTask(const long long _id, const QString &_token) /** * @fn task */ -const QueuedProcess *QueuedCore::task(const long long _id) +const QueuedProcess *QueuedCore::task(const long long _id) const { qCDebug(LOG_LIB) << "Get task by ID" << _id; @@ -443,10 +477,43 @@ const QueuedProcess *QueuedCore::task(const long long _id) } +/** + * @fn taskReport + */ +QList QueuedCore::taskReport(const long long _user, + const QDateTime &_from, + const QDateTime &_to, + const QString &_token) const +{ + qCDebug(LOG_LIB) << "Get tasks table by" << _user << _from << _to; + + // check permissions + auto authUser = m_users->user(_token, true); + if (!authUser) { + qCWarning(LOG_LIB) << "Could not find auth user" << _token; + return QList(); + } + long long userAuthId = authUser->index(); + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); + long long effectiveUserId = _user; + if (_user == -1) { + effectiveUserId = userAuthId; + } else if (userAuthId != _user) { + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token + << "not allowed to get task report"; + return QList(); + } + } + + return m_reports->tasks(effectiveUserId, _from, _to); +} + + /** * @fn user */ -const QueuedUser *QueuedCore::user(const long long _id) +const QueuedUser *QueuedCore::user(const long long _id) const { qCDebug(LOG_LIB) << "Get user by ID" << _id; @@ -457,7 +524,7 @@ const QueuedUser *QueuedCore::user(const long long _id) /** * @fn user */ -const QueuedUser *QueuedCore::user(const QString &_name) +const QueuedUser *QueuedCore::user(const QString &_name) const { qCDebug(LOG_LIB) << "Get user by name" << _name; @@ -465,6 +532,28 @@ const QueuedUser *QueuedCore::user(const QString &_name) } +/** + * @fn userReport + */ +QList +QueuedCore::userReport(const QDateTime &_lastLogged, + const QueuedEnums::Permission _permission, + const QString &_token) const +{ + qCDebug(LOG_LIB) << "Get users table by" << _lastLogged + << static_cast(_permission); + + // check permissions + bool isAdmin = m_users->authorize(_token, QueuedEnums::Permission::Reports); + if (!isAdmin) { + qCInfo(LOG_LIB) << "User" << _token << "not allowed to get user report"; + return QList(); + } + + return m_reports->users(_lastLogged, _permission); +} + + /** * @fn deinit */ @@ -480,6 +569,8 @@ void QueuedCore::deinit() QueuedConfig::DBUS_OBJECT_PATH); QDBusConnection::sessionBus().unregisterObject( QueuedConfig::DBUS_PROPERTY_PATH); + QDBusConnection::sessionBus().unregisterObject( + QueuedConfig::DBUS_REPORTS_PATH); QDBusConnection::sessionBus().unregisterService(QueuedConfig::DBUS_SERVICE); // delete objects now @@ -593,9 +684,9 @@ void QueuedCore::updateTaskTime(const long long _id, QVariantHash record; if (_startTime.isValid()) - record[QString("startTime")] = _startTime.toString(Qt::ISODate); + record[QString("startTime")] = _startTime.toString(Qt::ISODateWithMs); if (_endTime.isValid()) - record[QString("endTime")] = _endTime.toString(Qt::ISODate); + record[QString("endTime")] = _endTime.toString(Qt::ISODateWithMs); bool status = m_database->modify(QueuedDB::TASKS_TABLE, _id, record); if (!status) @@ -611,7 +702,7 @@ void QueuedCore::updateUserLoginTime(const long long _id, { qCDebug(LOG_LIB) << "Update user" << _id << "with login time" << _time; - QVariantHash record = {{"lastLogin", _time.toString(Qt::ISODate)}}; + QVariantHash record = {{"lastLogin", _time.toString(Qt::ISODateWithMs)}}; bool status = m_database->modify(QueuedDB::USERS_TABLE, _id, record); if (!status) @@ -662,13 +753,21 @@ void QueuedCore::initDBus() throw QueuedDBusException(message); } if (!bus.registerObject(QueuedConfig::DBUS_PROPERTY_PATH, - new QueuedCorePropertiesInterface(this), + new QueuedPropertyInterface(this), QDBusConnection::ExportAllContents)) { QString message = QString("Could not register properties object %1") .arg(bus.lastError().message()); qCCritical(LOG_DBUS) << message; throw QueuedDBusException(message); } + if (!bus.registerObject(QueuedConfig::DBUS_REPORTS_PATH, + new QueuedReportInterface(this), + QDBusConnection::ExportAllContents)) { + QString message = QString("Could not register reports object %1") + .arg(bus.lastError().message()); + qCCritical(LOG_DBUS) << message; + throw QueuedDBusException(message); + } } @@ -772,7 +871,7 @@ void QueuedCore::initUsers() m_users = new QueuedUserManager(this); m_users->setTokenExpiration(expiry); - QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); + QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs); auto dbTokens = m_database->get( QueuedDB::TOKENS_TABLE, QString("WHERE datetime(validUntil) > datetime('%1')").arg(now)); diff --git a/sources/queued/src/QueuedCoreAdaptor.cpp b/sources/queued/src/QueuedCoreAdaptor.cpp index 0f815a0..cee073e 100644 --- a/sources/queued/src/QueuedCoreAdaptor.cpp +++ b/sources/queued/src/QueuedCoreAdaptor.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include #include @@ -313,6 +313,27 @@ QVariant QueuedCoreAdaptor::getOption(const QString &_property) } +/** + * @fn getPerformance + */ +QList QueuedCoreAdaptor::getPerformance(const QDateTime &_from, + const QDateTime &_to, + const QString &_token) +{ + qCDebug(LOG_DBUS) << "Get performance report for" << _from << _to; + + QVariantList args = {_from.toString(Qt::ISODateWithMs), + _to.toString(Qt::ISODateWithMs), _token}; + return qdbus_cast>( + toNativeType(sendRequest(QueuedConfig::DBUS_SERVICE, + QueuedConfig::DBUS_REPORTS_PATH, + QueuedConfig::DBUS_SERVICE, "Performance", + args) + .first()) + .value()); +} + + /** * @fn getTask */ @@ -329,6 +350,27 @@ QVariant QueuedCoreAdaptor::getTask(const long long _id, } +/** + * @fn getTasks + */ +QList QueuedCoreAdaptor::getTasks(const long long _user, + const QDateTime &_from, + const QDateTime &_to, + const QString &_token) +{ + qCDebug(LOG_DBUS) << "Get tasks list for" << _user << _from << _to; + + QVariantList args = {_user, _from.toString(Qt::ISODateWithMs), + _to.toString(Qt::ISODateWithMs), _token}; + return qdbus_cast>( + toNativeType(sendRequest(QueuedConfig::DBUS_SERVICE, + QueuedConfig::DBUS_REPORTS_PATH, + QueuedConfig::DBUS_SERVICE, "Tasks", args) + .first()) + .value()); +} + + /** * @fn getUser */ @@ -345,6 +387,28 @@ QVariant QueuedCoreAdaptor::getUser(const long long _id, } +/** + * @fn getUsers + */ +QList +QueuedCoreAdaptor::getUsers(const QDateTime &_lastLogged, + const QueuedEnums::Permission _permission, + const QString &_token) +{ + qCDebug(LOG_DBUS) << "Get users list for" << _lastLogged + << static_cast(_permission); + + QVariantList args = {_lastLogged.toString(Qt::ISODateWithMs), + static_cast(_permission), _token}; + return qdbus_cast>( + toNativeType(sendRequest(QueuedConfig::DBUS_SERVICE, + QueuedConfig::DBUS_REPORTS_PATH, + QueuedConfig::DBUS_SERVICE, "Users", args) + .first()) + .value()); +} + + /** * @fn getUserId */ diff --git a/sources/queued/src/QueuedCoreInterface.cpp b/sources/queued/src/QueuedCoreInterface.cpp index fc4d61c..96902bf 100644 --- a/sources/queued/src/QueuedCoreInterface.cpp +++ b/sources/queued/src/QueuedCoreInterface.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include /** diff --git a/sources/queued/src/QueuedDatabase.cpp b/sources/queued/src/QueuedDatabase.cpp index 5ac6cee..84db17a 100644 --- a/sources/queued/src/QueuedDatabase.cpp +++ b/sources/queued/src/QueuedDatabase.cpp @@ -21,13 +21,13 @@ */ -#include "queued/Queued.h" +#include #include #include #include -#include "queued/QueuedDatabaseSchema.h" +#include /** @@ -115,7 +115,7 @@ QList QueuedDatabase::get(const QString &_table, QList output; QSqlQuery query - = m_database.exec(QString("SELECT * FROM '%1' %2 ORDER BY _id DESC") + = m_database.exec(QString("SELECT * FROM '%1' %2 ORDER BY _id ASC") .arg(_table) .arg(_condition)); @@ -278,7 +278,7 @@ void QueuedDatabase::removeTasks(const QDateTime &_endTime) QSqlQuery query = m_database.exec( QString("DELETE FROM %1 WHERE datetime(endTime) < datetime('%2')") .arg(QueuedDB::TASKS_TABLE) - .arg(_endTime.toString(Qt::ISODate))); + .arg(_endTime.toString(Qt::ISODateWithMs))); QSqlError error = query.lastError(); if (error.isValid()) @@ -292,7 +292,7 @@ void QueuedDatabase::removeTasks(const QDateTime &_endTime) */ void QueuedDatabase::removeTokens() { - QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODate); + QString now = QDateTime::currentDateTimeUtc().toString(Qt::ISODateWithMs); QSqlQuery query = m_database.exec( QString("DELETE FROM %1 WHERE datetime(validUntil) > datetime('%2')") .arg(QueuedDB::TOKENS_TABLE) @@ -316,7 +316,7 @@ void QueuedDatabase::removeUsers(const QDateTime &_lastLogin) QSqlQuery query = m_database.exec( QString("DELETE FROM %1 WHERE datetime(lastLogin) < datetime('%2')") .arg(QueuedDB::USERS_TABLE) - .arg(_lastLogin.toString(Qt::ISODate))); + .arg(_lastLogin.toString(Qt::ISODateWithMs))); QSqlError error = query.lastError(); if (error.isValid()) diff --git a/sources/queued/src/QueuedDatabaseManager.cpp b/sources/queued/src/QueuedDatabaseManager.cpp index c6d3a7e..b90d97d 100644 --- a/sources/queued/src/QueuedDatabaseManager.cpp +++ b/sources/queued/src/QueuedDatabaseManager.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include diff --git a/sources/queued/src/QueuedDebug.cpp b/sources/queued/src/QueuedDebug.cpp index 9f812af..eae3b24 100644 --- a/sources/queued/src/QueuedDebug.cpp +++ b/sources/queued/src/QueuedDebug.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include "version.h" @@ -34,6 +34,15 @@ Q_LOGGING_CATEGORY(LOG_PL, "org.queued.plugin", QtMsgType::QtWarningMsg) Q_LOGGING_CATEGORY(LOG_SERV, "org.queued.server", QtMsgType::QtWarningMsg) +/** + * @fn applyLogFormat + */ +void QueuedDebug::applyLogFormat() +{ + qSetMessagePattern(QueuedDebug::LOG_FORMAT); +} + + /** * @fn enableDebug */ diff --git a/sources/queued/src/QueuedLimits.cpp b/sources/queued/src/QueuedLimits.cpp index 62986a1..352d17d 100644 --- a/sources/queued/src/QueuedLimits.cpp +++ b/sources/queued/src/QueuedLimits.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include /** diff --git a/sources/queued/src/QueuedPluginManager.cpp b/sources/queued/src/QueuedPluginManager.cpp index 937767d..1e0c642 100644 --- a/sources/queued/src/QueuedPluginManager.cpp +++ b/sources/queued/src/QueuedPluginManager.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include #include diff --git a/sources/queued/src/QueuedProcessManager.cpp b/sources/queued/src/QueuedProcessManager.cpp index e665e38..147a318 100644 --- a/sources/queued/src/QueuedProcessManager.cpp +++ b/sources/queued/src/QueuedProcessManager.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include extern "C" { #include @@ -81,9 +81,9 @@ QueuedProcess *QueuedProcessManager::add(const QVariantHash &_properties, defs.user = _properties[QString("user")].toLongLong(); // metadata defs.startTime = QDateTime::fromString( - _properties[QString("startTime")].toString(), Qt::ISODate); + _properties[QString("startTime")].toString(), Qt::ISODateWithMs); defs.endTime = QDateTime::fromString( - _properties[QString("endTime")].toString(), Qt::ISODate); + _properties[QString("endTime")].toString(), Qt::ISODateWithMs); return add(defs, _index); } diff --git a/sources/queued/src/QueuedCorePropertiesInterface.cpp b/sources/queued/src/QueuedPropertyInterface.cpp similarity index 76% rename from sources/queued/src/QueuedCorePropertiesInterface.cpp rename to sources/queued/src/QueuedPropertyInterface.cpp index c68b547..9d53a2c 100644 --- a/sources/queued/src/QueuedCorePropertiesInterface.cpp +++ b/sources/queued/src/QueuedPropertyInterface.cpp @@ -13,7 +13,7 @@ * all copies or substantial portions of the Software. */ /** - * @file QueuedCorePropertiesInterface.cpp + * @file QueuedPropertyInterface.cpp * Source code of queued library * @author Evgeniy Alekseev * @copyright GPLv3 @@ -21,18 +21,18 @@ */ -#include "queued/Queued.h" +#include #include /** - * @class QueuedCorePropertiesInterface + * @class QueuedPropertyInterface */ /** - * @fn QueuedCorePropertiesInterface + * @fn QueuedPropertyInterface */ -QueuedCorePropertiesInterface::QueuedCorePropertiesInterface(QueuedCore *parent) +QueuedPropertyInterface::QueuedPropertyInterface(QueuedCore *parent) : QDBusAbstractAdaptor(parent) , m_core(parent) { @@ -41,9 +41,9 @@ QueuedCorePropertiesInterface::QueuedCorePropertiesInterface(QueuedCore *parent) /** - * @fn ~QueuedCorePropertiesInterface + * @fn ~QueuedPropertyInterface */ -QueuedCorePropertiesInterface::~QueuedCorePropertiesInterface() +QueuedPropertyInterface::~QueuedPropertyInterface() { qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__; } @@ -52,7 +52,7 @@ QueuedCorePropertiesInterface::~QueuedCorePropertiesInterface() /** * @fn Option */ -QDBusVariant QueuedCorePropertiesInterface::Option(const QString &property) +QDBusVariant QueuedPropertyInterface::Option(const QString &property) { qCDebug(LOG_DBUS) << "Get property" << property; @@ -63,8 +63,8 @@ QDBusVariant QueuedCorePropertiesInterface::Option(const QString &property) /** * @fn Task */ -QDBusVariant QueuedCorePropertiesInterface::Task(const long long id, - const QString &property) +QDBusVariant QueuedPropertyInterface::Task(const long long id, + const QString &property) { qCDebug(LOG_DBUS) << "Get property" << property << "from task" << id; @@ -85,8 +85,8 @@ QDBusVariant QueuedCorePropertiesInterface::Task(const long long id, /** * @fn User */ -QDBusVariant QueuedCorePropertiesInterface::User(const long long id, - const QString &property) +QDBusVariant QueuedPropertyInterface::User(const long long id, + const QString &property) { qCDebug(LOG_DBUS) << "Get property" << property << "from user" << id; @@ -107,7 +107,7 @@ QDBusVariant QueuedCorePropertiesInterface::User(const long long id, /** * @fn UserIdByName */ -qlonglong QueuedCorePropertiesInterface::UserIdByName(const QString &name) +qlonglong QueuedPropertyInterface::UserIdByName(const QString &name) { qCDebug(LOG_DBUS) << "Look for user ID" << name; @@ -124,8 +124,7 @@ qlonglong QueuedCorePropertiesInterface::UserIdByName(const QString &name) /** * @fn getProperties */ -QVariantHash -QueuedCorePropertiesInterface::getProperties(const QObject *_object) +QVariantHash QueuedPropertyInterface::getProperties(const QObject *_object) { qCDebug(LOG_DBUS) << "Get all properties from" << _object->objectName(); diff --git a/sources/queued/src/QueuedReportInterface.cpp b/sources/queued/src/QueuedReportInterface.cpp new file mode 100644 index 0000000..068c9aa --- /dev/null +++ b/sources/queued/src/QueuedReportInterface.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2017 Evgeniy Alekseev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ +/** + * @file QueuedReportInterface.cpp + * Source code of queued library + * @author Evgeniy Alekseev + * @copyright GPLv3 + * @bug https://github.com/arcan1s/queued/issues + */ + + +#include + +#include + + +/** + * @class QueuedReportInterface + */ +/** + * @fn QueuedReportInterface + */ +QueuedReportInterface::QueuedReportInterface(QueuedCore *parent) + : QDBusAbstractAdaptor(parent) + , m_core(parent) +{ + qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__; + + qRegisterMetaType>("QList"); + qDBusRegisterMetaType>(); +} + + +/** + * @fn ~QueuedReportInterface + */ +QueuedReportInterface::~QueuedReportInterface() +{ + qCDebug(LOG_DBUS) << __PRETTY_FUNCTION__; +} + + +/** + * @fn Performance + */ +QDBusVariant QueuedReportInterface::Performance(const QString &from, + const QString &to, + const QString &token) +{ + qCDebug(LOG_DBUS) << "Performance report for" << from << to; + + return QDBusVariant( + QVariant::fromValue>(m_core->performanceReport( + QDateTime::fromString(from, Qt::ISODateWithMs), + QDateTime::fromString(to, Qt::ISODateWithMs), token))); +} + + +/** + * @fn Tasks + */ +QDBusVariant QueuedReportInterface::Tasks(const qlonglong user, + const QString &from, + const QString &to, + const QString &token) +{ + qCDebug(LOG_DBUS) << "Search for tasks" << user << from << to; + + return QDBusVariant(QVariant::fromValue>( + m_core->taskReport(user, QDateTime::fromString(from, Qt::ISODateWithMs), + QDateTime::fromString(to, Qt::ISODateWithMs), + token))); +} + + +/** + * @fn Users + */ +QDBusVariant QueuedReportInterface::Users(const QString &lastLogged, + const uint permission, + const QString &token) +{ + qCDebug(LOG_DBUS) << "Search for users" << lastLogged << permission; + + return QDBusVariant(QVariant::fromValue>( + m_core->userReport(QDateTime::fromString(lastLogged, Qt::ISODateWithMs), + permission < 1 ? QueuedEnums::Permission::Invalid + : QueuedEnums::Permission(permission), + token))); +} diff --git a/sources/queued/src/QueuedReportManager.cpp b/sources/queued/src/QueuedReportManager.cpp index bbf1b70..a4c137a 100644 --- a/sources/queued/src/QueuedReportManager.cpp +++ b/sources/queued/src/QueuedReportManager.cpp @@ -21,7 +21,9 @@ */ -#include "queued/Queued.h" +#include + +#include /** @@ -46,3 +48,146 @@ QueuedReportManager::~QueuedReportManager() { qCDebug(LOG_LIB) << __PRETTY_FUNCTION__; } + + +/** + * @fn performance + */ +QList QueuedReportManager::performance(const QueuedCore *_core, + const QDateTime &_from, + const QDateTime &_to) const +{ + qCDebug(LOG_LIB) << "Build performance report from" << _from << "to" << _to; + + QStringList conditions; + if (_from.isValid()) + conditions += QString("((datetime(startTime) > datetime('%1')) OR " + "(startTime IS NULL))") + .arg(_from.toString(Qt::ISODateWithMs)); + if (_to.isValid()) + conditions += QString("((datetime(endTime) < datetime('%1')) AND " + "(endTime NOT NULL))") + .arg(_to.toString(Qt::ISODateWithMs)); + + QString condition + = conditions.isEmpty() + ? "" + : QString("WHERE (%1)").arg(conditions.join(" AND ")); + qCInfo(LOG_LIB) << "Task condition select" << condition; + auto tasks = m_database->get(QueuedDB::TASKS_TABLE, condition); + + // build hash first + QHash hashOutput; + for (auto &task : tasks) { + QueuedLimits::Limits limits + = QueuedLimits::Limits(task["limits"].toString()); + // update values to system ones if empty + if (limits.cpu == 0) + limits.cpu = QueuedSystemInfo::cpuCount(); + if (limits.memory == 0) + limits.memory = QueuedSystemInfo::memoryCount(); + // calculate usage stats + long long taskTime + = QDateTime::fromString(task["endTime"].toString(), + Qt::ISODateWithMs) + .toMSecsSinceEpoch() + - QDateTime::fromString(task["startTime"].toString(), + Qt::ISODateWithMs) + .toMSecsSinceEpoch(); + limits *= taskTime / 1000; + + // append + long long userId = task.value("user").toLongLong(); + auto userObj = _core->user(userId); + QVariantHash currentData = hashOutput[userId]; + currentData["cpu"] + = currentData.value("cpu", 0).toLongLong() + limits.cpu; + currentData["memory"] + = currentData.value("memory", 0).toLongLong() + limits.memory; + currentData["gpu"] + = currentData.value("gpu", 0).toLongLong() + limits.gpu; + currentData["gpumemory"] + = currentData.value("gpumemory", 0).toLongLong() + limits.gpumemory; + currentData["storage"] + = currentData.value("storage", 0).toLongLong() + limits.storage; + currentData["count"] = currentData.value("count", 0).toLongLong() + 1; + // internal fields + currentData["user"] = userObj ? userObj->name() : ""; + currentData["email"] = userObj ? userObj->email() : ""; + currentData["_id"] = userId; + + hashOutput[userId] = currentData; + } + + // append output data + auto userList = hashOutput.keys(); + std::sort(userList.begin(), userList.end(), + [](const long long first, const long long second) { + return first < second; + }); + QList output; + for (auto userId : userList) + output.append(hashOutput[userId]); + + return output; +} + + +/** + * @fn tasks + */ +QList QueuedReportManager::tasks(const long long _user, + const QDateTime &_from, + const QDateTime &_to) const +{ + qCDebug(LOG_LIB) << "Search for tasks in" << _user << _from << _to; + + QStringList conditions; + if (_user != -1) + conditions += QString("(user = %1)").arg(_user); + if (_from.isValid()) + conditions += QString("((datetime(startTime) > datetime('%1')) OR " + "(startTime IS NULL))") + .arg(_from.toString(Qt::ISODateWithMs)); + if (_to.isValid()) + conditions += QString("((datetime(endTime) < datetime('%1')) AND " + "(endTime NOT NULL))") + .arg(_to.toString(Qt::ISODateWithMs)); + + QString condition + = conditions.isEmpty() + ? "" + : QString("WHERE (%1)").arg(conditions.join(" AND ")); + qCInfo(LOG_LIB) << "Task condition select" << condition; + + return m_database->get(QueuedDB::TASKS_TABLE, condition); +} + + +/** + * @fn users + */ +QList +QueuedReportManager::users(const QDateTime &_lastLogged, + const QueuedEnums::Permission _permission) const +{ + qCDebug(LOG_LIB) << "Search for users in" << _lastLogged + << static_cast(_permission); + + QStringList conditions; + if (_lastLogged.isValid()) + conditions += QString("((datetime(lastLogin) > datetime('%1')) AND " + "(lastLogin NOT NULL))") + .arg(_lastLogged.toString(Qt::ISODateWithMs)); + if (_permission != QueuedEnums::Permission::Invalid) + conditions += QString("((permissions & ~%1) != permissions)") + .arg(static_cast(_permission)); + + QString condition + = conditions.isEmpty() + ? "" + : QString("WHERE (%1)").arg(conditions.join(" AND ")); + qCInfo(LOG_LIB) << "User condition select" << condition; + + return m_database->get(QueuedDB::USERS_TABLE, condition); +} diff --git a/sources/queued/src/QueuedSettings.cpp b/sources/queued/src/QueuedSettings.cpp index bd9fd61..5332f9a 100644 --- a/sources/queued/src/QueuedSettings.cpp +++ b/sources/queued/src/QueuedSettings.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include #include diff --git a/sources/queued/src/QueuedSystemInfo.cpp b/sources/queued/src/QueuedSystemInfo.cpp index a68d525..36e614a 100644 --- a/sources/queued/src/QueuedSystemInfo.cpp +++ b/sources/queued/src/QueuedSystemInfo.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include diff --git a/sources/queued/src/QueuedTokenManager.cpp b/sources/queued/src/QueuedTokenManager.cpp index 58485ce..df53795 100644 --- a/sources/queued/src/QueuedTokenManager.cpp +++ b/sources/queued/src/QueuedTokenManager.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include #include @@ -97,7 +97,7 @@ void QueuedTokenManager::loadTokens(const QList &_values) for (auto &token : _values) { QDateTime validUntil = QDateTime::fromString( - token[QString("validUntil")].toString(), Qt::ISODate); + token[QString("validUntil")].toString(), Qt::ISODateWithMs); loadToken({token[QString("token")].toString(), token[QString("user")].toString(), validUntil}); } diff --git a/sources/queued/src/QueuedUser.cpp b/sources/queued/src/QueuedUser.cpp index 98c41e6..0eef7d9 100644 --- a/sources/queued/src/QueuedUser.cpp +++ b/sources/queued/src/QueuedUser.cpp @@ -21,7 +21,7 @@ */ -#include "queued/Queued.h" +#include #include diff --git a/sources/queuedctl/src/QueuedctlCommon.cpp b/sources/queuedctl/src/QueuedctlCommon.cpp index 629a52a..2d6e0ed 100644 --- a/sources/queuedctl/src/QueuedctlCommon.cpp +++ b/sources/queuedctl/src/QueuedctlCommon.cpp @@ -18,6 +18,8 @@ #include +#include + #include "QueuedctlAuth.h" #include "QueuedctlOption.h" #include "QueuedctlPermissions.h" @@ -32,7 +34,7 @@ void QueuedctlCommon::checkArgs(const QStringList &_args, const int _count, qCDebug(LOG_APP) << "Check args count" << _args << _count; if (_args.count() != _count) { - qWarning() << "Invalid command"; + qCWarning(LOG_APP) << "Invalid command"; _parser.showHelp(1); } } @@ -68,6 +70,32 @@ QString QueuedctlCommon::hashToString(const QVariantHash &_hash) } +QString QueuedctlCommon::hashListToString(const QList &_list) +{ + qCDebug(LOG_APP) << "Convert hash list to string" << _list; + + if (_list.isEmpty()) + return ""; + + QStringList output; + // get table header + QStringList header = _list.first().keys(); + header.sort(); + output += header.join(','); + // append rows + for (auto &hash : _list) { + QStringList row; + std::for_each(header.cbegin(), header.cend(), + [&hash, &row](const QString &column) { + row += hash[column].toString().replace('\n', ' '); + }); + output += row.join(','); + } + + return output.join('\n'); +} + + void QueuedctlCommon::preprocess(const QStringList &_args, QCommandLineParser &_parser) { @@ -105,12 +133,18 @@ void QueuedctlCommon::preprocess(const QStringList &_args, break; case QueuedctlArgument::PluginList: break; + case QueuedctlArgument::Report: + QueuedctlUser::parserReport(_parser); + break; case QueuedctlArgument::TaskAdd: QueuedctlTask::parserAdd(_parser); break; case QueuedctlArgument::TaskGet: QueuedctlTask::parserGet(_parser); break; + case QueuedctlArgument::TaskList: + QueuedctlTask::parserList(_parser); + break; case QueuedctlArgument::TaskSet: QueuedctlTask::parserSet(_parser); break; @@ -124,6 +158,9 @@ void QueuedctlCommon::preprocess(const QStringList &_args, case QueuedctlArgument::UserGet: QueuedctlUser::parserGet(_parser); break; + case QueuedctlArgument::UserList: + QueuedctlUser::parserList(_parser); + break; case QueuedctlArgument::UserSet: QueuedctlUser::parserSet(_parser); break; @@ -137,9 +174,9 @@ void QueuedctlCommon::preprocess(const QStringList &_args, void QueuedctlCommon::print(const QueuedctlResult &_result) { if (!_result.status) - qInfo() << "Subprocess returns error"; + std::cout << "Subprocess returns error" << std::endl; if (!_result.output.isEmpty()) - QDebug(QtMsgType::QtInfoMsg).noquote() << _result.output; + std::cout << qPrintable(_result.output) << std::endl; } @@ -240,6 +277,13 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, = QString("Could not remove plugin %1").arg(args.at(1)); break; } + case QueuedctlArgument::Report: { + QString token = QueuedctlAuth::getToken(_cache, _user); + result.status = true; + result.output + = hashListToString(QueuedctlUser::getReport(_parser, token)); + break; + } case QueuedctlArgument::TaskAdd: { QString token = QueuedctlAuth::getToken(_cache, _user); auto definitions = QueuedctlTask::getDefinitions(_parser, false); @@ -259,6 +303,13 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, : value.toString(); break; } + case QueuedctlArgument::TaskList: { + QString token = QueuedctlAuth::getToken(_cache, _user); + result.status = true; + result.output + = hashListToString(QueuedctlTask::getTasks(_parser, token)); + break; + } case QueuedctlArgument::TaskSet: { QString token = QueuedctlAuth::getToken(_cache, _user); auto definitions = QueuedctlTask::getDefinitions(_parser, true); @@ -296,6 +347,13 @@ QueuedctlCommon::process(QCommandLineParser &_parser, const QString &_cache, : value.toString(); break; } + case QueuedctlArgument::UserList: { + QString token = QueuedctlAuth::getToken(_cache, _user); + result.status = true; + result.output + = hashListToString(QueuedctlUser::getUsers(_parser, token)); + break; + } case QueuedctlArgument::UserSet: { auto userId = QueuedctlUser::getUserId(args.at(1)); QString token = QueuedctlAuth::getToken(_cache, _user); diff --git a/sources/queuedctl/src/QueuedctlCommon.h b/sources/queuedctl/src/QueuedctlCommon.h index 448ad07..101104f 100644 --- a/sources/queuedctl/src/QueuedctlCommon.h +++ b/sources/queuedctl/src/QueuedctlCommon.h @@ -33,13 +33,16 @@ enum class QueuedctlArgument { PluginAdd, PluginList, PluginRemove, + Report, TaskAdd, TaskGet, + TaskList, TaskSet, TaskStart, TaskStop, UserAdd, UserGet, + UserList, UserSet }; typedef struct { @@ -64,19 +67,23 @@ const QHash QueuedctlArguments = { {QueuedctlArgument::PluginList, "Shows enabled plugins.", 1}}, {"plugin-remove", {QueuedctlArgument::PluginRemove, "Removes plugin to load.", 2}}, + {"report", {QueuedctlArgument::Report, "Shows usage report.", 1}}, {"task-add", {QueuedctlArgument::TaskAdd, "Adds new task.", 2}}, {"task-get", {QueuedctlArgument::TaskGet, "Gets task properties.", 3}}, + {"task-list", {QueuedctlArgument::TaskList, "Gets tasks list.", 1}}, {"task-set", {QueuedctlArgument::TaskSet, "Sets task properties.", 2}}, {"task-start", {QueuedctlArgument::TaskStart, "Starts task.", 2}}, {"task-stop", {QueuedctlArgument::TaskStop, "Stops task.", 2}}, {"user-add", {QueuedctlArgument::UserAdd, "Adds new user.", 2}}, {"user-get", {QueuedctlArgument::UserGet, "Gets user properties.", 3}}, + {"user-list", {QueuedctlArgument::UserList, "Gets users list.", 1}}, {"user-set", {QueuedctlArgument::UserSet, "Sets user properties.", 2}}}; // methods void checkArgs(const QStringList &_args, const int _count, QCommandLineParser &_parser); QString commandsHelp(); QString hashToString(const QVariantHash &_hash); +QString hashListToString(const QList &_list); void preprocess(const QStringList &_args, QCommandLineParser &_parser); void print(const QueuedctlResult &_result); QueuedctlResult process(QCommandLineParser &_parser, const QString &_cache, diff --git a/sources/queuedctl/src/QueuedctlTask.cpp b/sources/queuedctl/src/QueuedctlTask.cpp index 4d8f68d..e861d58 100644 --- a/sources/queuedctl/src/QueuedctlTask.cpp +++ b/sources/queuedctl/src/QueuedctlTask.cpp @@ -72,10 +72,10 @@ QueuedctlTask::getDefinitions(const QCommandLineParser &_parser, if (_expandAll) { definitions.command = _parser.value("program"); definitions.endTime - = QDateTime::fromString(_parser.value("stop"), Qt::ISODate); + = QDateTime::fromString(_parser.value("stop"), Qt::ISODateWithMs); definitions.gid = _parser.value("gid").toUInt(); definitions.startTime - = QDateTime::fromString(_parser.value("start"), Qt::ISODate); + = QDateTime::fromString(_parser.value("start"), Qt::ISODateWithMs); definitions.uid = _parser.value("uid").toUInt(); } else { // queuedctl -- task-add /path/to/application @@ -98,6 +98,21 @@ QVariant QueuedctlTask::getTask(const long long _id, const QString &_property) } +QList QueuedctlTask::getTasks(const QCommandLineParser &_parser, + const QString &_token) +{ + long long user = _parser.value("task-user").isEmpty() + ? -1 + : QueuedctlUser::getUserId(_parser.value("task-user")); + QDateTime stop + = QDateTime::fromString(_parser.value("stop"), Qt::ISODateWithMs); + QDateTime start + = QDateTime::fromString(_parser.value("start"), Qt::ISODateWithMs); + + return QueuedCoreAdaptor::getTasks(user, start, stop, _token); +} + + void QueuedctlTask::parserAdd(QCommandLineParser &_parser) { _parser.addPositionalArgument("program", "Command line.", ""); @@ -150,6 +165,20 @@ void QueuedctlTask::parserGet(QCommandLineParser &_parser) } +void QueuedctlTask::parserList(QCommandLineParser &_parser) +{ + // user + QCommandLineOption userOption("task-user", "Task user.", "task-user", ""); + _parser.addOption(userOption); + // start + QCommandLineOption startOption("start", "Task start time.", "start", ""); + _parser.addOption(startOption); + // stop + QCommandLineOption stopOption("stop", "Task stop time.", "stop", ""); + _parser.addOption(stopOption); +} + + void QueuedctlTask::parserSet(QCommandLineParser &_parser) { _parser.addPositionalArgument("id", "Task ID.", ""); diff --git a/sources/queuedctl/src/QueuedctlTask.h b/sources/queuedctl/src/QueuedctlTask.h index 3d82932..232ed5d 100644 --- a/sources/queuedctl/src/QueuedctlTask.h +++ b/sources/queuedctl/src/QueuedctlTask.h @@ -29,8 +29,11 @@ long long addTask(const QueuedProcess::QueuedProcessDefinitions &_definitions, QueuedProcess::QueuedProcessDefinitions getDefinitions(const QCommandLineParser &_parser, const bool _expandAll); QVariant getTask(const long long _id, const QString &_property); +QList getTasks(const QCommandLineParser &_parser, + const QString &_token); void parserAdd(QCommandLineParser &_parser); void parserGet(QCommandLineParser &_parser); +void parserList(QCommandLineParser &_parser); void parserSet(QCommandLineParser &_parser); void parserStart(QCommandLineParser &_parser); bool setTask(const long long _id, diff --git a/sources/queuedctl/src/QueuedctlUser.cpp b/sources/queuedctl/src/QueuedctlUser.cpp index 4876959..b86f93f 100644 --- a/sources/queuedctl/src/QueuedctlUser.cpp +++ b/sources/queuedctl/src/QueuedctlUser.cpp @@ -18,6 +18,8 @@ #include +#include + extern "C" { #include #include @@ -34,6 +36,20 @@ QueuedctlUser::addUser(const QueuedUser::QueuedUserDefinitions &_definitions, } +QList QueuedctlUser::getReport(const QCommandLineParser &_parser, + const QString &_token) +{ + qCDebug(LOG_APP) << "Get usage report"; + + QDateTime stop + = QDateTime::fromString(_parser.value("stop"), Qt::ISODateWithMs); + QDateTime start + = QDateTime::fromString(_parser.value("start"), Qt::ISODateWithMs); + + return QueuedCoreAdaptor::getPerformance(start, stop, _token); +} + + QueuedUser::QueuedUserDefinitions QueuedctlUser::getDefinitions(const QCommandLineParser &_parser, const bool _expandAll) @@ -47,6 +63,11 @@ QueuedctlUser::getDefinitions(const QCommandLineParser &_parser, definitions.password = _parser.isSet("stdin-password") ? getPassword() : _parser.value("password"); + // transform to hash + definitions.password + = definitions.password.isEmpty() + ? "" + : QueuedUser::hashFromPassword(definitions.password); // limits now QueuedLimits::Limits limits( _parser.value("limit-cpu").toLongLong(), @@ -77,7 +98,7 @@ QString QueuedctlUser::getPassword() tty.c_lflag &= ~ECHO; tcsetattr(STDIN_FILENO, TCSANOW, &tty); - qInfo() << "Password"; + std::cout << "Password" << std::endl; QTextStream stream(stdin); QString password; stream >> password; @@ -98,6 +119,20 @@ QVariant QueuedctlUser::getUser(const long long _id, const QString &_property) } +QList QueuedctlUser::getUsers(const QCommandLineParser &_parser, + const QString &_token) +{ + QDateTime lastLogin = QDateTime::fromString(_parser.value("last-logged"), + Qt::ISODateWithMs); + auto permission + = _parser.value("access").isEmpty() + ? QueuedEnums::Permission::Invalid + : QueuedEnums::Permission(_parser.value("access").toInt()); + + return QueuedCoreAdaptor::getUsers(lastLogin, permission, _token); +} + + long long QueuedctlUser::getUserId(const QString &_name) { qCDebug(LOG_APP) << "Get user ID for" << _name; @@ -164,6 +199,29 @@ void QueuedctlUser::parserGet(QCommandLineParser &_parser) } +void QueuedctlUser::parserList(QCommandLineParser &_parser) +{ + // last logged in + QCommandLineOption loggedOption("last-logged", "User last logged time.", + "last-logged", ""); + _parser.addOption(loggedOption); + // permissions + QCommandLineOption accessOption("access", "User permission.", "access", ""); + _parser.addOption(accessOption); +} + + +void QueuedctlUser::parserReport(QCommandLineParser &_parser) +{ + // start + QCommandLineOption startOption("start", "Task start time.", "start", ""); + _parser.addOption(startOption); + // stop + QCommandLineOption stopOption("stop", "Task stop time.", "stop", ""); + _parser.addOption(stopOption); +} + + void QueuedctlUser::parserSet(QCommandLineParser &_parser) { _parser.addPositionalArgument("id", "User ID.", ""); diff --git a/sources/queuedctl/src/QueuedctlUser.h b/sources/queuedctl/src/QueuedctlUser.h index 2f3a217..089f7b0 100644 --- a/sources/queuedctl/src/QueuedctlUser.h +++ b/sources/queuedctl/src/QueuedctlUser.h @@ -26,13 +26,19 @@ namespace QueuedctlUser { long long addUser(const QueuedUser::QueuedUserDefinitions &_definitions, const QString &_token); +QList getReport(const QCommandLineParser &_parser, + const QString &_token); QueuedUser::QueuedUserDefinitions getDefinitions(const QCommandLineParser &_parser, const bool _expandAll); QString getPassword(); QVariant getUser(const long long _id, const QString &_property); +QList getUsers(const QCommandLineParser &_parser, + const QString &_token); long long getUserId(const QString &_name); void parserAdd(QCommandLineParser &_parser); void parserGet(QCommandLineParser &_parser); +void parserList(QCommandLineParser &_parser); +void parserReport(QCommandLineParser &_parser); void parserSet(QCommandLineParser &_parser); bool setUser(const long long _id, const QueuedUser::QueuedUserDefinitions &_definitions, diff --git a/sources/queuedctl/src/main.cpp b/sources/queuedctl/src/main.cpp index b5a9838..c9b27db 100644 --- a/sources/queuedctl/src/main.cpp +++ b/sources/queuedctl/src/main.cpp @@ -19,6 +19,8 @@ #include +#include + #include "QueuedctlCommon.h" #include "version.h" @@ -29,6 +31,8 @@ extern "C" { int main(int argc, char *argv[]) { + QueuedDebug::applyLogFormat(); + QCoreApplication app(argc, argv); app.setApplicationName(NAME); app.setApplicationVersion(VERSION); @@ -81,13 +85,12 @@ int main(int argc, char *argv[]) if (parser.isSet(infoOption)) { auto metadata = QueuedDebug::getBuildData(); for (auto &string : metadata) - QDebug(QtMsgType::QtInfoMsg).noquote() << string; + std::cout << qPrintable(string) << std::endl; return 0; } if (parser.isSet(commandsOption)) { - QDebug(QtMsgType::QtInfoMsg).noquote() << parser.helpText(); - QDebug(QtMsgType::QtInfoMsg).noquote() - << QueuedctlCommon::commandsHelp(); + std::cout << qPrintable(parser.helpText()) << std::endl; + std::cout << qPrintable(QueuedctlCommon::commandsHelp()) << std::endl; return 0; }