From 7708980e2d47d7373e56208781d58776bf85c102 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 16 Oct 2020 11:08:40 +0200 Subject: [PATCH 1/2] derive auto-generated uuid for nodes, paths and relay-sessions from instance uuid --- include/villas/node.h | 2 +- include/villas/path.h | 2 +- lib/api/requests/status.cpp | 6 ++-- lib/node.cpp | 19 +++++++---- lib/path.cpp | 4 +-- lib/super_node.cpp | 7 ++-- src/villas-relay.cpp | 64 ++++++++++++++++++++++++++----------- src/villas-relay.hpp | 28 ++++++++-------- src/villas-signal.cpp | 5 ++- 9 files changed, 85 insertions(+), 52 deletions(-) diff --git a/include/villas/node.h b/include/villas/node.h index 671347d74..ceb9286bf 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -112,7 +112,7 @@ int node_prepare(struct vnode *n); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -int node_parse(struct vnode *n, json_t *cfg, const char *name); +int node_parse(struct vnode *n, json_t *cfg, const uuid_t sn_uuid); /** Parse an array or single node and checks if they exist in the "nodes" section. * diff --git a/include/villas/path.h b/include/villas/path.h index bd3ec8067..df4b302f2 100644 --- a/include/villas/path.h +++ b/include/villas/path.h @@ -155,7 +155,7 @@ int path_reverse(struct vpath *p, struct vpath *r); * @retval 0 Success. Everything went well. * @retval <0 Error. Something went wrong. */ -int path_parse(struct vpath *p, json_t *cfg, struct vlist *nodes); +int path_parse(struct vpath *p, json_t *cfg, struct vlist *nodes, const uuid_t sn_uuid); void path_parse_mask(struct vpath *p, json_t *json_mask, struct vlist *nodes); diff --git a/lib/api/requests/status.cpp b/lib/api/requests/status.cpp index 336522670..474da7c9f 100644 --- a/lib/api/requests/status.cpp +++ b/lib/api/requests/status.cpp @@ -29,9 +29,7 @@ #include #include -#ifndef UUID_STR_LEN - #define UUID_STR_LEN 37 -#endif +typedef char uuid_string_t[37]; namespace villas { namespace node { @@ -73,10 +71,10 @@ public: auto *sn = session->getSuperNode(); uuid_t uuid; + uuid_string_t uuid_str; struct utsname uts; struct sysinfo sinfo; char hname[128]; - char uuid_str[UUID_STR_LEN]; sn->getUUID(uuid); uuid_unparse_lower(uuid, uuid_str); diff --git a/lib/node.cpp b/lib/node.cpp index 3ed189730..6677a4d03 100644 --- a/lib/node.cpp +++ b/lib/node.cpp @@ -133,7 +133,7 @@ int node_prepare(struct vnode *n) return 0; } -int node_parse(struct vnode *n, json_t *json, const char *name) +int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid) { int ret, enabled = n->enabled; @@ -141,18 +141,16 @@ int node_parse(struct vnode *n, json_t *json, const char *name) json_t *json_netem = nullptr; const char *uuid_str = nullptr; + const char *name_str = nullptr; - n->name = strdup(name); - - ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: b }", + ret = json_unpack_ex(json, &err, 0, "{ s?: s, s?: s, s?: b }", + "name", &name_str, "uuid", &uuid_str, "enabled", &enabled ); if (ret) return ret; - n->enabled = enabled; - #ifdef __linux__ ret = json_unpack_ex(json, &err, 0, "{ s?: { s?: o, s?: i } }", "out", @@ -163,6 +161,13 @@ int node_parse(struct vnode *n, json_t *json, const char *name) return ret; #endif /* __linux__ */ + n->enabled = enabled; + + if (name_str) + n->name = strdup(name_str); + else + n->name = strdup(""); + if (uuid_str) { ret = uuid_parse(uuid_str, n->uuid); if (ret) @@ -170,7 +175,7 @@ int node_parse(struct vnode *n, json_t *json, const char *name) } else /* Generate UUID from hashed config including node name */ - uuid_generate_from_json(n->uuid, json, name); + uuid_generate_from_json(n->uuid, json, sn_uuid); if (json_netem) { #ifdef WITH_NETEM diff --git a/lib/path.cpp b/lib/path.cpp index 4e2d33eb7..000a66421 100644 --- a/lib/path.cpp +++ b/lib/path.cpp @@ -386,7 +386,7 @@ int path_prepare(struct vpath *p, struct vlist *nodes) return 0; } -int path_parse(struct vpath *p, json_t *cfg, struct vlist *nodes) +int path_parse(struct vpath *p, json_t *cfg, struct vlist *nodes, const uuid_t sn_uuid) { int ret; @@ -442,7 +442,7 @@ int path_parse(struct vpath *p, json_t *cfg, struct vlist *nodes) } else /* Generate UUID from hashed config */ - uuid_generate_from_json(p->uuid, cfg); + uuid_generate_from_json(p->uuid, cfg, sn_uuid); /* Input node(s) */ ret = mapping_list_parse(&p->mappings, json_in); diff --git a/lib/super_node.cpp b/lib/super_node.cpp index 5af5ea95c..b9327109c 100644 --- a/lib/super_node.cpp +++ b/lib/super_node.cpp @@ -74,6 +74,7 @@ SuperNode::SuperNode() : if (ret) throw SystemError("Failed to determine hostname"); + /* Default UUID is derived from hostname */ uuid_generate_from_str(uuid, hname); ret = vlist_init(&nodes); @@ -163,6 +164,8 @@ void SuperNode::parse(json_t *root) if (ret) throw ConfigError(root, err, "node-config-node-type", "Failed to parse type of node '{}'", name); + json_object_set(json_node, "name", json_string(name)); + nt = node_type_lookup(type); if (!nt) throw ConfigError(json_node, "node-config-node-type", "Invalid node type: {}", type); @@ -175,7 +178,7 @@ void SuperNode::parse(json_t *root) if (ret) throw RuntimeError("Failed to initialize node"); - ret = node_parse(n, json_node, name); + ret = node_parse(n, json_node, uuid); if (ret) { auto config_id = fmt::format("node-config-node-{}", type); @@ -202,7 +205,7 @@ parse: auto *p = new vpath; if (ret) throw RuntimeError("Failed to initialize path"); - ret = path_parse(p, json_path, &nodes); + ret = path_parse(p, json_path, &nodes, uuid); if (ret) throw RuntimeError("Failed to parse path"); diff --git a/src/villas-relay.cpp b/src/villas-relay.cpp index 206ebea5d..5e9714671 100644 --- a/src/villas-relay.cpp +++ b/src/villas-relay.cpp @@ -30,21 +30,26 @@ #include #include +#include #include #include #include #include #include +#include #include "villas-relay.hpp" +typedef char uuid_string_t[37]; + +using namespace villas::utils; namespace villas { namespace node { namespace tools { -RelaySession::RelaySession(Identifier sid) : +RelaySession::RelaySession(Relay *r, Identifier sid) : identifier(sid), connects(0) { @@ -56,7 +61,7 @@ RelaySession::RelaySession(Identifier sid) : created = time(nullptr); - uuid_generate(uuid); + uuid_generate_from_str(uuid, identifier, r->uuid); } RelaySession::~RelaySession() @@ -68,7 +73,7 @@ RelaySession::~RelaySession() sessions.erase(identifier); } -RelaySession * RelaySession::get(lws *wsi) +RelaySession * RelaySession::get(Relay *r, lws *wsi) { Logger logger = villas::logging.get("console"); @@ -88,7 +93,7 @@ RelaySession * RelaySession::get(lws *wsi) auto it = sessions.find(sid); if (it == sessions.end()) { - auto *rs = new RelaySession(sid); + auto *rs = new RelaySession(r, sid); if (!rs) throw MemoryAllocationError(); @@ -111,7 +116,7 @@ json_t * RelaySession::toJson() const json_array_append(json_connections, conn->toJson()); } - char uuid_str[UUID_STR_LEN]; + uuid_string_t uuid_str; uuid_unparse_lower(uuid, uuid_str); return json_pack("{ s: s, s: s, s: o, s: I, s: i }", @@ -125,7 +130,7 @@ json_t * RelaySession::toJson() const std::map RelaySession::sessions; -RelayConnection::RelayConnection(lws *w, bool lo) : +RelayConnection::RelayConnection(Relay *r, lws *w, bool lo) : wsi(w), currentFrame(std::make_shared()), outgoingFrames(), @@ -137,7 +142,7 @@ RelayConnection::RelayConnection(lws *w, bool lo) : { Logger logger = villas::logging.get("console"); - session = RelaySession::get(wsi); + session = RelaySession::get(r, wsi); session->connections[wsi] = this; session->connects++; @@ -232,13 +237,23 @@ Relay::Relay(int argc, char *argv[]) : { int ret; + char hname[128]; + ret = gethostname(hname, sizeof(hname)); + if (ret) + throw SystemError("Failed to get hostname"); + + hostname = hname; + + /* Default UUID is derived from hostname */ + uuid_generate_from_str(uuid, hname); + ret = memory_init(0); if (ret) throw RuntimeError("Failed to initialize memory"); /* Initialize logging */ spdlog::stdout_color_mt("lws"); - lws_set_log_level((1 << LLL_COUNT) - 1, logger_cb); + lws_set_log_level((1 << LLL_COUNT) - 1, loggerCallback); protocols = { { @@ -249,13 +264,13 @@ Relay::Relay(int argc, char *argv[]) : }, { .name = "http-api", - .callback = http_protocol_cb, + .callback = httpProtocolCallback, .per_session_data_size = 0, .rx_buffer_size = 1024 }, { .name = "live", - .callback = protocol_cb, + .callback = protocolCallback, .per_session_data_size = sizeof(RelayConnection), .rx_buffer_size = 0 }, @@ -263,7 +278,7 @@ Relay::Relay(int argc, char *argv[]) : }; } -void Relay::logger_cb(int level, const char *msg) +void Relay::loggerCallback(int level, const char *msg) { auto log = spdlog::get("lws"); @@ -294,7 +309,7 @@ void Relay::logger_cb(int level, const char *msg) } } -int Relay::http_protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +int Relay::httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { int ret; size_t json_len; @@ -332,13 +347,14 @@ int Relay::http_protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *us json_array_append(json_sessions, session->toJson()); } - char hname[128]; - gethostname(hname, 128); + uuid_string_t uuid_str; + uuid_unparse(r->uuid, uuid_str); - json_body = json_pack("{ s: o, s: s, s: s, s: { s: b, s: i, s: s } }", + json_body = json_pack("{ s: o, s: s, s: s, s: s, s: { s: b, s: i, s: s } }", "sessions", json_sessions, "version", PROJECT_VERSION_STR, - "hostname", hname, + "hostname", r->hostname.c_str(), + "uuid", uuid_str, "options", "loopback", r->loopback, "port", r->port, @@ -363,7 +379,7 @@ int Relay::http_protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *us return lws_callback_http_dummy(wsi, reason, user, in, len); } -int Relay::protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +int Relay::protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { lws_context *ctx = lws_get_context(wsi); void *user_ctx = lws_context_user(ctx); @@ -375,7 +391,7 @@ int Relay::protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *user, v case LWS_CALLBACK_ESTABLISHED: try { - new (c) RelayConnection(wsi, r->loopback); + new (c) RelayConnection(r, wsi, r->loopback); } catch (const InvalidUrlException &e) { lws_close_reason(wsi, LWS_CLOSE_STATUS_PROTOCOL_ERR, (unsigned char *) "Invalid URL", strlen("Invalid URL")); @@ -411,6 +427,7 @@ void Relay::usage() << " -p PORT the port number to listen on" << std::endl << " -P PROT the websocket protocol" << std::endl << " -l enable loopback of own data" << std::endl + << " -u UUID unique instance id" << std::endl << " -V show version and exit" << std::endl << " -h show usage and exit" << std::endl << std::endl; @@ -419,8 +436,9 @@ void Relay::usage() void Relay::parse() { + int ret; char c, *endptr; - while ((c = getopt (argc, argv, "hVp:P:ld:")) != -1) { + while ((c = getopt (argc, argv, "hVp:P:ld:u:")) != -1) { switch (c) { case 'd': spdlog::set_level(spdlog::level::from_str(optarg)); @@ -438,6 +456,14 @@ void Relay::parse() loopback = true; break; + case 'u': + ret = uuid_parse(optarg, uuid); + if (ret) { + logger->error("Failed to parse UUID: {}", optarg); + exit(EXIT_FAILURE); + } + break; + case 'V': printVersion(); exit(EXIT_SUCCESS); diff --git a/src/villas-relay.hpp b/src/villas-relay.hpp index 0c8c297d2..1e38bf8e1 100644 --- a/src/villas-relay.hpp +++ b/src/villas-relay.hpp @@ -27,10 +27,6 @@ #include #include -#ifndef UUID_STR_LEN - #define UUID_STR_LEN 37 -#endif - #include namespace villas { @@ -38,13 +34,14 @@ namespace node { namespace tools { /* Forward declarations */ -lws_callback_function protocol_cb, http_protocol_cb; class Relay; class RelaySession; class RelayConnection; class InvalidUrlException { }; +typedef std::string Identifier; + class Frame : public std::vector { public: Frame() { @@ -66,14 +63,10 @@ class RelaySession { friend RelayConnection; friend Relay; -public: - typedef std::string Identifier; - protected: time_t created; uuid_t uuid; - Identifier identifier; std::map connections; @@ -83,9 +76,9 @@ protected: static std::map sessions; public: - static RelaySession * get(lws *wsi); + static RelaySession * get(Relay *r, lws *wsi); - RelaySession(Identifier sid); + RelaySession(Relay *r, Identifier sid); ~RelaySession(); @@ -116,7 +109,7 @@ protected: bool loopback; public: - RelayConnection(lws *w, bool lo); + RelayConnection(Relay *r, lws *w, bool lo); ~RelayConnection(); json_t * toJson() const; @@ -128,6 +121,8 @@ public: class Relay : public Tool { public: + friend RelaySession; + Relay(int argc, char *argv[]); protected: @@ -142,6 +137,9 @@ protected: bool loopback; int port; std::string protocol; + std::string hostname; + + uuid_t uuid; /** List of libwebsockets protocols. */ std::vector protocols; @@ -151,11 +149,11 @@ protected: static const lws_http_mount mount; - static void logger_cb(int level, const char *msg); + static void loggerCallback(int level, const char *msg); - static int http_protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int httpProtocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); - static int protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int protocolCallback(lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); void usage(); diff --git a/src/villas-signal.cpp b/src/villas-signal.cpp index 1499403b1..ead053a30 100644 --- a/src/villas-signal.cpp +++ b/src/villas-signal.cpp @@ -235,7 +235,10 @@ check: if (optarg == endptr) exit(EXIT_FAILURE); } - ret = node_parse(&n, cfg, "cli"); + uuid_t uuid; + uuid_clear(uuid); + + ret = node_parse(&n, cfg, uuid); if (ret) { usage(); exit(EXIT_FAILURE); From ca8cb9523f6d96f4cfeb8f051e9491eba51669b2 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 16 Oct 2020 11:13:39 +0200 Subject: [PATCH 2/2] update VILLAScommon submodule --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 3f3296e01..db106f50e 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 3f3296e01752eddc02c077cb9a7e43171f69c75e +Subproject commit db106f50e053dc48c739c65e352d8885415e460b