API CHANGE: New class - sysadm/powerd

This is a class for managing the "powerd" service on the system.

Available "action"s:
"list_options": List all the available options and possible settings for each.
"read_options": Show all the current settings.
"set_options":  Modify any settings.
"list_status":  List the current state of the service (running, enabled)
"set_active":   Enable this device for starting on bootup.
"set_inactive": Disable this device from starting on bootup.
"start":        Start this service now.
"stop":         Stop this service now.

Example API Calls:
==================

REST Request (example):
-------------------------------
PUT /sysadm/powerd
{
   "action" : "list_options"
}

WebSocket Request:
-------------------------------
{
   "name" : "powerd",
   "namespace" : "sysadm",
   "args" : {
      "action" : "list_options"
   },
   "id" : "fooid"
}

Response:
-------------------------------
{
  "args": {
    "list_options": {
      "ac_power_mode": [
        "maximum",
        "hiadaptive",
        "adaptive",
        "minumum"
      ],
      "adaptive_lower_threshold_percent": "int min=1 max=100",
      "adaptive_raise_threshold_percent": "int min=1 max=100",
      "battery_power_mode": [
        "maximum",
        "hiadaptive",
        "adaptive",
        "minumum"
      ],
      "max_cpu_freq": "int frequency(hz)>0",
      "min_cpu_freq": "int frequency(hz)>0",
      "polling_interval_ms": "int milliseconds>0",
      "unknown_power_mode": [
        "maximum",
        "hiadaptive",
        "adaptive",
        "minumum"
      ]
    }
  },
  "id": "fooid",
  "name": "response",
  "namespace": "sysadm"
}
===============================

REST Request (example):
-------------------------------
PUT /sysadm/powerd
{
   "action" : "read_options"
}

WebSocket Request:
-------------------------------
{
   "id" : "fooid",
   "name" : "powerd",
   "args" : {
      "action" : "read_options"
   },
   "namespace" : "sysadm"
}

Response:
-------------------------------
{
  "args": {
    "read_options": {
      "ac_power_mode": "maximum",
      "adaptive_lower_threshold_percent": "50",
      "adaptive_raise_threshold_percent": "75",
      "battery_power_mode": "adaptive",
      "max_cpu_freq": "-1",
      "min_cpu_freq": "-1",
      "polling_interval_ms": "250",
      "unknown_power_mode": "adaptive"
    }
  },
  "id": "fooid",
  "name": "response",
  "namespace": "sysadm"
}
===========================

REST Request (example):
-------------------------------
PUT /sysadm/powerd
{
   "action" : "list_status"
}

WebSocket Request:
-------------------------------
{
   "id" : "fooid",
   "name" : "powerd",
   "namespace" : "sysadm",
   "args" : {
      "action" : "list_status"
   }
}

Response:
-------------------------------
{
  "args": {
    "list_status": {
      "enabled": "true",
      "running": "true"
    }
  },
  "id": "fooid",
  "name": "response",
  "namespace": "sysadm"
}
===================

REST Request (example):
-------------------------------
PUT /sysadm/powerd
{
   "action" : "stop"
}

WebSocket Request:
-------------------------------
{
   "args" : {
      "action" : "stop"
   },
   "id" : "fooid",
   "namespace" : "sysadm",
   "name" : "powerd"
}

Response:
-------------------------------
{
  "args": {
    "stop": {
      "stopped": "true"
    }
  },
  "id": "fooid",
  "name": "response",
  "namespace": "sysadm"
}
==================

REST Request (example):
-------------------------------
PUT /sysadm/powerd
{
   "battery_power_mode" : "minimum",
   "action" : "set_options"
}

WebSocket Request:
-------------------------------
{
   "name" : "powerd",
   "args" : {
      "action" : "set_options",
      "battery_power_mode" : "minimum"
   },
   "id" : "fooid",
   "namespace" : "sysadm"
}

Response:
-------------------------------
{
  "args": {
    "set_options": {
      "ac_power_mode": "maximum",
      "adaptive_lower_threshold_percent": "50",
      "adaptive_raise_threshold_percent": "75",
      "battery_power_mode": "minimum",
      "max_cpu_freq": "-1",
      "min_cpu_freq": "-1",
      "polling_interval_ms": "250",
      "unknown_power_mode": "adaptive"
    }
  },
  "id": "fooid",
  "name": "response",
  "namespace": "sysadm"
}
This commit is contained in:
Ken Moore
2017-02-07 12:34:33 -05:00
parent e67f77f447
commit de9b9af3c0
5 changed files with 254 additions and 2 deletions

View File

@@ -24,6 +24,7 @@
#include "library/sysadm-servicemanager.h"
#include "library/sysadm-firewall.h"
#include "library/sysadm-moused.h"
#include "library/sysadm-powerd.h"
#define DEBUG 0
//#define SCLISTDELIM QString("::::") //SysCache List Delimiter
@@ -99,6 +100,10 @@ RestOutputStruct::ExitCode WebSocket::AvailableSubsystems(bool allaccess, QJsonO
if(QFile::exists("/usr/sbin/moused")){
out->insert("sysadm/moused", "read/write");
}
// - powerd
if(QFile::exists("/usr/sbin/powerd")){
out->insert("sysadm/powerd", "read/write");
}
return RestOutputStruct::OK;
}
@@ -157,6 +162,8 @@ RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(const RestInputStru
return EvaluateSysadmFirewallRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="moused"){
return EvaluateSysadmMousedRequest(IN.args, out);
}else if(namesp=="sysadm" && name=="powerd"){
return EvaluateSysadmPowerdRequest(IN.args, out);
}else{
return RestOutputStruct::BADREQUEST;
}
@@ -1248,3 +1255,33 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSysadmMousedRequest(const QJsonVal
}
}
RestOutputStruct::ExitCode WebSocket::EvaluateSysadmPowerdRequest(const QJsonValue in_args, QJsonObject *out){
QString action = in_args.toObject().value("action").toString();
QJsonObject outobj;
if(action == "list_options"){
outobj = sysadm::powerd::listOptions();
}else if(action == "read_options"){
outobj = sysadm::powerd::readOptions();
}else if(action == "set_options"){
outobj = sysadm::powerd::setOptions(in_args.toObject());
}else if(action == "list_status"){
outobj = sysadm::powerd::listStatus();
}else if(action == "set_active"){
outobj = sysadm::powerd::enableService();
}else if(action == "set_inactive"){
outobj = sysadm::powerd::disableService();
}else if(action == "start"){
outobj = sysadm::powerd::startService();
}else if(action == "stop"){
outobj = sysadm::powerd::stopService();
}
//check return structure for validity
if(!outobj.keys().isEmpty()){
out->insert(action, outobj);
return RestOutputStruct::OK;
}else{
return RestOutputStruct::BADREQUEST;
}
}

View File

@@ -98,6 +98,8 @@ private:
RestOutputStruct::ExitCode EvaluateSysadmFirewallRequest(const QJsonValue in_args, QJsonObject *out);
// -- sysadm moused API
RestOutputStruct::ExitCode EvaluateSysadmMousedRequest(const QJsonValue in_args, QJsonObject *out);
// -- sysadm powerd API
RestOutputStruct::ExitCode EvaluateSysadmPowerdRequest(const QJsonValue in_args, QJsonObject *out);
private slots:
void sendReply(QString msg);

View File

@@ -16,7 +16,8 @@ HEADERS += $${PWD}/sysadm-global.h \
$${PWD}/sysadm-users.h \
$${PWD}/sysadm-zfs.h \
$${PWD}/sysadm-pkg.h \
$${PWD}/sysadm-moused.h
$${PWD}/sysadm-moused.h \
$${PWD}/sysadm-powerd.h
SOURCES += $${PWD}/NetDevice.cpp \
$${PWD}/sysadm-general.cpp \
@@ -33,4 +34,5 @@ SOURCES += $${PWD}/NetDevice.cpp \
$${PWD}/sysadm-users.cpp \
$${PWD}/sysadm-zfs.cpp \
$${PWD}/sysadm-pkg.cpp \
$${PWD}/sysadm-moused.cpp
$${PWD}/sysadm-moused.cpp \
$${PWD}/sysadm-powerd.cpp

View File

@@ -0,0 +1,177 @@
//===========================================
// TrueOS source code
// Copyright (c) 2017, TrueOS Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-general.h"
#include "sysadm-powerd.h"
#include "sysadm-global.h"
#include "globals.h"
#include "sysadm-servicemanager.h"
#define _POWERD_CONF QString("/etc/conf.d/powerd")
#define _POWERD_SYS_CONF QString("/etc/rc.conf")
#define _POWERD_DEFAULT_CONF QString("/etc/defaults/rc.conf")
using namespace sysadm;
//Service options for individual devices
QJsonObject powerd::listOptions(){
QJsonObject out;
out.insert("ac_power_mode", QJsonArray() << "maximum" << "hiadaptive" << "adaptive" << "minumum"); // "-a" flag
out.insert("battery_power_mode", QJsonArray() << "maximum" << "hiadaptive" << "adaptive" << "minumum"); // "-b" flag
out.insert("unknown_power_mode", QJsonArray() << "maximum" << "hiadaptive" << "adaptive" << "minumum"); // "-n" flag
out.insert("adaptive_lower_threshold_percent", "int min=1 max=100"); // "-i" flag
out.insert("adaptive_raise_threshold_percent", "int min=1 max=100"); // "-r" flag
out.insert("min_cpu_freq", "int frequency(hz)>0"); // "-m" flag
out.insert("max_cpu_freq", "int frequency(hz)>0"); // "-M" flag
out.insert("polling_interval_ms", "int milliseconds>0"); // "-p" flag
return out;
}
QJsonObject powerd::readOptions(){
QString val = General::getConfFileValue(_POWERD_CONF, "powerd_args=" );
if(val.isEmpty()){ General::getConfFileValue(_POWERD_SYS_CONF, "powerd_args=" ); }
if(val.isEmpty()){ General::getConfFileValue(_POWERD_DEFAULT_CONF, "powerd_args=" ); }
val = val.simplified();
if(val.startsWith("\"")){ val.remove(0,1); }
if(val.endsWith("\"")){ val.chop(1); }
QStringList args = val.split(" ");
//qDebug() << " - Arguments:" << args;
QJsonObject out;
//Now parse the arguments and list them in the output object
int index = args.indexOf("-a");
if(index>=0 && index < (args.length()-1) ){
out.insert("ac_power_mode", args[index+1] );
}else{
QString ac = General::getConfFileValue(_POWERD_CONF, "powerd_ac_mode=" );
if(ac.isEmpty()){ ac = "adaptive"; }
out.insert("ac_power_mode",ac);
}
index = args.indexOf("-b");
if(index>=0 && index < (args.length()-1) ){
out.insert("battery_power_mode", args[index+1] );
}else{
QString bat = General::getConfFileValue(_POWERD_CONF, "powerd_battery_mode=" );
if(bat.isEmpty()){ bat = "adaptive"; }
out.insert("battery_power_mode",bat);
}
index = args.indexOf("-n");
if(index>=0 && index < (args.length()-1) ){
out.insert("unknown_power_mode", args[index+1] );
}else{
out.insert("unknown_power_mode", "adaptive");
}
index = args.indexOf("-i");
if(index>=0 && index < (args.length()-1) ){
out.insert("adaptive_lower_threshold_percent", args[index+1] );
}else{
out.insert("adaptive_lower_threshold_percent", "50");
}
index = args.indexOf("-r");
if(index>=0 && index < (args.length()-1) ){
out.insert("adaptive_raise_threshold_percent", args[index+1] );
}else{
out.insert("adaptive_raise_threshold_percent", "75");
}
index = args.indexOf("-m");
if(index>=0 && index < (args.length()-1) ){
out.insert("min_cpu_freq", args[index+1] );
}else{
out.insert("min_cpu_freq", "-1");
}
index = args.indexOf("-M");
if(index>=0 && index < (args.length()-1) ){
out.insert("max_cpu_freq", args[index+1] );
}else{
out.insert("max_cpu_freq", "-1");
}
index = args.indexOf("-p");
if(index>=0 && index < (args.length()-1) ){
out.insert("polling_interval_ms", args[index+1] );
}else{
out.insert("polling_interval_ms", "250");
}
return out;
}
QJsonObject powerd::setOptions(QJsonObject obj){
QJsonObject Cobj = readOptions();
//Overlay the user's settings on top of the current settings
QStringList keys = Cobj.keys();
bool foundchange = false;
for(int i=0; i<keys.length(); i++){
if(obj.contains(keys[i])){ foundchange = true; Cobj.insert(keys[i], obj.value(keys[i])); } //This will replace any current setting with the user-requested one
}
if(!foundchange){ return QJsonObject(); } //invalid inputs - nothing to do
//Assemble the argument list based on the options
QStringList args;
for(int i=0; i<keys.length(); i++){
QString val = Cobj.value(keys[i]).toString();
if(keys[i]=="ac_power_mode"){ General::setConfFileValue(_POWERD_CONF, "powerd_ac_mode=", "powerd_ac_mode=\""+val+"\"" ); }
else if(keys[i]=="battery_power_mode"){ General::setConfFileValue(_POWERD_CONF, "powerd_battery_mode=", "powerd_ac_mode=\""+val+"\"" ); }
else if(keys[i]=="unknown_power_mode"){ args << "-n" << val; }
else if(keys[i]=="adaptive_lower_threshold_percent"){ args << "-i" << val; }
else if(keys[i]=="adaptive_raise_threshold_percent"){ args << "-r" << val; }
else if(keys[i]=="min_cpu_freq" && val.toInt()>=0){ args << "-m" << val; }
else if(keys[i]=="max_cpu_freq" && val.toInt()>=0){ args << "-M" << val; }
else if(keys[i]=="polling_interval_ms"){ args << "-p" << val; }
}
//Save the arguments into the settings file
QString device = obj.value("device").toString();
General::setConfFileValue(_POWERD_CONF, "powerd_args=", "powerd_args=\""+args.join(" ")+"\"" );
//Restart the moused daemon for this device
General::RunQuickCommand("service moused."+device+" restart");
return Cobj; //return the object for the settings we just used
}
//Service status for devices (enable/disable device)
QJsonObject powerd::listStatus(){
ServiceManager SMGR;
Service serv = SMGR.GetService("powerd");
QJsonObject out;
out.insert("running", SMGR.isRunning(serv) ? "true" : "false" );
out.insert("enabled", SMGR.isEnabled(serv) ? "true" : "false" );
return out;
}
QJsonObject powerd::startService(){
ServiceManager SMGR;
Service serv = SMGR.GetService("powerd");
bool ok = SMGR.Start(serv);
QJsonObject out;
out.insert("started", ok ? "true" : "false");
return out;
}
QJsonObject powerd::stopService(){
ServiceManager SMGR;
Service serv = SMGR.GetService("powerd");
bool ok = SMGR.Stop(serv);
QJsonObject out;
out.insert("stopped", ok ? "true" : "false");
return out;
}
QJsonObject powerd::enableService(){
ServiceManager SMGR;
Service serv = SMGR.GetService("powerd");
bool ok = SMGR.Enable(serv);
QJsonObject out;
out.insert("enabled", ok ? "true" : "false");
return out;
}
QJsonObject powerd::disableService(){
ServiceManager SMGR;
Service serv = SMGR.GetService("powerd");
bool ok = SMGR.Disable(serv);
QJsonObject out;
out.insert("disabled", ok ? "true" : "false");
return out;
}

View File

@@ -0,0 +1,34 @@
//===========================================
// TrueOS source code
// Copyright (c) 2017, TrueOS Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __TRUEOS_SYSADM_UTILS_POWERD_H
#define __TRUEOS_SYSADM_UTILS_POWERD_H
#include <QJsonObject>
#include "sysadm-global.h"
namespace sysadm{
class powerd{
public:
//Service options for individual devices
static QJsonObject listOptions(); //list all the options and possible values
static QJsonObject readOptions(); //current values for device
static QJsonObject setOptions(QJsonObject); //change values for device
//Service status for devices (enable/disable device)
static QJsonObject listStatus();
static QJsonObject startService();
static QJsonObject stopService();
static QJsonObject enableService();
static QJsonObject disableService();
};
} //end of namespace
#endif