ubus: add api for modifying node script data
authorFelix Fietkau <nbd@nbd.name>
Tue, 6 Jul 2021 08:29:20 +0000 (10:29 +0200)
committerFelix Fietkau <nbd@nbd.name>
Tue, 6 Jul 2021 09:10:47 +0000 (11:10 +0200)
This is replicated across nodes

Signed-off-by: Felix Fietkau <nbd@nbd.name>
local_node.c
node.h
ubus.c
usteer.h

index 31c33779bca1a0f0c32fab75b4da8bb9493895c8..f1bc38558e68708a4bb131380191074c37f93446 100644 (file)
@@ -62,6 +62,7 @@ usteer_free_node(struct ubus_context *ctx, struct usteer_local_node *ln)
        uloop_timeout_cancel(&ln->update);
        avl_delete(&local_nodes, &ln->node.avl);
        ubus_unregister_subscriber(ctx, &ln->ev);
+       kvlist_free(&ln->script_data);
        free(ln);
 }
 
@@ -374,6 +375,7 @@ usteer_get_node(struct ubus_context *ctx, const char *name)
        ln->req_timer.cb = usteer_local_node_state_next;
        ubus_register_subscriber(ctx, &ln->ev);
        avl_insert(&local_nodes, &node->avl);
+       kvlist_init(&ln->script_data, kvlist_blob_len);
        INIT_LIST_HEAD(&node->sta_info);
 
        return ln;
@@ -504,6 +506,23 @@ node_list_cb(struct ubus_context *ctx, struct ubus_object_data *obj, void *priv)
        usteer_register_node(ctx, obj->path, obj->id);
 }
 
+void usteer_local_node_update_script_data(struct usteer_local_node *ln)
+{
+       struct blob_attr *val;
+       const char *name;
+
+       blob_buf_init(&b, 0);
+       kvlist_for_each(&ln->script_data, name, val)
+               blobmsg_add_field(&b, blobmsg_type(val), name,
+                                 blobmsg_data(val), blobmsg_len(val));
+
+       val = b.head;
+       if (!blobmsg_len(val))
+               val = NULL;
+
+       usteer_node_set_blob(&ln->node.script_data, val);
+}
+
 void config_set_node_up_script(struct blob_attr *data)
 {
        const char *val;
diff --git a/node.h b/node.h
index 34b030ae7c6be45978283b5bb1e66901f874da60..7d60528f435f8fed75b9f9ad5ca70371b1373f62 100644 (file)
--- a/node.h
+++ b/node.h
@@ -51,6 +51,8 @@ struct usteer_local_node {
 
        uint64_t time, time_busy;
 
+       struct kvlist script_data;
+
        struct {
                bool present;
                struct uloop_timeout update;
diff --git a/ubus.c b/ubus.c
index 8c6711a73bd72f8353411f8c4610e638028edd2d..7abc7dc15443e5b7ec6cb2af0686182bf9017570 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -323,6 +323,79 @@ usteer_ubus_remote_info(struct ubus_context *ctx, struct ubus_object *obj,
        return 0;
 }
 
+enum {
+       NODE_DATA_NODE,
+       NODE_DATA_VALUES,
+       __NODE_DATA_MAX,
+};
+
+static const struct blobmsg_policy set_node_data_policy[] = {
+       [NODE_DATA_NODE] = { "node", BLOBMSG_TYPE_STRING },
+       [NODE_DATA_VALUES] = { "data", BLOBMSG_TYPE_TABLE },
+};
+
+static const struct blobmsg_policy del_node_data_policy[] = {
+       [NODE_DATA_NODE] = { "node", BLOBMSG_TYPE_STRING },
+       [NODE_DATA_VALUES] = { "names", BLOBMSG_TYPE_ARRAY },
+};
+
+static void
+__usteer_ubus_update_node_data(struct usteer_local_node *ln, struct blob_attr *data,
+                              bool delete)
+{
+       struct blob_attr *cur;
+       int rem;
+
+       blobmsg_for_each_attr(cur, data, rem) {
+               if (delete)
+                       kvlist_delete(&ln->script_data, blobmsg_get_string(cur));
+               else
+                       kvlist_set(&ln->script_data, blobmsg_name(cur), cur);
+       }
+
+       usteer_local_node_update_script_data(ln);
+}
+
+static int
+usteer_ubus_update_node_data(struct ubus_context *ctx, struct ubus_object *obj,
+                            struct ubus_request_data *req, const char *method,
+                            struct blob_attr *msg)
+{
+       const struct blobmsg_policy *policy;
+       struct blob_attr *tb[__NODE_DATA_MAX];
+       struct usteer_local_node *ln;
+       struct blob_attr *val;
+       const char *name;
+       bool delete;
+
+       delete = !strncmp(method, "del", 3);
+       policy = delete ? del_node_data_policy : set_node_data_policy;
+
+       blobmsg_parse(policy, __NODE_DATA_MAX, tb, blob_data(msg), blob_len(msg));
+       if (!tb[NODE_DATA_NODE] || !tb[NODE_DATA_VALUES])
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       name = blobmsg_get_string(tb[NODE_DATA_NODE]);
+       val = tb[NODE_DATA_VALUES];
+       if (delete && blobmsg_check_array(val, BLOBMSG_TYPE_STRING) < 0)
+               return UBUS_STATUS_INVALID_ARGUMENT;
+
+       if (strcmp(name, "*") != 0) {
+               ln = avl_find_element(&local_nodes, name, ln, node.avl);
+               if (!ln)
+                       return UBUS_STATUS_NOT_FOUND;
+
+               __usteer_ubus_update_node_data(ln, val, delete);
+
+               return 0;
+       }
+
+       avl_for_each_element(&local_nodes, ln, node.avl)
+               __usteer_ubus_update_node_data(ln, val, delete);
+
+       return 0;
+}
+
 static const struct ubus_method usteer_methods[] = {
        UBUS_METHOD_NOARG("local_info", usteer_ubus_local_info),
        UBUS_METHOD_NOARG("remote_info", usteer_ubus_remote_info),
@@ -331,6 +404,8 @@ static const struct ubus_method usteer_methods[] = {
        UBUS_METHOD_NOARG("get_config", usteer_ubus_get_config),
        UBUS_METHOD("set_config", usteer_ubus_set_config, config_policy),
        UBUS_METHOD("update_config", usteer_ubus_set_config, config_policy),
+       UBUS_METHOD("set_node_data", usteer_ubus_update_node_data, set_node_data_policy),
+       UBUS_METHOD("delete_node_data", usteer_ubus_update_node_data, del_node_data_policy),
 };
 
 static struct ubus_object_type usteer_obj_type =
index b3c2b99b5fb2281cd585cfcf85a7ffd99821b39a..c28fac08ff0a769f325db60542a456aef6b088a4 100644 (file)
--- a/usteer.h
+++ b/usteer.h
@@ -24,6 +24,7 @@
 #include <libubox/blobmsg.h>
 #include <libubox/uloop.h>
 #include <libubox/utils.h>
+#include <libubox/kvlist.h>
 #include <libubus.h>
 #include "utils.h"
 #include "timeout.h"
@@ -229,6 +230,7 @@ bool usteer_handle_sta_event(struct usteer_node *node, const uint8_t *addr,
 
 void usteer_local_nodes_init(struct ubus_context *ctx);
 void usteer_local_node_kick(struct usteer_local_node *ln);
+void usteer_local_node_update_script_data(struct usteer_local_node *ln);
 
 void usteer_ubus_init(struct ubus_context *ctx);
 void usteer_ubus_kick_client(struct sta_info *si);