diff --git a/api/classes/iocage.rst b/api/classes/iocage.rst index d1d7d6a..dea8b7a 100644 --- a/api/classes/iocage.rst +++ b/api/classes/iocage.rst @@ -20,12 +20,290 @@ Every iocage class request contains the following parameters: | namespace | sysadm | | | | | | +---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+ -| action | | supported actions include "listjails" | +| action | | supported actions include "getdefaultsettings", "listjails", "getjailsettings" | | | | | +---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+ The rest of this section provides examples of the available *actions* for each type of request, along with their responses. +.. index:: getdefaultsettings, iocage + +.. _Default Settings: + +Default Settings +================ + +The "getdefaultsettings" action lists all of the global settings that apply to all jails. + +**REST Request** + +.. code-block:: json + + PUT /sysadm/iocage + { + "action" : "getdefaultsettings" + } + +**REST Response** + +.. code-block:: json + + { + "args": { + "getdefaultsettings": { + "defaults": { + "allow_chflags": "0", + "allow_mount": "0", + "allow_mount_devfs": "0", + "allow_mount_nullfs": "0", + "allow_mount_procfs": "0", + "allow_mount_tmpfs": "0", + "allow_mount_zfs": "0", + "allow_quotas": "0", + "allow_raw_sockets": "0", + "allow_set_hostname": "1", + "allow_socket_af": "0", + "allow_sysvipc": "0", + "available": "426G", + "boot": "off", + "bpf": "off", + "children_max": "0", + "compression": "lz4", + "compressratio": "1.00x", + "coredumpsize": "off", + "count": "1", + "cpuset": "off", + "cputime": "off", + "datasize": "off", + "dedup": "off", + "defaultrouter": "none", + "defaultrouter6": "none", + "devfs_ruleset": "4", + "dhcp": "off", + "enforce_statfs": "2", + "exec_clean": "1", + "exec_fib": "0", + "exec_jail_user": "root", + "exec_poststart": "/usr/bin/true", + "exec_poststop": "/usr/bin/true", + "exec_prestart": "/usr/bin/true", + "exec_prestop": "/usr/bin/true", + "exec_start": "/bin/sh /etc/rc", + "exec_stop": "/bin/sh /etc/rc.shutdown", + "exec_system_jail_user": "0", + "exec_system_user": "root", + "exec_timeout": "60", + "ftpfiles": "base.txz doc.txz lib32.txz src.txz", + "ftphost": "ftp.freebsd.org", + "gitlocation": "https://github.com", + "hack88": "0", + "host_domainname": "none", + "host_hostname": "442a5843-c6bd-11e5-bbe9-fcaa14deb15d", + "host_hostuuid": "442a5843-c6bd-11e5-bbe9-fcaa14deb15d", + "hostid": "4145fbb8-c5b6-11e5-9f2f-fcaa14deb15d", + "interfaces": "vnet0:bridge0,vnet1:bridge1", + "ip4": "new", + "ip4_addr": "none", + "ip4_autoend": "none", + "ip4_autostart": "none", + "ip4_autosubnet": "none", + "ip4_saddrsel": "1", + "ip6": "new", + "ip6_addr": "none", + "ip6_saddrsel": "1", + "istemplate": "no", + "jail_zfs": "off", + "jail_zfs_dataset": "iocage/jails/442a5843-c6bd-11e5-bbe9-fcaa14deb15d/data", + "jail_zfs_mountpoint": "none", + "last_started": "none", + "login_flags": "-f root", + "maxproc": "off", + "memorylocked": "off", + "memoryuse": "8G:log", + "mount_devfs": "1", + "mount_fdescfs": "1", + "mount_linprocfs": "0", + "mount_procfs": "0", + "mountpoint": "/iocage/.defaults", + "msgqqueued": "off", + "msgqsize": "off", + "nmsgq": "off", + "notes": "none", + "nsemop": "off", + "nshm": "off", + "nthr": "off", + "openfiles": "off", + "origin": "-", + "owner": "root", + "pcpu": "off", + "pkglist": "none", + "priority": "99", + "pseudoterminals": "off", + "quota": "none", + "release": "11.0-CURRENTJAN2016", + "reservation": "none", + "resolver": "none", + "rlimits": "off", + "securelevel": "2", + "shmsize": "off", + "stacksize": "off", + "stop_timeout": "30", + "swapuse": "off", + "sync_target": "none", + "sync_tgt_zpool": "none", + "tag": "2016-01-29@14:19:49", + "type": "basejail", + "used": "96K", + "vmemoryuse": "off", + "vnet": "off", + "vnet0_mac": "none", + "vnet1_mac": "none", + "vnet2_mac": "none", + "vnet3_mac": "none", + "wallclock": "off" + } + } + } + } + +**WebSocket Request** + +.. code-block:: json + + { + "args" : { + "action" : "getdefaultsettings" + }, + "id" : "fooid", + "name" : "iocage", + "namespace" : "sysadm" + } + +**WebSocket Response** + +.. code-block:: json + + { + "args": { + "getdefaultsettings": { + "defaults": { + "allow_chflags": "0", + "allow_mount": "0", + "allow_mount_devfs": "0", + "allow_mount_nullfs": "0", + "allow_mount_procfs": "0", + "allow_mount_tmpfs": "0", + "allow_mount_zfs": "0", + "allow_quotas": "0", + "allow_raw_sockets": "0", + "allow_set_hostname": "1", + "allow_socket_af": "0", + "allow_sysvipc": "0", + "available": "426G", + "boot": "off", + "bpf": "off", + "children_max": "0", + "compression": "lz4", + "compressratio": "1.00x", + "coredumpsize": "off", + "count": "1", + "cpuset": "off", + "cputime": "off", + "datasize": "off", + "dedup": "off", + "defaultrouter": "none", + "defaultrouter6": "none", + "devfs_ruleset": "4", + "dhcp": "off", + "enforce_statfs": "2", + "exec_clean": "1", + "exec_fib": "0", + "exec_jail_user": "root", + "exec_poststart": "/usr/bin/true", + "exec_poststop": "/usr/bin/true", + "exec_prestart": "/usr/bin/true", + "exec_prestop": "/usr/bin/true", + "exec_start": "/bin/sh /etc/rc", + "exec_stop": "/bin/sh /etc/rc.shutdown", + "exec_system_jail_user": "0", + "exec_system_user": "root", + "exec_timeout": "60", + "ftpfiles": "base.txz doc.txz lib32.txz src.txz", + "ftphost": "ftp.freebsd.org", + "gitlocation": "https://github.com", + "hack88": "0", + "host_domainname": "none", + "host_hostname": "442a5843-c6bd-11e5-bbe9-fcaa14deb15d", + "host_hostuuid": "442a5843-c6bd-11e5-bbe9-fcaa14deb15d", + "hostid": "4145fbb8-c5b6-11e5-9f2f-fcaa14deb15d", + "interfaces": "vnet0:bridge0,vnet1:bridge1", + "ip4": "new", + "ip4_addr": "none", + "ip4_autoend": "none", + "ip4_autostart": "none", + "ip4_autosubnet": "none", + "ip4_saddrsel": "1", + "ip6": "new", + "ip6_addr": "none", + "ip6_saddrsel": "1", + "istemplate": "no", + "jail_zfs": "off", + "jail_zfs_dataset": "iocage/jails/442a5843-c6bd-11e5-bbe9-fcaa14deb15d/data", + "jail_zfs_mountpoint": "none", + "last_started": "none", + "login_flags": "-f root", + "maxproc": "off", + "memorylocked": "off", + "memoryuse": "8G:log", + "mount_devfs": "1", + "mount_fdescfs": "1", + "mount_linprocfs": "0", + "mount_procfs": "0", + "mountpoint": "/iocage/.defaults", + "msgqqueued": "off", + "msgqsize": "off", + "nmsgq": "off", + "notes": "none", + "nsemop": "off", + "nshm": "off", + "nthr": "off", + "openfiles": "off", + "origin": "-", + "owner": "root", + "pcpu": "off", + "pkglist": "none", + "priority": "99", + "pseudoterminals": "off", + "quota": "none", + "release": "11.0-CURRENTJAN2016", + "reservation": "none", + "resolver": "none", + "rlimits": "off", + "securelevel": "2", + "shmsize": "off", + "stacksize": "off", + "stop_timeout": "30", + "swapuse": "off", + "sync_target": "none", + "sync_tgt_zpool": "none", + "tag": "2016-01-29@14:19:49", + "type": "basejail", + "used": "96K", + "vmemoryuse": "off", + "vnet": "off", + "vnet0_mac": "none", + "vnet1_mac": "none", + "vnet2_mac": "none", + "vnet3_mac": "none", + "wallclock": "off" + } + } + }, + "id": "fooid", + "name": "response", + "namespace": "sysadm" + } + .. index:: listjails, iocage .. _List Jails: @@ -96,3 +374,278 @@ system boot, the jail ID (only applies to running jails), whether or not the jai "name": "response", "namespace": "sysadm" } + +.. index:: getjailsettings, iocage + +.. _Jail Settings: + +Jail Settings +============= + +The "getjailsettings" action lists all of the settings that apply to the specified jail. This is equivalent to running :command:`iocage get all `. + +**REST Request** + +.. code-block:: json + + PUT /sysadm/iocage + { + "jail" : "testjail", + "action" : "getjailsettings" + } + +**REST Response** + +.. code-block:: json + + { + "args": { + "getjailsettings": { + "testjail": { + "allow_chflags": "0", + "allow_mount": "0", + "allow_mount_devfs": "0", + "allow_mount_nullfs": "0", + "allow_mount_procfs": "0", + "allow_mount_tmpfs": "0", + "allow_mount_zfs": "0", + "allow_quotas": "0", + "allow_raw_sockets": "0", + "allow_set_hostname": "1", + "allow_socket_af": "0", + "allow_sysvipc": "0", + "boot": "off", + "bpf": "off", + "branch": "-", + "children_max": "0", + "coredumpsize": "off", + "count": "1", + "cpuset": "off", + "cputime": "off", + "datasize": "off", + "defaultrouter": "none", + "defaultrouter6": "none", + "devfs_ruleset": "4", + "dhcp": "off", + "enforce_statfs": "2", + "exec_clean": "1", + "exec_fib": "0", + "exec_jail_user": "root", + "exec_poststart": "/usr/bin/true", + "exec_poststop": "/usr/bin/true", + "exec_prestart": "/usr/bin/true", + "exec_prestop": "/usr/bin/true", + "exec_start": "/bin/sh /etc/rc", + "exec_stop": "/bin/sh /etc/rc.shutdown", + "exec_system_jail_user": "0", + "exec_system_user": "root", + "exec_timeout": "60", + "ftpdir": "-", + "ftpfiles": "-", + "ftphost": "-", + "ftplocaldir": "-", + "gitlocation": "https", + "hack88": "0", + "host_domainname": "none", + "host_hostname": "4bb3f929-c6bf-11e5-bbe9-fcaa14deb15d", + "host_hostuuid": "4bb3f929-c6bf-11e5-bbe9-fcaa14deb15d", + "hostid": "4145fbb8-c5b6-11e5-9f2f-fcaa14deb15d", + "interfaces": "vnet0", + "ip4": "new", + "ip4_addr": "none", + "ip4_autoend": "none", + "ip4_autostart": "none", + "ip4_autosubnet": "none", + "ip4_saddrsel": "1", + "ip6": "new", + "ip6_addr": "none", + "ip6_saddrsel": "1", + "istemplate": "no", + "jail_zfs": "off", + "jail_zfs_dataset": "iocage/jails/4ba5d76b-c6bf-11e5-bbe9-fcaa14deb15d/data", + "jail_zfs_mountpoint": "none", + "last_started": "none", + "login_flags": "-f root", + "maxproc": "off", + "memorylocked": "off", + "memoryuse": "8G", + "mount_devfs": "1", + "mount_fdescfs": "1", + "mount_linprocfs": "0", + "mount_procfs": "0", + "msgqqueued": "off", + "msgqsize": "off", + "nmsgq": "off", + "notes": "none", + "nsemop": "off", + "nshm": "off", + "nthr": "off", + "openfiles": "off", + "owner": "root", + "pcpu": "off", + "pkglist": "none", + "priority": "99", + "pseudoterminals": "off", + "release": "10.2-RELEASE", + "resolver": "none", + "rlimits": "off", + "securelevel": "2", + "shmsize": "off", + "stacksize": "off", + "start": "-", + "stop_timeout": "30", + "swapuse": "off", + "sync_stat": "-", + "sync_target": "none", + "sync_tgt_zpool": "none", + "tag": "testjail", + "template": "-", + "type": "basejail", + "vmemoryuse": "off", + "vnet": "off", + "vnet0_mac": "none", + "vnet1_mac": "none", + "vnet2_mac": "none", + "vnet3_mac": "none", + "wallclock": "off" + } + } + } + } + +**WebSocket Request** + +.. code-block:: json + + { + "args" : { + "jail" : "testjail", + "action" : "getjailsettings" + }, + "id" : "fooid", + "name" : "iocage", + "namespace" : "sysadm" + } + +**WebSocket Response** + +.. code-block:: json + + { + "args": { + "getjailsettings": { + "testjail": { + "allow_chflags": "0", + "allow_mount": "0", + "allow_mount_devfs": "0", + "allow_mount_nullfs": "0", + "allow_mount_procfs": "0", + "allow_mount_tmpfs": "0", + "allow_mount_zfs": "0", + "allow_quotas": "0", + "allow_raw_sockets": "0", + "allow_set_hostname": "1", + "allow_socket_af": "0", + "allow_sysvipc": "0", + "boot": "off", + "bpf": "off", + "branch": "-", + "children_max": "0", + "coredumpsize": "off", + "count": "1", + "cpuset": "off", + "cputime": "off", + "datasize": "off", + "defaultrouter": "none", + "defaultrouter6": "none", + "devfs_ruleset": "4", + "dhcp": "off", + "enforce_statfs": "2", + "exec_clean": "1", + "exec_fib": "0", + "exec_jail_user": "root", + "exec_poststart": "/usr/bin/true", + "exec_poststop": "/usr/bin/true", + "exec_prestart": "/usr/bin/true", + "exec_prestop": "/usr/bin/true", + "exec_start": "/bin/sh /etc/rc", + "exec_stop": "/bin/sh /etc/rc.shutdown", + "exec_system_jail_user": "0", + "exec_system_user": "root", + "exec_timeout": "60", + "ftpdir": "-", + "ftpfiles": "-", + "ftphost": "-", + "ftplocaldir": "-", + "gitlocation": "https", + "hack88": "0", + "host_domainname": "none", + "host_hostname": "4bb3f929-c6bf-11e5-bbe9-fcaa14deb15d", + "host_hostuuid": "4bb3f929-c6bf-11e5-bbe9-fcaa14deb15d", + "hostid": "4145fbb8-c5b6-11e5-9f2f-fcaa14deb15d", + "interfaces": "vnet0", + "ip4": "new", + "ip4_addr": "none", + "ip4_autoend": "none", + "ip4_autostart": "none", + "ip4_autosubnet": "none", + "ip4_saddrsel": "1", + "ip6": "new", + "ip6_addr": "none", + "ip6_saddrsel": "1", + "istemplate": "no", + "jail_zfs": "off", + "jail_zfs_dataset": "iocage/jails/4ba5d76b-c6bf-11e5-bbe9-fcaa14deb15d/data", + "jail_zfs_mountpoint": "none", + "last_started": "none", + "login_flags": "-f root", + "maxproc": "off", + "memorylocked": "off", + "memoryuse": "8G", + "mount_devfs": "1", + "mount_fdescfs": "1", + "mount_linprocfs": "0", + "mount_procfs": "0", + "msgqqueued": "off", + "msgqsize": "off", + "nmsgq": "off", + "notes": "none", + "nsemop": "off", + "nshm": "off", + "nthr": "off", + "openfiles": "off", + "owner": "root", + "pcpu": "off", + "pkglist": "none", + "priority": "99", + "pseudoterminals": "off", + "release": "10.2-RELEASE", + "resolver": "none", + "rlimits": "off", + "securelevel": "2", + "shmsize": "off", + "stacksize": "off", + "start": "-", + "stop_timeout": "30", + "swapuse": "off", + "sync_stat": "-", + "sync_target": "none", + "sync_tgt_zpool": "none", + "tag": "testjail", + "template": "-", + "type": "basejail", + "vmemoryuse": "off", + "vnet": "off", + "vnet0_mac": "none", + "vnet1_mac": "none", + "vnet2_mac": "none", + "vnet3_mac": "none", + "wallclock": "off" + } + } + }, + "id": "fooid", + "name": "response", + "namespace": "sysadm" + } + \ No newline at end of file diff --git a/src/library/sysadm-iocage.cpp b/src/library/sysadm-iocage.cpp index 3652059..393282b 100644 --- a/src/library/sysadm-iocage.cpp +++ b/src/library/sysadm-iocage.cpp @@ -11,6 +11,64 @@ using namespace sysadm; //PLEASE: Keep the functions in the same order as listed in pcbsd-general.h +// Return all the default iocage settings +QJsonObject Iocage::getDefaultSettings() { + QJsonObject retObject; + + QStringList output = General::RunCommand("iocage defaults").split("\n"); + + QJsonObject vals; + for ( int i = 0; i < output.size(); i++) + { + if ( output.at(i).indexOf("JID") != -1 ) + continue; + + if ( output.at(i).isEmpty() ) + break; + + QString key = output.at(i).simplified().section("=", 0, 0); + QString value = output.at(i).simplified().section("=", 1, 1); + + vals.insert(key, value); + } + + retObject.insert("defaults", vals); + return retObject; +} + +// List the jails on the box +QJsonObject Iocage::getJailSettings(QJsonObject jsin) { + QJsonObject retObject; + + QStringList keys = jsin.keys(); + if (! keys.contains("jail") ) { + retObject.insert("error", "Missing required keys"); + return retObject; + } + + // Get the key values + QString jail = jsin.value("jail").toString(); + + QStringList output = General::RunCommand("iocage get all " + jail).split("\n"); + + QJsonObject vals; + for ( int i = 0; i < output.size(); i++) + { + if ( output.at(i).indexOf("JID") != -1 ) + continue; + + if ( output.at(i).isEmpty() ) + break; + + QString key = output.at(i).simplified().section(":", 0, 0); + QString value = output.at(i).simplified().section(":", 1, 1); + + vals.insert(key, value); + } + + retObject.insert(jail, vals); + return retObject; +} // List the jails on the box QJsonObject Iocage::listJails() { diff --git a/src/library/sysadm-iocage.h b/src/library/sysadm-iocage.h index d9f191e..3a1f9f7 100644 --- a/src/library/sysadm-iocage.h +++ b/src/library/sysadm-iocage.h @@ -14,6 +14,8 @@ namespace sysadm{ class Iocage{ public: + static QJsonObject getDefaultSettings(); + static QJsonObject getJailSettings(QJsonObject); static QJsonObject listJails(); }; diff --git a/src/server/Dispatcher.cpp b/src/server/Dispatcher.cpp index 411edb9..74f6ff2 100644 --- a/src/server/Dispatcher.cpp +++ b/src/server/Dispatcher.cpp @@ -20,7 +20,7 @@ DProcess::DProcess(QObject *parent) : QProcess(parent){ } DProcess::~DProcess(){ - if(this->state()!=QProcess::NotRunning)){ + if( this->state()!=QProcess::NotRunning ){ this->terminate(); } } @@ -30,11 +30,14 @@ void DProcess::startProc(){ finished = QDateTime::currentDateTime(); emit ProcFinished(ID); return; + }else if(proclog.isEmpty()){ + started = QDateTime::currentDateTime(); //first cmd started + rawcmds = cmds; + }else{ + proclog.append("\n"); } QString cmd = cmds.takeFirst(); success = false; //not finished yet - if(!proclog.isEmpty()){ proclog.append("\n"); } - else{ started = QDateTime::currentDateTime(); } //first cmd started proclog.append("[Running Command: "+cmd+" ]"); this->start(cmd); } @@ -105,8 +108,10 @@ void Dispatcher::queueProcess(Dispatcher::PROC_QUEUE queue, QString ID, QStringL 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(); } + if(queue==NO_QUEUE || HASH[queue].length()==1){ + emit DispatchStarting(P->ID); + P->startProc(); //go ahead and start it now + }else{ CheckQueues(); } } // === PRIVATE === @@ -115,6 +120,7 @@ DProcess* Dispatcher:: createProcess(QString ID, QStringList cmds){ DProcess* P = new DProcess(this); P->cmds = cmds; P->ID = ID; + P->success = false; connect(P, SIGNAL(ProcFinished(QString)), this, SLOT(ProcFinished(QString)) ); return P; } @@ -122,22 +128,23 @@ DProcess* Dispatcher:: createProcess(QString ID, QStringList cmds){ // === 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); + bool found = false; + for(int i=0; i(i); if(HASH.contains(queue)){ QList list = HASH[queue]; - bool found = false; for(int l=0; lID==ID){ QJsonObject obj; - obj.insert("log",list[l].procLog()); - obj.insert("success", list[l].success ? "true" : "false" ); + obj.insert("log",list[l]->getProcLog()); + obj.insert("success", list[l]->success ? "true" : "false" ); obj.insert("proc_id", ID); - obj.insert("cmd_list", QJsonArray::fromStringList( list[l].rawcmds ); - obj.insert("time_started", list[l].started.toString(QT::ISODate) ); - obj.insert("time_finished", list[l].finished.toString(QT::ISODate) ); + obj.insert("cmd_list", QJsonArray::fromStringList( list[l]->rawcmds ) ); + obj.insert("time_started", list[l]->started.toString(Qt::ISODate) ); + obj.insert("time_finished", list[l]->finished.toString(Qt::ISODate) ); + emit DispatchFinished(ID, list[l]->success); delete list.takeAt(l); - LogManager::log(LogManager::EV_DISPATCH, obj); + LogManager::log(LogManager::DISPATCH, obj); found = true; } } //end loop over queue list @@ -147,5 +154,19 @@ void Dispatcher::ProcFinished(QString ID){ } void Dispatcher::CheckQueues(){ - + for(int i=0; i(i); + if(HASH.contains(queue)){ + QList list = HASH[queue]; + for(int j=0; j0 && queue!=NO_QUEUE){ break; } //done with this - only first item in these queues should run at a time + if(!list[j]->isRunning() && list[j]->getProcLog().isEmpty()){ + //Need to start this one - has not run yet + emit DispatchStarting(list[j]->ID); + list[j]->startProc(); + } + } //end loop over list + } + + } //end loop over queue types } diff --git a/src/server/Dispatcher.h b/src/server/Dispatcher.h index 19d5af1..5a40332 100644 --- a/src/server/Dispatcher.h +++ b/src/server/Dispatcher.h @@ -14,7 +14,7 @@ class DProcess : public QProcess{ Q_OBJECT public: - DProcess(QObject parent = 0); + DProcess(QObject *parent = 0); ~DProcess(); QString ID; @@ -68,16 +68,10 @@ private: QString queue_file; //Internal lists - QHash > QUEUES; + QHash > HASH; //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; - } + DProcess* createProcess(QString ID, QStringList cmds); private slots: void ProcFinished(QString ID); diff --git a/src/server/EventWatcher.cpp b/src/server/EventWatcher.cpp index 6c53046..7b08090 100644 --- a/src/server/EventWatcher.cpp +++ b/src/server/EventWatcher.cpp @@ -5,6 +5,8 @@ // ================================= #include "EventWatcher.h" +#include "globals.h" + // === PUBLIC === EventWatcher::EventWatcher(){ starting = true; @@ -24,9 +26,9 @@ EventWatcher::~EventWatcher(){ void EventWatcher::start(){ // - DISPATCH Events starting = true; - if(!QFile::exists(DISPATCHWORKING)){ QProcess::execute("touch "+DISPATCHWORKING); } + //if(!QFile::exists(DISPATCHWORKING)){ QProcess::execute("touch "+DISPATCHWORKING); } //qDebug() << " Dispatcher Events:" << DISPATCHWORKING; - WatcherUpdate(DISPATCHWORKING); //load it initially (will also add it to the watcher) + //WatcherUpdate(DISPATCHWORKING); //load it initially (will also add it to the watcher) // - Life Preserver Events WatcherUpdate(LPLOG); //load it initially (will also add it to the watcher); WatcherUpdate(LPERRLOG); //load it initially (will also add it to the watcher); @@ -86,10 +88,29 @@ double EventWatcher::displayToDoubleK(QString displayNumber){ return num; } +// === PUBLIC SLOTS === +//Slots for the global Dispatcher to connect to +void EventWatcher::DispatchStarting(QString ID){ + QJsonObject obj; + obj.insert("process_id", ID); + obj.insert("state", "running"); + LogManager::log(LogManager::EV_DISPATCH, obj); + emit NewEvent(DISPATCHER, obj); +} + +void EventWatcher::DispatchFinished(QString ID, bool success){ + QJsonObject obj; + obj.insert("process_id", ID); + obj.insert("state", "finished"); + obj.insert("result", success ? "success" : "failure"); + LogManager::log(LogManager::EV_DISPATCH, obj); + emit NewEvent(DISPATCHER, obj); +} + // === PRIVATE SLOTS === void EventWatcher::WatcherUpdate(const QString &path){ if(!starting){ qDebug() << "Event Watcher Update:" << path; } - if(path==DISPATCHWORKING){ + /*if(path==DISPATCHWORKING){ //Read the file contents QString stat = readFile(DISPATCHWORKING); if(stat.simplified().isEmpty()){ stat = "idle"; } @@ -97,7 +118,8 @@ void EventWatcher::WatcherUpdate(const QString &path){ HASH.insert(DISPATCHER,stat); //save for later //Forward those contents on to the currently-open sockets emit NewEvent(DISPATCHER, QJsonValue(stat) ); - }else if(path==LPLOG){ + }else*/ + if(path==LPLOG){ //Main Life Preserver Log File ReadLPLogFile(); }else if(path==LPERRLOG){ @@ -121,7 +143,7 @@ void EventWatcher::CheckLogFiles(){ if(!watched.contains(LPLOG) && QFile::exists(LPLOG)){ watcher->addPath(LPLOG); } if(!watched.contains(LPERRLOG) && QFile::exists(LPERRLOG)){ watcher->addPath(LPERRLOG); } if(!watched.contains(tmpLPRepFile) && QFile::exists(tmpLPRepFile)){ watcher->addPath(tmpLPRepFile); } - if(!watched.contains(DISPATCHWORKING) && QFile::exists(LPLOG)){ watcher->addPath(DISPATCHWORKING); } + //if(!watched.contains(DISPATCHWORKING) && QFile::exists(LPLOG)){ watcher->addPath(DISPATCHWORKING); } //qDebug() << "watched:" << watcher->files() << watcher->directories(); } diff --git a/src/server/EventWatcher.h b/src/server/EventWatcher.h index 7f464ab..35e6bed 100644 --- a/src/server/EventWatcher.h +++ b/src/server/EventWatcher.h @@ -8,7 +8,7 @@ #include "globals-qt.h" -#define DISPATCHWORKING QString("/var/tmp/appcafe/dispatch-queue.working") +//#define DISPATCHWORKING QString("/var/tmp/appcafe/dispatch-queue.working") #define LPLOG QString("/var/log/lpreserver/lpreserver.log") #define LPERRLOG QString("/var/log/lpreserver/error.log") #define LPREPLOGDIR QString("/var/log/lpreserver/") @@ -49,6 +49,10 @@ private: public slots: void start(); + //Slots for the global Dispatcher to connect to + void DispatchStarting(QString); + void DispatchFinished(QString, bool); + private slots: //File watcher signals void WatcherUpdate(const QString&); diff --git a/src/server/LogManager.h b/src/server/LogManager.h index 7237c59..eee6ac0 100644 --- a/src/server/LogManager.h +++ b/src/server/LogManager.h @@ -15,7 +15,7 @@ //=========================================== // Event Files (EV_*): JSON input/output (full event) // HOST: String input/output (simple messages) -// +// DISPATCH: Full log of dispatcher processes //=========================================== #define LOGDIR QString("/var/log/sysadm") @@ -24,11 +24,12 @@ class LogManager{ public: //Enumeration of common log files (will automatically use proper file) // === ADD NEW FILE SUPPORT HERE === - enum LOG_FILE {HOST, EV_DISPATCH, EV_LP}; + enum LOG_FILE {HOST, DISPATCH, EV_DISPATCH, EV_LP}; //Conversion function for flag->path static QString flagToPath(LogManager::LOG_FILE flag){ QString filepath; if(flag==HOST){ filepath.append("hostinfo"); } + else if(flag==DISPATCH){ filepath.append("dispatcher"); } else if(flag==EV_DISPATCH){ filepath.append("events-dispatcher"); } else if(flag==EV_LP){ filepath.append("events-lifepreserver"); } else{ return ""; } //invalid file given diff --git a/src/server/WebBackend.cpp b/src/server/WebBackend.cpp index af95ff5..45c71b9 100644 --- a/src/server/WebBackend.cpp +++ b/src/server/WebBackend.cpp @@ -34,6 +34,7 @@ RestOutputStruct::ExitCode WebSocket::AvailableSubsystems(bool allaccess, QJsonO if(QFile::exists("/var/run/syscache.pipe")){ out->insert("rpc/syscache","read"); //no write to syscache - only reads } + // - dispatcher (Internal to server - always available) //"read" is the event notifications, "write" is the ability to queue up jobs out->insert("rpc/dispatcher", allaccess ? "read/write" : "read"); @@ -150,7 +151,7 @@ RestOutputStruct::ExitCode WebSocket::EvaluateDispatcherRequest(const QJsonValue }else{ return RestOutputStruct::BADREQUEST; } //Run the Request (should be one value for each in_req) - QStringList values = DispatcherClient::parseInputs(in_req, AUTHSYSTEM);; + QStringList values = DispatcherClient::parseInputs(in_req, AUTHSYSTEM); while(values.length() < in_req.length()){ values << "[ERROR]"; } //ensure lists are same length //Format the result @@ -350,6 +351,14 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmIocageRequest(const QJsonVal bool ok = false; if(keys.contains("action")){ QString act = JsonValueToString(in_args.toObject().value("action")); + if(act=="getdefaultsettings"){ + ok = true; + out->insert("getdefaultsettings", sysadm::Iocage::getDefaultSettings()); + } + if(act=="getjailsettings"){ + ok = true; + out->insert("getjailsettings", sysadm::Iocage::getJailSettings(in_args.toObject())); + } if(act=="listjails"){ ok = true; out->insert("listjails", sysadm::Iocage::listJails()); diff --git a/src/server/globals.h b/src/server/globals.h index ad9ec30..05dd4d7 100644 --- a/src/server/globals.h +++ b/src/server/globals.h @@ -8,15 +8,15 @@ #include "globals-qt.h" +#include "LogManager.h" + //Global variables/classes (intially created in main.cpp) extern QSettings *CONFIG; #include "EventWatcher.h" extern EventWatcher *EVENTS; -//#include "ProcessQueue.h" -//extern ProcessQueue *PQUEUE; -//#include "LogManager.h" -//extern LogManager *LOGS; +#include "Dispatcher.h" +extern Dispatcher *DISPATCHER; //Special defines #define WSPORTNUMBER 12150 // WebSocket server default port diff --git a/src/server/main.cpp b/src/server/main.cpp index a32abaa..5b3deba 100644 --- a/src/server/main.cpp +++ b/src/server/main.cpp @@ -15,6 +15,7 @@ //Create any global classes QSettings *CONFIG = new QSettings("PCBSD","sysadm"); EventWatcher *EVENTS = new EventWatcher(); +Dispatcher *DISPATCHER = new Dispatcher(); //Create the default logfile QFile logfile; @@ -76,6 +77,10 @@ int main( int argc, char ** argv ) logfile.open(QIODevice::WriteOnly | QIODevice::Append); qInstallMessageHandler(MessageOutput); + //Connect the background classes + QObject::connect(DISPATCHER, SIGNAL(DispatchFinished(QString, bool)), EVENTS, SLOT(DispatchFinished(QString,bool)) ); + QObject::connect(DISPATCHER, SIGNAL(DispatchStarting(QString)), EVENTS, SLOT(DispatchStarting(QString)) ); + //Create the daemon qDebug() << "Starting the PC-BSD sysadm server...." << (websocket ? "(WebSocket)" : "(TCP)"); WebServer *w = new WebServer(); diff --git a/src/server/server.pro b/src/server/server.pro index 81e4a8a..a006f6b 100644 --- a/src/server/server.pro +++ b/src/server/server.pro @@ -13,7 +13,8 @@ HEADERS += globals.h globals-qt.h \ AuthorizationManager.h \ SslServer.h \ EventWatcher.h \ - LogManager.h + LogManager.h \ + Dispatcher.h SOURCES += main.cpp \ WebServer.cpp \ @@ -23,7 +24,8 @@ SOURCES += main.cpp \ dispatcher-client.cpp \ AuthorizationManager.cpp \ EventWatcher.cpp \ - LogManager.cpp + LogManager.cpp \ + Dispatcher.cpp TARGET=sysadm-server diff --git a/tests/api-test.sh b/tests/api-test.sh index 2321f04..00f947b 100755 --- a/tests/api-test.sh +++ b/tests/api-test.sh @@ -7,14 +7,20 @@ JSAWK="./utils/jsawk -j js24" which npm >/dev/null 2>/dev/null if [ $? -ne 0 ] ; then - echo "Please install npm first" - exit 1 + pkg install -y npm + if [ $? -ne 0 ] ; then + echo "Requires npm!" + exit 1 + fi fi pkg info p5-JSON >/dev/null 2>/dev/null if [ $? -ne 0 ] ; then - echo "Please install p5-JSON first" - exit 1 + pkg install -y p5-JSON + if [ $? -ne 0 ] ; then + echo "Requires p5-JSON!" + exit 1 + fi fi if [ ! -d "${HOME}/.npm/ws" ] ; then