diff --git a/src/server/Dispatcher.cpp b/src/server/Dispatcher.cpp new file mode 100644 index 0000000..d5ac4a1 --- /dev/null +++ b/src/server/Dispatcher.cpp @@ -0,0 +1,137 @@ +// =============================== +// PC-BSD REST API Server +// Available under the 3-clause BSD License +// Written by: Ken Moore 2015-2016 +// ================================= +#include "Dispatcher.h" + +#include "globals.h" + +// ================================ +// DProcess Class (Internal) +// ================================ +DProcess::DProcess(QObject *parent) : QProcess(parent){ + //Setup the process + this->setProcessEnvironment(QProcessEnvironment::systemEnvironment()); + this->setProcessChannelMode(QProcess::MergedChannels); + + //setup internal connections + connect(this, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(cmdFinished(int, QProcess::ExitStatus)) ); +} + +DProcess::~DProcess(){ + if(this->state()!=QProcess::NotRunning)){ + this->terminate(); + } +} + +void DProcess::startProc(){ + if(cmds.isEmpty()){ emit ProcFinished(ID); return; } + QString cmd = cmds.takeFirst(); + success = false; //not finished yet + if(!proclog.isEmpty()){ proclog.append("\n"); } + proclog.append("[Running Command: "+cmd+" ]"); + this->start(cmd); +} + +bool DProcess::isRunning(){ + return (this->state()!=QProcess::NotRunning); +} + +QString DProcess::getProcLog(){ + //First update the internal log as needed + proclog.append( this->readAllStandardOutput() ); + //Now return the current version of the log + return proclog; +} + +void DProcess::cmdFinished(int ret, QProcess::ExitStatus status){ + //determin success/failure + success = (status==QProcess::NormalExit && ret==0); + //update the log before starting another command + proclog.append( this->readAllStandardOutput() ); + //Now run any additional commands + if(success){ startProc(); }//will emit the finished signal as needed if no more commands + else{ + if(status==QProcess::NormalExit){ + proclog.append("\n[Command Failed: " + QString::number(ret)+" ]"); + }else{ + proclog.append("\n[Command Failed: Process Crashed ]"); + } + emit ProcFinished(ID); + } +} + +// ================================ +// Dispatcher Class +// ================================ +Dispatcher::Dispatcher(){ + +} + +Dispatcher::~Dispatcher(){ + +} + +void Dispatcher::start(QString queuefile){ + //load any previously-unrun processes + // TO DO +} + +void Dispatcher::stop(){ + //save any currently-unrun processes for next time the server starts + // TO DO +} + +//Overloaded Main Calling Functions (single command, or multiple in-order commands) +void Dispatcher::queueProcess(QString ID, QString cmd){ + queueProcess(NO_QUEUE, ID, QStringList() << cmd); +} +void Dispatcher::queueProcess(QString ID, QStringList cmds){ + queueProcess(NO_QUEUE, ID, cmds); +} +void Dispatcher::queueProcess(Dispatcher::PROC_QUEUE queue, QString ID, QString cmd){ + queueProcess(queue, ID, QStringList() << cmd); +} +void Dispatcher::queueProcess(Dispatcher::PROC_QUEUE queue, QString ID, QStringList cmds){ + //This is the primary queueProcess() function - all the overloads end up here to do the actual work + DProcess *P = createProcess(ID, cmds); + QList list; + if(!HASH.contains(queue)){ HASH.insert(queue, list); } //insert an empty list + HASH[queue] << P; //add this proc to the end of the list + if(queue==NO_QUEUE || HASH[queue].length()==1){ P->startProc(); } //go ahead and start it now + else{ CheckQueues(); } +} + +// === PRIVATE === +//Simplification routine for setting up a process +DProcess* Dispatcher:: createProcess(QString ID, QStringList cmds){ + DProcess* P = new DProcess(this); + P->cmds = cmds; + P->ID = ID; + connect(P, SIGNAL(ProcFinished(QString)), this, SLOT(ProcFinished(QString)) ); + return P; +} + +// === PRIVATE SLOTS === +void Dispatcher::ProcFinished(QString ID){ + //Find the process with this ID and close it down (with proper events) + for int i=0; i(i); + if(HASH.contains(queue)){ + QList list = HASH[queue]; + bool found = false; + for(int l=0; l 2015-2016 +// ================================= +#ifndef _PCBSD_SYSADM_DISPATCH_PROCESS_SYSTEM_H +#define _PCBSD_SYSADM_DISPATCH_PROCESS_SYSTEM_H + +#include "globals-qt.h" + + +// == Simple Process class for running sequential commands == +// == INTERNAL ONLY - Do not use directly == +class DProcess : public QProcess{ + Q_OBJECT +public: + DProcess(QObject parent = 0); + ~DProcess(); + + QString ID; + QStringList cmds; + bool success; + + void startProc(); + + //Get the current process log (can be run during/after the process runs) + QString getProcLog(); + + bool isRunning(); + +private: + QString proclog; + +private slots: + void cmdFinished(int, QProcess::ExitStatus); + +signals: + void ProcFinished(QString ID); +}; + + +class Dispatcher : public QObject{ + Q_OBJECT +public: + enum PROC_QUEUE { NO_QUEUE = 0, PKG_QUEUE, IOCAGE_QUEUE }; +#define enum_length 3 //This needs to be the number of items in the enum above + + Dispatcher(); + ~Dispatcher(); + +public slots: + //Main start/stop + void start(QString queuefile); //load any previously-unrun processes + void stop(); //save any currently-unrun processes for next time + + //Main Calling Functions (single command, or multiple in-order commands) + void queueProcess(QString ID, QString cmd); //uses NO_QUEUE + void queueProcess(QString ID, QStringList cmds); //uses NO_QUEUE + void queueProcess(Dispatcher::PROC_QUEUE, QString ID, QString cmd); + void queueProcess(Dispatcher::PROC_QUEUE, QString ID, QStringList cmds); + +private: + // Queue file + QString queue_file; + + //Internal lists + QHash > QUEUES; + + //Simplification routine for setting up a process + DProcess* createProcess(QString ID, QStringList cmds){ + DProcess* P = new DProcess(this); + P->cmds = cmds; + P->ID = ID; + connect(P, SIGNAL(ProcFinished(QString)), this, SLOT(ProcFinished(QString)) ); + return P; + } + +private slots: + void ProcFinished(QString ID); + void CheckQueues(); + +signals: + void DispatchFinished(QString ID, bool success); + void DispatchStarting(QString ID); + +}; + +#endif \ No newline at end of file diff --git a/src/server/globals-qt.h b/src/server/globals-qt.h index 6323e6e..6a81693 100644 --- a/src/server/globals-qt.h +++ b/src/server/globals-qt.h @@ -22,6 +22,8 @@ #include #include #include +#include + #include #include #include @@ -46,10 +48,14 @@ #include #include +// SSL Version/File defines #define SSLVERSION QSsl::TlsV1_0 #define SSLCERTFILE "/usr/local/etc/sysadm/restserver.crt" #define SSLKEYFILE "/usr/local/etc/sysadm/restserver.key" +// Server Settings defines +#define DISPATCH_QUEUE "/usr/local/etc/sysadm/dispatch_queue" + inline QString DisplayPriority(int pri){ //ensure bounds if(pri<0){ pri = 0; }