Merge branch 'master' of github.com:pcbsd/sysadm

This commit is contained in:
Ken Moore
2016-01-26 12:56:27 -05:00
23 changed files with 962 additions and 90 deletions

View File

@@ -1,7 +1,98 @@
.. _iocage:
iocage
======
******
Some intro text here...
The iocage class is used to manage jails which provide a light-weight, operating system-level virtualization for running applications or services.
Every iocage class request contains the following parameters:
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| **Parameter** | **Value** | **Description** |
| | | |
+=================================+===============+======================================================================================================================+
| id | | any unique value for the request; examples include a hash, checksum, or uuid |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| name | iocage | |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| namespace | sysadm | |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| action | | supported actions include "listjails" |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
The rest of this section provides examples of the available *actions* for each type of request, along with their responses.
.. index:: listjails, iocage
.. _List Jails:
List Jails
==========
The "listjails" action lists information about currently installed jails. For each jail, the response includes the UUID of the jail, whether or not the jail has been configured to start at
system boot, the jail ID (only applies to running jails), whether or not the jail is running, a friendly name for the jail (tag), and the type of jail (basejail or thickjail).
**REST Request**
.. code-block:: json
PUT /sysadm/iocage
{
"action" : "listjails"
}
**REST Response**
.. code-block:: json
{
"args": {
"listjails": {
"611c89ae-c43c-11e5-9602-54ee75595566": {
"boot": "off",
"jid": "-",
"state": "down",
"tag": "testjail",
"type": "basejail"
}
}
}
}
**WebSocket Request**
.. code-block:: json
{
"args" : {
"action" : "listjails"
},
"name" : "iocage",
"id" : "fooid",
"namespace" : "sysadm"
}
**WebSocket Response**
.. code-block:: json
{
"args": {
"listjails": {
"611c89ae-c43c-11e5-9602-54ee75595566": {
"boot": "off",
"jid": "-",
"state": "down",
"tag": "testjail",
"type": "basejail"
}
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}

View File

@@ -18,12 +18,224 @@ The systeminfo class is used to retrieve information about the system. Every sys
| namespace | sysadm | |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| action | | supported actions include "batteryinfo", "externalmounts" |
| action | | supported actions include "memorystats", "cpupercentage", "cputemps", "batteryinfo", "externalmounts", "systeminfo" |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
The rest of this section provides examples of the available *actions* for each type of request, along with their responses.
.. index:: memorystats, systeminfo
.. _Memory Statistics:
Memory Statistics
=================
The "memorystats" action returns memory statistics, including the amount of active, cached, free, inactive, and total physical (wired) memory.
**REST Request**
.. code-block:: json
PUT /sysadm/systeminfo
{
"action" : "memorystats"
}
**REST Response**
.. code-block:: json
{
"args": {
"memorystats": {
"active": "818",
"cache": "69",
"free": "4855",
"inactive": "2504",
"wired": "1598"
}
}
}
**WebSocket Request**
.. code-block:: json
{
"id" : "fooid",
"args" : {
"action" : "memorystats"
},
"namespace" : "sysadm",
"name" : "systeminfo"
}
**WebSocket Response**
.. code-block:: json
{
"args": {
"memorystats": {
"active": "826",
"cache": "69",
"free": "4847",
"inactive": "2505",
"wired": "1598"
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}
.. index:: cpupercentage, systeminfo
.. _CPU Usage:
CPU Usage
=========
The "cpupercentage" action returns the usage percentage of each CPU.
**REST Request**
.. code-block:: json
PUT /sysadm/systeminfo
{
"action" : "cpupercentage"
}
**REST Response**
.. code-block:: json
{
"args": {
"cpupercentage": {
"busytotal": "28",
"cpu1": {
"busy": "28"
},
"cpu2": {
"busy": "31"
},
"cpu3": {
"busy": "29"
},
"cpu4": {
"busy": "24"
}
}
}
}
**WebSocket Request**
.. code-block:: json
{
"args" : {
"action" : "cpupercentage"
},
"name" : "systeminfo",
"id" : "fooid",
"namespace" : "sysadm"
}
**WebSocket Response**
.. code-block:: json
{
"args": {
"cpupercentage": {
"busytotal": "28",
"cpu1": {
"busy": "28"
},
"cpu2": {
"busy": "31"
},
"cpu3": {
"busy": "29"
},
"cpu4": {
"busy": "24"
}
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}
.. index:: cputemps, systeminfo
.. _CPU Temperature:
CPU Temperature
===============
The "cputemps" action returns the temperature of each CPU.
**REST Request**
.. code-block:: json
PUT /sysadm/systeminfo
{
"action" : "cputemps"
}
**REST Response**
.. code-block:: json
{
"args": {
"cputemps": {
"cpu0": "27.0C",
"cpu1": "34.0C",
"cpu2": "33.0C",
"cpu3": "31.0C"
}
}
}
**WebSocket Request**
.. code-block:: json
{
"args" : {
"action" : "cputemps"
},
"id" : "fooid",
"name" : "systeminfo",
"namespace" : "sysadm"
}
**WebSocket Response**
.. code-block:: json
{
"args": {
"cputemps": {
"cpu0": "34.0C",
"cpu1": "32.0C",
"cpu2": "34.0C",
"cpu3": "31.0C"
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}
.. index:: batteryinfo, systeminfo
.. _Battery Information:
@@ -31,9 +243,8 @@ The rest of this section provides examples of the available *actions* for each t
Battery Information
===================
The "batteryinfo" action will indicate whether or not a battery exists. If it does, it will also report its current charge percentage level (1-99) and its
status (offline, charging, on backup, or unknown) and estimated time left (in seconds)
timeleft (1-XXXXXX)
The "batteryinfo" action will indicate whether or not a battery exists. If it does, it will also report its current charge percentage level (1-99). its
status (offline, charging, on backup, or unknown), and estimated time left (in seconds).
**REST Request**
@@ -150,3 +361,78 @@ For each mounted device, the response will include the device name, filesystem,
"name": "response",
"namespace": "sysadm"
}
.. index:: systeminfo
.. _System Information:
System Information
==================
The "systeminfo" action lists system information, including the architecture, number of CPUs, type of CPU, hostname, kernel name and version, system version and patch level, total amount
of RAM, and the system's uptime.
**REST Request**
.. code-block:: json
PUT /sysadm/systeminfo
{
"action" : "systeminfo"
}
**REST Response**
.. code-block:: json
{
"args": {
"systeminfo": {
"arch": "amd64",
"cpucores": "4",
"cputype": "Intel(R) Xeon(R) CPU E3-1220 v3 @ 3.10GHz",
"hostname": "krisdesktop",
"kernelident": "GENERIC",
"kernelversion": "10.2-RELEASE-p11",
"systemversion": "10.2-RELEASE-p12",
"totalmem": 10720,
"uptime": "up 2 days 5:09"
}
}
}
**WebSocket Request**
.. code-block:: json
{
"args" : {
"action" : "systeminfo"
},
"id" : "fooid",
"name" : "systeminfo",
"namespace" : "sysadm"
}
**WebSocket Response**
.. code-block:: json
{
"args": {
"systeminfo": {
"arch": "amd64",
"cpucores": "4",
"cputype": "Intel(R) Xeon(R) CPU E3-1220 v3 @ 3.10GHz",
"hostname": "krisdesktop",
"kernelident": "GENERIC",
"kernelversion": "10.2-RELEASE-p11",
"systemversion": "10.2-RELEASE-p12",
"totalmem": 10720,
"uptime": "up 2 days 5:09"
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}

View File

@@ -20,7 +20,7 @@ Every update class request contains the following parameters:
| namespace | sysadm | |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| action | | supported actions include "checkupdates" |
| action | | supported actions include "checkupdates", "listbranches" |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
@@ -83,4 +83,64 @@ upgrade to a newer version of the operating system, a system patch, or an update
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}
.. index:: listbranches, update
.. _List Branches:
List Branches
=============
The "listbranches" action retrieves the list of available branches (operating system versions). The currently installed version will be listed as "active".
**REST Request**
.. code-block:: json
PUT /sysadm/update
{
"action" : "listbranches"
}
**REST Response**
.. code-block:: json
{
"args": {
"listbranches": {
"10.2-RELEASE": "active",
"11.0-CURRENTJAN2016": "available"
}
}
}
**WebSocket Request**
.. code-block:: json
{
"args" : {
"action" : "listbranches"
},
"namespace" : "sysadm",
"name" : "update",
"id" : "fooid"
}
**WebSocket Response**
.. code-block:: json
{
"args": {
"listbranches": {
"10.2-RELEASE": "active",
"11.0-CURRENTJAN2016": "available"
}
},
"id": "fooid",
"name": "response",
"namespace": "sysadm"
}

61
api/events.rst Normal file
View File

@@ -0,0 +1,61 @@
.. _Events:
Events
******
The "events" namespace can be used to setup and receive asyncronous updates about system status and other types of system notifications.
.. _note: the events namespace does not really translate over to REST which was not designed for asyncronous events. For this reason, only Websocket examples are used in this section.
Every events request contains the following parameters:
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| **Parameter** | **Value** | **Description** |
| | | |
+=================================+===============+======================================================================================================================+
| id | | any unique value for the request; examples include a hash, checksum, or uuid |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| name | | supported values are "subscribe" or unsubscribe" |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| namespace | events | |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
| args | | values vary by type of class |
| | | |
+---------------------------------+---------------+----------------------------------------------------------------------------------------------------------------------+
Here is an example of subscribing to Life Preserver events:
**Websocket Request**
.. code-block:: json
{
"namespace" : "events",
"name" : "subscribe",
"id" : "sampleID",
"args" : ["dispatcher", "life-preserver"]
}
Once subscribed, events will be received as they are produced. To unsubscribe from events, repeat the request, using "unsubscribe" for the "name".
Here is an example reply:
**Websocket Reply**
.. code-block:: json
{
"namespace" : "events",
"name" : "life-preserver",
"id" : "<none>"
"args" : {
"message" : <message>,
"priority" : "<number> -
<category>",
"class" : "[snapshot/replication]"
}
}

View File

@@ -7,6 +7,7 @@ PC-BSD® API Reference
connection
users
events
classes/index
Indices and tables

1
mkports-list Normal file
View File

@@ -0,0 +1 @@
src sysutils/sysadm sysadm

146
mkports.sh Executable file
View File

@@ -0,0 +1,146 @@
#!/bin/sh
# Helper script which will create the port / distfiles
# from a checked out git repo
get_last_rev_git()
{
oPWD=`pwd`
cd "${1}"
rev=0
rev=`git log -n 1 --date=raw . | grep 'Date:' | awk '{print $2}'`
cd "$oPWD"
if [ -n "$rev" ] ; then
echo "$rev"
return 0
else
rev=`git log -n 1 --date=raw . | grep 'Date:' | awk '{print $2}'`
echo $rev
return 0
fi
return 1
}
massage_subdir() {
cd "$1"
if [ $? -ne 0 ] ; then
echo "SKIPPING $i"
continue
fi
echo "# \$FreeBSD\$
#
$comment
" > Makefile.tmp
for d in `ls`
do
if [ "$d" = ".." ]; then continue ; fi
if [ "$d" = "." ]; then continue ; fi
if [ "$d" = "Makefile" ]; then continue ; fi
if [ ! -f "$d/Makefile" ]; then continue ; fi
echo " SUBDIR += $d" >> Makefile.tmp
done
echo "" >> Makefile.tmp
echo ".include <bsd.port.subdir.mk>" >> Makefile.tmp
mv Makefile.tmp Makefile
}
if [ -z "$1" ] ; then
echo "Usage: ./mkports.sh <portstree> <distfiles>"
exit 1
fi
if [ ! -d "${1}/Mk" ] ; then
echo "Invalid directory: $1"
exit 1
fi
portsdir="${1}"
if [ -z "$2" ] ; then
distdir="${1}/distfiles"
else
distdir="${2}"
fi
if [ ! -d "$distdir" ] ; then
mkdir -p ${distdir}
fi
ODIR=`pwd`
# Get this jail version
export UNAME_r="`freebsd-version`"
# Get the GIT tag
ghtag=`git log -n 1 . | grep '^commit ' | awk '{print $2}'`
# Read the list of ports and build them now
while read pline
do
cd "$ODIR"
ldir=`echo $pline | awk '{print $1}'`
# Check for sub-dir
echo "$ldir" | grep -q '/'
if [ $? -eq 0 ] ; then
lsubdir=`echo $ldir | cut -d '/' -f 1`
ltopdir=`echo $ldir | cut -d '/' -f 2`
tOps="-C $lsubdir $ltopdir"
else
unset lsubdir ltopdir
tOps="$ldir"
fi
tdir=`echo $pline | awk '{print $2}'`
tcat=`echo $tdir | cut -d '/' -f 1`
dfile=`echo $pline | awk '{print $3}'`
# Get git revision number
REV=`get_last_rev_git "./$ldir"`
port=`echo $pline | awk '{print $2}'`
tverfile="/tmp/.pcbsd-tests/`echo $port | sed 's|/|_|g'`"
if [ -e "$tverfile" -a -n "$PCBSD_MKTESTS" ] ; then
# If this file exists, we did a previous build of this port
oVer=`cat $tverfile`
echo "$port - $REV - $oVer -"
if [ "$REV" = "$oVer" ] ; then
echo "No changes to port: $port"
continue
fi
fi
# Make the dist files
rm ${distdir}/${dfile}-* 2>/dev/null
echo "Creating $tdir dist file for version: $REV"
tar cvJf ${distdir}/${dfile}-${REV}.tar.xz --exclude .git $tOps 2>/dev/null >/dev/null
if [ $? -ne 0 ] ; then
echo "Error creating distfile..."
exit 1
fi
# Copy ports files
if [ -d "${portsdir}/$tdir" ] ; then
rm -rf ${portsdir}/$tdir 2>/dev/null
fi
cp -r ${ldir}/port-files ${portsdir}/$tdir
# Set the version numbers
sed -i '' "s|%%CHGVERSION%%|${REV}|g" ${portsdir}/$tdir/Makefile
sed -i '' "s|%%GHTAG%%|${ghtag}|g" ${portsdir}/$tdir/Makefile
# Create the makesums / distinfo file
cd "${portsdir}/$tdir"
make makesum
if [ $? -ne 0 ] ; then
echo "Failed makesum"
exit 1
fi
# Now make sure subdir Makefile is correct
massage_subdir "${portsdir}/$tcat"
done < mkports-list

View File

@@ -1,3 +0,0 @@
PC-BSD SysAdm utility and websocket server
WWW: https://github.com/pcbsd/sysadm

View File

@@ -12,6 +12,7 @@ VERSION = 1.0.0
HEADERS += sysadm-global.h \
sysadm-general.h \
sysadm-iocage.h \
sysadm-lifepreserver.h \
sysadm-network.h \
sysadm-firewall.h \
@@ -22,6 +23,7 @@ HEADERS += sysadm-global.h \
SOURCES += NetDevice.cpp \
sysadm-general.cpp \
sysadm-iocage.cpp \
sysadm-lifepreserver.cpp \
sysadm-network.cpp \
sysadm-firewall.cpp \

View File

@@ -0,0 +1,43 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-general.h"
#include "sysadm-iocage.h"
#include "sysadm-global.h"
using namespace sysadm;
//PLEASE: Keep the functions in the same order as listed in pcbsd-general.h
// List the jails on the box
QJsonObject Iocage::listJails() {
QJsonObject retObject;
QStringList output = General::RunCommand("iocage list").split("\n");
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("JID") != -1 )
continue;
if ( output.at(i).isEmpty() )
break;
QJsonObject jail;
QString line = output.at(i).simplified();
QString uuid = line.section(" ", 1, 1);
jail.insert("jid", line.section(" ", 0, 0));
jail.insert("boot", line.section(" ", 2, 2));
jail.insert("state", line.section(" ", 3, 3));
jail.insert("tag", line.section(" ", 4, 4));
jail.insert("type", line.section(" ", 5, 5));
retObject.insert(uuid, jail);
}
return retObject;
}

View File

@@ -0,0 +1,22 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_IOCAGE_H
#define __PCBSD_LIB_UTILS_IOCAGE_H
#include <QJsonObject>
#include "sysadm-global.h"
namespace sysadm{
class Iocage{
public:
static QJsonObject listJails();
};
} //end of pcbsd namespace
#endif

View File

@@ -161,16 +161,91 @@ QJsonObject SysInfo::externalDevicePaths() {
return retObject;
}
// KPM 1-21-2016
// This needs to beefed up as well, so we return more stats on arc, wired, etc
QJsonObject SysInfo::memoryPercentage() {
// Return information about memory
QJsonObject SysInfo::memoryStats() {
QJsonObject retObject;
//SYSCTL: vm.stats.vm.v_<something>_count
QStringList info = General::RunCommand("sysctl -n vm.stats.vm.v_page_count vm.stats.vm.v_wire_count vm.stats.vm.v_active_count").split("\n");
if(info.length()<3){ return retObject; } //error in fetching information
//List output: [total, wired, active]
double perc = 100.0* (info[1].toLong()+info[2].toLong())/(info[0].toDouble());
retObject.insert("memoryused", qRound(perc));
QString tmp;
long pageSize;
bool ok;
// Get the page size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_page_size").simplified();
tmp.toLong(&ok);
if ( ok )
pageSize = tmp.toLong();
else
return retObject;
// Get the free size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_free_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("free", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the inactive size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_inactive_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("inactive", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the cache size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_cache_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("cache", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the wired size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_wire_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("wired", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the active size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_active_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("active", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
return retObject;
}
// Return a bunch of various system information
QJsonObject SysInfo::systemInfo() {
QJsonObject retObject;
QString arch = General::RunCommand("uname -m").simplified();
retObject.insert("arch", arch);
QString sysver = General::RunCommand("freebsd-version").simplified();
retObject.insert("systemversion", sysver);
QString kernver = General::RunCommand("uname -r").simplified();
retObject.insert("kernelversion", kernver);
QString kernident = General::RunCommand("uname -i").simplified();
retObject.insert("kernelident", kernident);
QString host = General::RunCommand("hostname").simplified();
retObject.insert("hostname", host);
QString uptime = General::RunCommand("uptime").simplified().section(" ", 1, 4).simplified().replace(",", "");
retObject.insert("uptime", uptime);
QString cputype = General::RunCommand("sysctl -n hw.model").simplified();
retObject.insert("cputype", cputype);
QString cpucores = General::RunCommand("sysctl -n kern.smp.cpus").simplified();
retObject.insert("cpucores", cpucores);
bool ok;
QString tmp;
QString totalmem = General::RunCommand("sysctl -n hw.realmem").simplified();
totalmem.toLong(&ok);
if ( ok ) {
retObject.insert("totalmem", tmp.setNum(totalmem.toLong() / 1024 / 1024));
}
return retObject;
}

View File

@@ -18,7 +18,8 @@ public:
static QJsonObject cpuPercentage();
static QJsonObject cpuTemps();
static QJsonObject externalDevicePaths();
static QJsonObject memoryPercentage();
static QJsonObject memoryStats();
static QJsonObject systemInfo();
};
} //end of pcbsd namespace

View File

@@ -14,56 +14,87 @@ using namespace sysadm;
// Return a list of updates available
QJsonObject Update::checkUpdates() {
QJsonObject retObject;
QJsonObject retObject;
QStringList output = General::RunCommand("pc-updatemanager check").split("\n");
QString nameval;
QStringList output = General::RunCommand("pc-updatemanager check").split("\n");
QString nameval;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("Your system is up to date!") != -1 )
{
retObject.insert("status", "noupdates");
return retObject;
}
if ( output.at(i).indexOf("NAME: ") != -1 )
nameval = output.at(i).section(" ", 1, 1);
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("Your system is up to date!") != -1 )
{
retObject.insert("status", "noupdates");
return retObject;
}
if ( output.at(i).indexOf("NAME: ") != -1 )
nameval = output.at(i).section(" ", 1, 1);
if ( output.at(i).indexOf("TYPE: SECURITYUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
retObject.insert("security", itemvals);
}
if ( output.at(i).indexOf("TYPE: SYSTEMUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
if ( output.size() > ( i + 1) )
itemvals.insert("tag", output.at(i+1).section(" ", 1, 1));
if ( output.size() > ( i + 2) )
itemvals.insert("version", output.at(i+2).section(" ", 1, 1));
retObject.insert("majorupgrade", itemvals);
}
if ( output.at(i).indexOf("TYPE: PATCH") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
if ( output.size() > ( i + 1) )
itemvals.insert("tag", output.at(i+1).section(" ", 1, 1));
if ( output.size() > ( i + 2) )
itemvals.insert("details", output.at(i+2).section(" ", 1, 1));
if ( output.size() > ( i + 3) )
itemvals.insert("date", output.at(i+3).section(" ", 1, 1));
if ( output.size() > ( i + 4) )
itemvals.insert("size", output.at(i+4).section(" ", 1, 1));
retObject.insert("patch", itemvals);
}
if ( output.at(i).indexOf("TYPE: PKGUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
retObject.insert("packageupdate", itemvals);
}
if ( output.at(i).indexOf("TYPE: SECURITYUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
retObject.insert("security", itemvals);
}
if ( output.at(i).indexOf("TYPE: SYSTEMUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
if ( output.size() > ( i + 1) )
itemvals.insert("tag", output.at(i+1).section(" ", 1, 1));
if ( output.size() > ( i + 2) )
itemvals.insert("version", output.at(i+2).section(" ", 1, 1));
retObject.insert("majorupgrade", itemvals);
}
if ( output.at(i).indexOf("TYPE: PATCH") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
if ( output.size() > ( i + 1) )
itemvals.insert("tag", output.at(i+1).section(" ", 1, 1));
if ( output.size() > ( i + 2) )
itemvals.insert("details", output.at(i+2).section(" ", 1, 1));
if ( output.size() > ( i + 3) )
itemvals.insert("date", output.at(i+3).section(" ", 1, 1));
if ( output.size() > ( i + 4) )
itemvals.insert("size", output.at(i+4).section(" ", 1, 1));
retObject.insert("patch", itemvals);
}
if ( output.at(i).indexOf("TYPE: PKGUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
retObject.insert("packageupdate", itemvals);
}
}
// Update status that we have updates
retObject.insert("status", "updatesavailable");
return retObject;
}
// List available branches we can switch to
QJsonObject Update::listBranches() {
QJsonObject retObject;
QStringList output = General::RunCommand("pc-updatemanager branches").split("\n");
bool inSection = false;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("-----------------") != -1 ) {
inSection = true;
continue;
}
if (!inSection)
continue;
if ( output.at(i).isEmpty() )
break;
QString tmp = output.at(i).section(" ", 0, 0);
QString tmp2 = output.at(i).section(" ", 1, 1);
if ( tmp2 == "*" )
retObject.insert(tmp, "active");
else
retObject.insert(tmp, "available");
}
return retObject;
}

View File

@@ -15,6 +15,7 @@ namespace sysadm{
class Update{
public:
static QJsonObject checkUpdates();
static QJsonObject listBranches();
};
} //end of pcbsd namespace

View File

@@ -1,7 +1,7 @@
# Created by: Kris Moore <kmoore@FreeBSD.org>
# $FreeBSD$
PORTNAME= pcbsd-sysadm
PORTNAME= sysadm
PORTVERSION= %%CHGVERSION%%
CATEGORIES= sysutils
@@ -10,10 +10,6 @@ COMMENT= PC-BSD SysAdm API server
LICENSE= BSD3CLAUSE
RUN_DEPENDS= sipcalc:${PORTSDIR}/net-mgmt/sipcalc \
eject:${PORTSDIR}/sysutils/eject \
unzip:${PORTSDIR}/archivers/unzip
WRKSRC_SUBDIR= src
USE_QT5= core network buildtools qmake
USES= pkgconfig tar:xz qmake

3
src/port-files/pkg-descr Normal file
View File

@@ -0,0 +1,3 @@
Sysadm API server and websocket daemon
WWW: https://github.com/pcbsd/sysadm

View File

@@ -1,10 +1,17 @@
bin/sysadm
bin/sysadm-server
etc/rc.d/sysadm
etc/rc.d/sysadm-restserver
etc/rc.d/sysadm-websocket
include/sysadm-firewall.h
include/sysadm-general.h
include/sysadm-global.h
include/sysadm-iocage.h
include/sysadm-lifepreserver.h
include/sysadm-network.h
include/sysadm-servicemanager.h
include/sysadm-systeminfo.h
include/sysadm-update.h
include/sysadm-usermanager.h
%%QT_LIBDIR%%/%%QT_LIBDIR%%sysadm.so
%%QT_LIBDIR%%/%%QT_LIBDIR%%sysadm.so.1
%%QT_LIBDIR%%/%%QT_LIBDIR%%sysadm.so.1.0

View File

@@ -15,9 +15,8 @@
name="sysadm_restserver"
rcvar=sysadm_restserver_enable
command="/usr/local/bin/sysadm-server"
start_cmd="sysadm_start"
stop_cmd="sysadm_stop"
start_cmd="sysadm_restserver_start"
stop_cmd="sysadm_restserver_stop"
flags=""
[ -z "$sysadm_restserver_enable" ] && sysadm_restserver_enable="NO"
@@ -35,19 +34,20 @@ ssl_keygen()
-subj "/C=US/ST=MY/L=NULL/O=SysAdm/OU=SysAdm/CN=SysAdm/emailAddress=none@example.org" 2>/dev/null
}
sysadm_stop()
sysadm_restserver_stop()
{
if [ -e "/var/run/sysadm-rest.pid" ] ; then
pkill -9 -F /var/run/sysadm-rest.pid
fi
}
sysadm_start()
sysadm_restserver_start()
{
export PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
sysadm_stop
sysadm_restserver_stop
ssl_keygen
echo "Starting sysadm (REST)..."
command="/usr/local/bin/sysadm-server"
daemon -p /var/run/sysadm-rest.pid $command $flags >/dev/null 2>/dev/null
chmod 744 /var/run/sysadm-rest.pid >/dev/null 2>/dev/null
}

View File

@@ -15,9 +15,8 @@
name="sysadm_websocket"
rcvar=sysadm_websocket_enable
command="/usr/local/bin/sysadm-server"
start_cmd="sysadm_start"
stop_cmd="sysadm_stop"
start_cmd="sysadm_websocket_start"
stop_cmd="sysadm_websocket_stop"
flags="-ws"
[ -z "$sysadm_websocket_enable" ] && sysadm_websocket_enable="NO"
@@ -35,19 +34,20 @@ ssl_keygen()
-subj "/C=US/ST=MY/L=NULL/O=SysAdm/OU=SysAdm/CN=SysAdm/emailAddress=none@example.org" 2>/dev/null
}
sysadm_stop()
sysadm_websocket_stop()
{
if [ -e "/var/run/sysadm-websocket.pid" ] ; then
pkill -9 -F /var/run/sysadm-websocket.pid
fi
}
sysadm_start()
sysadm_websocket_start()
{
export PATH="${PATH}:/usr/local/bin:/usr/local/sbin"
sysadm_stop
sysadm_websocket_stop
ssl_keygen
echo "Starting sysadm (WebSocket)..."
command="/usr/local/bin/sysadm-server"
daemon -p /var/run/sysadm-websocket.pid $command $flags >/dev/null 2>/dev/null
chmod 744 /var/run/sysadm-websocket.pid >/dev/null 2>/dev/null
}

View File

@@ -10,6 +10,7 @@
//sysadm library interface classes
#include "sysadm-general.h"
#include "sysadm-iocage.h"
#include "sysadm-lifepreserver.h"
#include "sysadm-network.h"
#include "sysadm-systeminfo.h"
@@ -45,7 +46,20 @@ RestOutputStruct::ExitCode WebSocket::AvailableSubsystems(bool allaccess, QJsonO
if(QFile::exists("/usr/local/bin/lpreserver")){
out->insert("sysadm/lifepreserver", "read/write");
}
// - iocage
if(QFile::exists("/usr/local/sbin/iocage")){
out->insert("sysadm/iocage", "read/write");
}
// - Generic system information
out->insert("sysadm/systeminfo","read/write");
// - PC-BSD Updater
if(QFile::exists("/usr/local/bin/pc-updatemanager")){
out->insert("sysadm/update", "read/write");
}
return RestOutputStruct::OK;
}
@@ -60,14 +74,16 @@ RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(const RestInputStru
//Go through and forward this request to the appropriate sub-system
if(namesp=="rpc" && name=="query"){
return AvailableSubsystems(IN.fullaccess, out);
}else if(namesp=="rpc" && name=="syscache"){
return EvaluateSyscacheRequest(IN.args, out);
}else if(namesp=="rpc" && name=="dispatcher"){
return EvaluateDispatcherRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="network"){
return EvaluateSysadmNetworkRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="iocage"){
return EvaluateSysadmIocageRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="lifepreserver"){
return EvaluateSysadmLifePreserverRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="network"){
return EvaluateSysadmNetworkRequest(IN.args, out);
}else if(namesp=="rpc" && name=="syscache"){
return EvaluateSyscacheRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="systeminfo"){
return EvaluateSysadmSystemInfoRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="update"){
@@ -271,9 +287,13 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmSystemInfoRequest(const QJso
ok = true;
out->insert("externalmounts", sysadm::SysInfo::externalDevicePaths());
}
if(act=="memorypercentage"){
if(act=="memorystats"){
ok = true;
out->insert("memorypercentage", sysadm::SysInfo::memoryPercentage());
out->insert("memorystats", sysadm::SysInfo::memoryStats());
}
if(act=="systeminfo"){
ok = true;
out->insert("systeminfo", sysadm::SysInfo::systemInfo());
}
} //end of "action" key usage
@@ -297,9 +317,35 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmUpdateRequest(const QJsonVal
QString act = JsonValueToString(in_args.toObject().value("action"));
if(act=="checkupdates"){
ok = true;
qDebug() << " - Starting update check";
out->insert("checkupdates", sysadm::Update::checkUpdates());
qDebug() << " - Finished update check";
}
if(act=="listbranches"){
ok = true;
out->insert("listbranches", sysadm::Update::listBranches());
}
} //end of "action" key usage
//If nothing done - return the proper code
if(!ok){
return RestOutputStruct::BADREQUEST;
}
}else{ // if(in_args.isArray()){
return RestOutputStruct::BADREQUEST;
}
return RestOutputStruct::OK;
}
//==== SYSADM -- iocage ====
RestOutputStruct::ExitCode WebSocket::EvaluateSysadmIocageRequest(const QJsonValue in_args, QJsonObject *out){
if(in_args.isObject()){
QStringList keys = in_args.toObject().keys();
bool ok = false;
if(keys.contains("action")){
QString act = JsonValueToString(in_args.toObject().value("action"));
if(act=="listjails"){
ok = true;
out->insert("listjails", sysadm::Iocage::listJails());
}
} //end of "action" key usage

View File

@@ -46,6 +46,8 @@ private:
// -- Individual subsystems
RestOutputStruct::ExitCode EvaluateSyscacheRequest(const QJsonValue in_args, QJsonObject *out);
RestOutputStruct::ExitCode EvaluateDispatcherRequest(const QJsonValue in_args, QJsonObject *out);
// -- sysadm iocage API
RestOutputStruct::ExitCode EvaluateSysadmIocageRequest(const QJsonValue in_args, QJsonObject *out);
// -- sysadm Network API
RestOutputStruct::ExitCode EvaluateSysadmNetworkRequest(const QJsonValue in_args, QJsonObject *out);
// -- sysadm LifePreserver API