mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
api: extend status endpoint
This commit is contained in:
parent
11d1786d9d
commit
8a6902bd90
6 changed files with 184 additions and 19 deletions
|
@ -58,7 +58,46 @@ paths:
|
|||
examples:
|
||||
example1:
|
||||
value:
|
||||
{ test: 1 }
|
||||
state: running
|
||||
version: v0.10.0
|
||||
release: 1.node_uuid_unique_debug.20201015git335440d
|
||||
build_id: v0.10.0-335440d-debug
|
||||
build_date: '20201015'
|
||||
hostname: ernie
|
||||
uuid: c9d64cc7-c6e1-4dd4-8873-126318e9d42c
|
||||
time_now: 1602765814.9240997
|
||||
time_started: 1602765814.3103526
|
||||
timezone:
|
||||
name: CEST
|
||||
offset: -3600
|
||||
dst: true
|
||||
kernel:
|
||||
sysname: Linux
|
||||
nodename: ernie
|
||||
release: 5.6.17-rt10
|
||||
version: "#5 SMP Fri Jul 10 14:02:33 CEST 2020"
|
||||
machine: x86_64
|
||||
domainname: "(none)"
|
||||
system:
|
||||
cores_configured: 28
|
||||
cores: 28
|
||||
procecces: 780
|
||||
uptime: 1379600
|
||||
load:
|
||||
- 1.66259765625
|
||||
- 1.271484375
|
||||
- 1.18701171875
|
||||
ram:
|
||||
total: 269994606592
|
||||
free: 262204465152
|
||||
shared: 44191744
|
||||
buffer: 130211840
|
||||
swap:
|
||||
total: 4294963200
|
||||
free: 4294963200
|
||||
highmem:
|
||||
total: 0
|
||||
free: 0
|
||||
|
||||
"/capabilities":
|
||||
get:
|
||||
|
|
|
@ -78,6 +78,10 @@ protected:
|
|||
|
||||
struct Task task; /**< Task for periodic stats output */
|
||||
|
||||
uuid_t uuid; /**< A globally unique identifier of the instance */
|
||||
|
||||
struct timespec started; /**< The time at which the instance has been started. */
|
||||
|
||||
std::string uri; /**< URI of configuration */
|
||||
|
||||
Config config; /** The configuration file. */
|
||||
|
@ -156,6 +160,16 @@ public:
|
|||
return state;
|
||||
}
|
||||
|
||||
void getUUID(uuid_t out) const
|
||||
{
|
||||
uuid_copy(out, uuid);
|
||||
}
|
||||
|
||||
struct timespec getStartTime() const
|
||||
{
|
||||
return started;
|
||||
}
|
||||
|
||||
#ifdef WITH_API
|
||||
Api * getApi()
|
||||
{
|
||||
|
|
|
@ -89,7 +89,7 @@ void Api::worker()
|
|||
logger->info("Started worker");
|
||||
|
||||
/* Process pending requests */
|
||||
while (!pending.empty() && running) {
|
||||
while (running) {
|
||||
Session *s = pending.pop();
|
||||
if (s) {
|
||||
/* Check that the session is still alive */
|
||||
|
|
|
@ -74,8 +74,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
|
||||
auto *json_capabilities = json_pack("{ s: s, s: o, s: o, s: o, s: o }",
|
||||
"build", PROJECT_BUILD_ID,
|
||||
auto *json_capabilities = json_pack("{ s: o, s: o, s: o, s: o }",
|
||||
"hooks", json_hooks,
|
||||
"node-types", json_nodes,
|
||||
"apis", json_apis,
|
||||
|
|
|
@ -20,27 +20,49 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************************/
|
||||
|
||||
#ifdef LWS_WITH_SERVER_STATUS
|
||||
|
||||
#include <jansson.h>
|
||||
#include <time.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/sysinfo.h>
|
||||
|
||||
#include <villas/timing.h>
|
||||
#include <villas/api/request.hpp>
|
||||
#include <villas/api/response.hpp>
|
||||
|
||||
#ifndef UUID_STR_LEN
|
||||
#define UUID_STR_LEN 37
|
||||
#endif
|
||||
|
||||
namespace villas {
|
||||
namespace node {
|
||||
namespace api {
|
||||
|
||||
class StatusRequest : public Request {
|
||||
|
||||
protected:
|
||||
|
||||
#ifdef LWS_WITH_SERVER_STATUS
|
||||
json_t * getLwsStatus()
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct lws_context *ctx = lws_get_context(session->wsi);
|
||||
char buf[4096];
|
||||
|
||||
ret = lws_json_dump_context(ctx, buf, sizeof(buf), 0);
|
||||
if (ret)
|
||||
throw Error();
|
||||
|
||||
return json_loads(buf, 0, nullptr);
|
||||
}
|
||||
#endif /* LWS_WITH_SERVER_STATUS */
|
||||
|
||||
public:
|
||||
using Request::Request;
|
||||
|
||||
virtual Response * execute()
|
||||
{
|
||||
int ret;
|
||||
struct lws_context *ctx = lws_get_context(s->wsi);
|
||||
char buf[4096];
|
||||
|
||||
if (method != Session::Method::GET)
|
||||
throw InvalidMethod(this);
|
||||
|
@ -48,11 +70,83 @@ public:
|
|||
if (body != nullptr)
|
||||
throw BadRequest("Status endpoint does not accept any body data");
|
||||
|
||||
ret = lws_json_dump_context(ctx, buf, sizeof(buf), 0);
|
||||
if (ret)
|
||||
throw Error();
|
||||
auto *sn = session->getSuperNode();
|
||||
|
||||
auto *json_status = json_loads(buf, 0, nullptr);
|
||||
uuid_t uuid;
|
||||
struct utsname uts;
|
||||
struct sysinfo sinfo;
|
||||
char hname[128];
|
||||
char uuid_str[UUID_STR_LEN];
|
||||
|
||||
sn->getUUID(uuid);
|
||||
uuid_unparse_lower(uuid, uuid_str);
|
||||
|
||||
auto now = time_now();
|
||||
auto started = sn->getStartTime();
|
||||
|
||||
ret = gethostname(hname, sizeof(hname));
|
||||
if (ret)
|
||||
throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get system hostname");
|
||||
|
||||
ret = uname(&uts);
|
||||
if (ret)
|
||||
throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get kernel information");
|
||||
|
||||
ret = sysinfo(&sinfo);
|
||||
if (ret)
|
||||
throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to get system information");
|
||||
|
||||
float f_load = 1.f / (1 << SI_LOAD_SHIFT);
|
||||
|
||||
json_error_t err;
|
||||
json_t *json_status = json_pack_ex(&err, 0, "{ s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: f, s: f, s: { s: s, s: I, s: b }, s: { s: s, s: s, s: s, s: s, s: s, s: s}, s: { s: i, s: i, s: I, s: I, s: [ f, f, f ], s: { s: I, s, I, s: I, s: I }, s: { s: I, s: I }, s: { s: I, s: I } } }",
|
||||
"state", state_print(sn->getState()),
|
||||
"version", PROJECT_VERSION_STR,
|
||||
"release", PROJECT_RELEASE,
|
||||
"build_id", PROJECT_BUILD_ID,
|
||||
"build_date", PROJECT_BUILD_DATE,
|
||||
"hostname", hname,
|
||||
"uuid", uuid_str,
|
||||
"time_now", time_to_double(&now),
|
||||
"time_started", time_to_double(&started),
|
||||
"timezone",
|
||||
"name", tzname[daylight],
|
||||
"offset", (json_int_t) timezone,
|
||||
"dst", daylight,
|
||||
"kernel",
|
||||
"sysname", uts.sysname,
|
||||
"nodename", uts.nodename,
|
||||
"release", uts.release,
|
||||
"version", uts.version,
|
||||
"machine", uts.machine,
|
||||
"domainname", uts.domainname,
|
||||
"system",
|
||||
"cores_configured", get_nprocs_conf(),
|
||||
"cores", get_nprocs(),
|
||||
"procecces", (json_int_t) sinfo.procs,
|
||||
"uptime", (json_int_t) sinfo.uptime,
|
||||
"load",
|
||||
f_load * sinfo.loads[0],
|
||||
f_load * sinfo.loads[1],
|
||||
f_load * sinfo.loads[2],
|
||||
"ram",
|
||||
"total", (json_int_t) (sinfo.totalram * sinfo.mem_unit),
|
||||
"free", (json_int_t) (sinfo.freeram * sinfo.mem_unit),
|
||||
"shared", (json_int_t) (sinfo.sharedram * sinfo.mem_unit),
|
||||
"buffer", (json_int_t) (sinfo.bufferram * sinfo.mem_unit),
|
||||
"swap",
|
||||
"total", (json_int_t) (sinfo.totalswap * sinfo.mem_unit),
|
||||
"free", (json_int_t) (sinfo.freeswap * sinfo.mem_unit),
|
||||
"highmem",
|
||||
"total", (json_int_t) (sinfo.totalhigh * sinfo.mem_unit),
|
||||
"free", (json_int_t) (sinfo.freehigh * sinfo.mem_unit)
|
||||
);
|
||||
if (!json_status)
|
||||
throw Error(HTTP_STATUS_INTERNAL_SERVER_ERROR, "Failed to prepare response: {}", err.text);
|
||||
|
||||
#ifdef LWS_WITH_SERVER_STATUS
|
||||
json_object_set(json_status, "lws", getLwsStatus());
|
||||
#endif /* LWS_WITH_SERVER_STATUS */
|
||||
|
||||
return new Response(session, json_status);
|
||||
}
|
||||
|
@ -68,4 +162,3 @@ static RequestPlugin<StatusRequest, n, r, d> p;
|
|||
} /* namespace node */
|
||||
} /* namespace villas */
|
||||
|
||||
#endif /* LWS_WITH_SERVER_STATUS */
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <villas/memory.h>
|
||||
#include <villas/config_helper.hpp>
|
||||
#include <villas/log.hpp>
|
||||
#include <villas/timing.h>
|
||||
#include <villas/node/exceptions.hpp>
|
||||
#include <villas/kernel/rt.hpp>
|
||||
#include <villas/kernel/if.hpp>
|
||||
|
@ -48,7 +49,7 @@ using namespace villas::utils;
|
|||
|
||||
SuperNode::SuperNode() :
|
||||
state(State::INITIALIZED),
|
||||
idleStop(true),
|
||||
idleStop(-1),
|
||||
#ifdef WITH_API
|
||||
api(this),
|
||||
#endif
|
||||
|
@ -63,10 +64,18 @@ SuperNode::SuperNode() :
|
|||
affinity(0),
|
||||
hugepages(DEFAULT_NR_HUGEPAGES),
|
||||
statsRate(1.0),
|
||||
task(CLOCK_REALTIME)
|
||||
task(CLOCK_REALTIME),
|
||||
started(time_now())
|
||||
{
|
||||
int ret;
|
||||
|
||||
char hname[128];
|
||||
ret = gethostname(hname, sizeof(hname));
|
||||
if (ret)
|
||||
throw SystemError("Failed to determine hostname");
|
||||
|
||||
uuid_generate_from_str(uuid, hname);
|
||||
|
||||
ret = vlist_init(&nodes);
|
||||
if (ret)
|
||||
throw RuntimeError("Failed to initialize list");
|
||||
|
@ -95,6 +104,8 @@ void SuperNode::parse(json_t *root)
|
|||
|
||||
assert(state != State::STARTED);
|
||||
|
||||
const char *uuid_str = nullptr;
|
||||
|
||||
json_t *json_nodes = nullptr;
|
||||
json_t *json_paths = nullptr;
|
||||
json_t *json_logging = nullptr;
|
||||
|
@ -102,7 +113,9 @@ void SuperNode::parse(json_t *root)
|
|||
|
||||
json_error_t err;
|
||||
|
||||
ret = json_unpack_ex(root, &err, 0, "{ s?: F, s?: o, s?: o, s?: o, s?: o, s?: i, s?: i, s?: i, s?: b }",
|
||||
idleStop = 1;
|
||||
|
||||
ret = json_unpack_ex(root, &err, 0, "{ s?: F, s?: o, s?: o, s?: o, s?: o, s?: i, s?: i, s?: i, s?: b, s?: s }",
|
||||
"stats", &statsRate,
|
||||
"http", &json_http,
|
||||
"logging", &json_logging,
|
||||
|
@ -111,11 +124,18 @@ void SuperNode::parse(json_t *root)
|
|||
"hugepages", &hugepages,
|
||||
"affinity", &affinity,
|
||||
"priority", &priority,
|
||||
"idle_stop", &idleStop
|
||||
"idle_stop", &idleStop,
|
||||
"uuid", &uuid_str
|
||||
);
|
||||
if (ret)
|
||||
throw ConfigError(root, err, "node-config", "Unpacking top-level config failed");
|
||||
|
||||
if (uuid_str) {
|
||||
ret = uuid_parse(uuid_str, uuid);
|
||||
if (ret)
|
||||
throw ConfigError(root, "node-config-uuid", "Failed to parse UUID: {}", uuid_str);
|
||||
}
|
||||
|
||||
#ifdef WITH_WEB
|
||||
if (json_http)
|
||||
web.parse(json_http);
|
||||
|
@ -502,7 +522,7 @@ int SuperNode::periodic()
|
|||
}
|
||||
}
|
||||
|
||||
if (idleStop && state == State::STARTED && started == 0) {
|
||||
if (idleStop > 0 && state == State::STARTED && started == 0) {
|
||||
info("No more active paths. Stopping super-node");
|
||||
|
||||
return -1;
|
||||
|
|
Loading…
Add table
Reference in a new issue