diff --git a/dm-service/dm_service.c b/dm-service/dm_service.c index 09369e39..16f175e3 100644 --- a/dm-service/dm_service.c +++ b/dm-service/dm_service.c @@ -27,7 +27,7 @@ static void usage(char *prog) int main(int argc, char **argv) { struct bbfdm_context bbfdm_ctx = {0}; - char proc_name[32] = {0}; + char proc_name[64] = {0}; int log_level = 3; // Default is LOG_ERR int err = 0, ch; diff --git a/gitlab-ci/setup.sh b/gitlab-ci/setup.sh index 2a664bb8..01eebdbb 100755 --- a/gitlab-ci/setup.sh +++ b/gitlab-ci/setup.sh @@ -30,3 +30,5 @@ echo "Starting base services..." supervisorctl reread supervisorctl update sleep 10 + +ubus list diff --git a/gitlab-ci/unit-test.sh b/gitlab-ci/unit-test.sh index ab94d6c3..1ab43048 100755 --- a/gitlab-ci/unit-test.sh +++ b/gitlab-ci/unit-test.sh @@ -7,7 +7,7 @@ pwd echo "Starting supervisor" supervisorctl stop all sleep 1 -supervisorctl start ubusd rpcd bbf.config +supervisorctl start ubusd rpcd bbf.config netmngr sysmngr sleep 3 supervisorctl status all diff --git a/libbbfdm-api/dmentry.h b/libbbfdm-api/dmentry.h index ee9acde5..a81c6561 100644 --- a/libbbfdm-api/dmentry.h +++ b/libbbfdm-api/dmentry.h @@ -35,7 +35,7 @@ bool adm_entry_object_exists(struct dmctx *ctx, const char *param); // To be rem void bbf_entry_services(unsigned int proto, bool is_commit, bool reload_required); void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf *bb); -bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_name, const char *srv_parent_dm, const char *srv_obj); +bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_name, const char *srv_parent_dm, const char *srv_obj, bool is_unified); void free_services_from_list(struct list_head *clist); #endif //__DMENTRY_H__ diff --git a/libbbfdm-api/dmplugin.c b/libbbfdm-api/dmplugin.c index cfe22db1..a2e3c631 100644 --- a/libbbfdm-api/dmplugin.c +++ b/libbbfdm-api/dmplugin.c @@ -18,6 +18,7 @@ extern struct list_head global_memhead; struct service { + bool is_unified_daemon; struct list_head list; char *name; char *parent_dm; @@ -73,7 +74,7 @@ static bool is_service_registered(struct list_head *srvlist, const char *srv_nam return false; } -static void add_service_to_list(struct list_head *srvlist, const char *srv_name, const char *srv_parent_dm, const char *srv_object) +static void add_service_to_list(struct list_head *srvlist, const char *srv_name, const char *srv_parent_dm, const char *srv_object, bool is_unified) { struct service *srv = NULL; @@ -83,6 +84,7 @@ static void add_service_to_list(struct list_head *srvlist, const char *srv_name, srv->name = strdup(srv_name); srv->parent_dm = strdup(srv_parent_dm); srv->object = strdup(srv_object); + srv->is_unified_daemon = is_unified; } void free_services_from_list(struct list_head *clist) @@ -98,7 +100,7 @@ void free_services_from_list(struct list_head *clist) } } -bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_name, const char *srv_parent_dm, const char *srv_obj) +bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_name, const char *srv_parent_dm, const char *srv_obj, bool is_unified) { if (!main_dm || !srv_list || !srv_name || !srv_parent_dm || !srv_obj) { BBF_ERR("Invalid arguments: main_dm, srv_list, srv_name, srv_parent_dm, and srv_obj must not be NULL."); @@ -117,7 +119,7 @@ bool load_service(DMOBJ *main_dm, struct list_head *srv_list, const char *srv_na return false; } - add_service_to_list(srv_list, srv_name, srv_parent_dm, srv_obj); + add_service_to_list(srv_list, srv_name, srv_parent_dm, srv_obj, is_unified); return true; } @@ -131,6 +133,7 @@ void get_list_of_registered_service(struct list_head *srvlist, struct blob_buf * blobmsg_add_string(bb, "name", srv->name); blobmsg_add_string(bb, "parent_dm", srv->parent_dm); blobmsg_add_string(bb, "object", srv->object); + blobmsg_add_u8(bb, "unified_daemon", srv->is_unified_daemon); blobmsg_close_table(bb, table); } } diff --git a/libbbfdm-ubus/bbfdm-ubus.c b/libbbfdm-ubus/bbfdm-ubus.c index c59d7c3f..7cdb0d6b 100644 --- a/libbbfdm-ubus/bbfdm-ubus.c +++ b/libbbfdm-ubus/bbfdm-ubus.c @@ -28,7 +28,7 @@ #include "get_helper.h" #include "plugin.h" -#define BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH "/etc/bbfdm/micro_services" +#define BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH "/etc/bbfdm/services" #define BBFDM_DEFAULT_MODULES_PATH "/usr/share/bbfdm" #define BBFDM_DEFAULT_PLUGINS_PATH BBFDM_DEFAULT_MODULES_PATH"/plugins" #define BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH BBFDM_DEFAULT_MODULES_PATH"/micro_services" @@ -710,21 +710,6 @@ int bbfdm_del_handler(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -enum { - BBF_SERVICE_CMD, - BBF_SERVICE_NAME, - BBF_SERVICE_PARENT_DM, - BBF_SERVICE_OBJECTS, - __BBF_SERVICE_MAX, -}; - -static const struct blobmsg_policy service_policy[] = { - [BBF_SERVICE_CMD] = { .name = "cmd", .type = BLOBMSG_TYPE_STRING }, - [BBF_SERVICE_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, - [BBF_SERVICE_PARENT_DM] = { .name = "parent_dm", .type = BLOBMSG_TYPE_STRING }, - [BBF_SERVICE_OBJECTS] = { .name = "objects", .type = BLOBMSG_TYPE_ARRAY }, -}; - static void service_list(struct blob_buf *bb) { void *array; @@ -743,7 +728,6 @@ static int bbfdm_service_handler(struct ubus_context *ctx, struct ubus_object *o struct ubus_request_data *req __attribute__((unused)), const char *method, struct blob_attr *msg) { - struct blob_attr *tb[__BBF_SERVICE_MAX] = {NULL}; struct blob_buf bb; struct bbfdm_context *u; @@ -756,11 +740,6 @@ static int bbfdm_service_handler(struct ubus_context *ctx, struct ubus_object *o memset(&bb, 0, sizeof(struct blob_buf)); blob_buf_init(&bb, 0); - if (blobmsg_parse(service_policy, __BBF_SERVICE_MAX, tb, blob_data(msg), blob_len(msg))) { - service_list(&bb); - goto end; - } - BBF_INFO("ubus method|%s|, name|%s|", method, obj->name); if (dm_is_micro_service() == true) { // It's a micro-service instance @@ -768,52 +747,7 @@ static int bbfdm_service_handler(struct ubus_context *ctx, struct ubus_object *o goto end; } - if (!tb[BBF_SERVICE_CMD]) { - service_list(&bb); - goto end; - } - - char *srv_cmd = blobmsg_get_string(tb[BBF_SERVICE_CMD]); - - if (is_str_eq(srv_cmd, "register")) { - - if (!tb[BBF_SERVICE_NAME]) { - blobmsg_add_string(&bb, "error", "service name should be defined!!"); - goto end; - } - - if (!tb[BBF_SERVICE_PARENT_DM]) { - blobmsg_add_string(&bb, "error", "service parent dm should be defined!!"); - goto end; - } - - if (!tb[BBF_SERVICE_OBJECTS]) { - blobmsg_add_string(&bb, "error", "service objects should be defined!!"); - goto end; - } - - char *srv_name = blobmsg_get_string(tb[BBF_SERVICE_NAME]); - char *srv_parent_dm = blobmsg_get_string(tb[BBF_SERVICE_PARENT_DM]); - bool res = true; - - if (tb[BBF_SERVICE_OBJECTS]) { - struct blob_attr *objs = tb[BBF_SERVICE_OBJECTS]; - struct blob_attr *attr_obj = NULL; - size_t rem; - - blobmsg_for_each_attr(attr_obj, objs, rem) { - char *srv_obj = blobmsg_get_string(attr_obj); - res |= load_service(DEAMON_DM_ROOT_OBJ, &head_registered_service, srv_name, srv_parent_dm, srv_obj); - } - } else { - res = false; - } - - blobmsg_add_u8(&bb, "status", res); - run_schema_updater(u); - } else { - service_list(&bb); - } + service_list(&bb); end: ubus_send_reply(ctx, req, bb.head); @@ -870,8 +804,8 @@ static struct ubus_method bbf_methods[] = { UBUS_METHOD("operate", bbfdm_operate_handler, dm_operate_policy), UBUS_METHOD("add", bbfdm_add_handler, dm_add_policy), UBUS_METHOD("del", bbfdm_del_handler, dm_del_policy), - UBUS_METHOD("service", bbfdm_service_handler, service_policy), UBUS_METHOD("notify_event", bbfdm_notify_event, dm_notify_event_policy), + UBUS_METHOD_NOARG("service", bbfdm_service_handler), }; static struct ubus_object_type bbf_type = UBUS_OBJECT_TYPE("", bbf_methods); @@ -1021,44 +955,6 @@ static void periodic_instance_updater(struct uloop_timeout *t) } } -static int register_service(struct ubus_context *ctx) -{ - struct blob_buf bb = {0}; - uint32_t ubus_id; - struct bbfdm_context *u; - struct pathNode *pn = NULL; - - u = container_of(ctx, struct bbfdm_context, ubus_ctx); - if (u == NULL) { - BBF_ERR("failed to get the bbfdm context"); - return false; - } - // check if object already present - int ret = ubus_lookup_id(ctx, u->config.out_root_obj, &ubus_id); - if (ret != 0) - return ret; - - memset(&bb, 0, sizeof(struct blob_buf)); - blob_buf_init(&bb, 0); - - blobmsg_add_string(&bb, "cmd", "register"); - blobmsg_add_string(&bb, "name", u->config.out_name); - blobmsg_add_string(&bb, "parent_dm", u->config.out_parent_dm); - - void *arr = blobmsg_open_array(&bb, "objects"); - - list_for_each_entry(pn, &u->config.list_objs, list) { - blobmsg_add_string(&bb, NULL, pn->path); - } - - blobmsg_close_array(&bb, arr); - - ubus_invoke(ctx, ubus_id, "service", bb.head, NULL, NULL, 5000); - blob_buf_free(&bb); - - return 0; -} - static int _fill_daemon_input_option(json_object *daemon_obj, bbfdm_config_t *config) { char opt_val[MAX_DM_PATH] = {0}; @@ -1190,6 +1086,67 @@ static int daemon_load_config_internal_plugin(bbfdm_config_t *config) return 0; } +static int daemon_load_services(const char *name, const char *json_path) +{ + json_object *json_obj = NULL; + json_object *jserv = NULL, *jservices = NULL; + int idx = 0, err = 0; + char buffer[MAX_DM_PATH/2] = {0}, service_name[MAX_DM_PATH] = {0}; + bool is_unified = false; + + if (!name || !json_path) { + BBF_ERR("Invalid service name or json file path"); + return -1; + } + + json_obj = json_object_from_file(json_path); + if (!json_obj) { + BBF_ERR("Failed to read input %s file for services", json_path); + return -1; + } + + json_object *daemon_obj = dmjson_get_obj(json_obj, 1, "daemon"); + if (!daemon_obj) { + err = -1; + goto exit; + } + + strncpyt(buffer, name, sizeof(buffer)); + // Remove .json from the end + size_t len = strlen(buffer) - strlen(".json"); + buffer[len] = '\0'; + + snprintf(service_name, sizeof(service_name), "%s.%s", BBFDM_DEFAULT_UBUS_OBJ, buffer); + string_to_bool(dmjson_get_value((daemon_obj), 1, "unified_daemon"), &is_unified); + + dmjson_foreach_obj_in_array(daemon_obj, jservices, jserv, idx, 1, "services") { + if (jserv) { + char parent[MAX_DM_PATH] = {0}, obj[MAX_DM_PATH] = {0}; + char *tmp; + + tmp = dmjson_get_value(jserv, 1, "parent_dm"); + replace_str(tmp, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, parent, sizeof(parent)); + + tmp = dmjson_get_value(jserv, 1, "object"); + replace_str(tmp, "{BBF_VENDOR_PREFIX}", BBF_VENDOR_PREFIX, obj, sizeof(obj)); + + if ((DM_STRLEN(parent) == 0) || (DM_STRLEN(obj) == 0)) { + BBF_ERR("Skip empty registration parent_dm[%s] or object[%s]", parent, obj); + continue; + } + + BBF_INFO("Registering [%s :: %s :: %s :: %d]", service_name, parent, obj, is_unified); + load_service(DEAMON_DM_ROOT_OBJ, &head_registered_service, service_name, parent, obj, is_unified); + } + } +exit: + if (json_obj) { + json_object_put(json_obj); + } + + return err; +} + static int daemon_load_config(bbfdm_config_t *config) { int err = 0; @@ -1229,38 +1186,6 @@ static int regiter_ubus_object(struct ubus_context *ctx) return ret; } -static void lookup_event_cb(struct ubus_context *ctx, - struct ubus_event_handler *ev __attribute__((unused)), - const char *type, struct blob_attr *msg) -{ - const struct blobmsg_policy policy = { - "path", BLOBMSG_TYPE_STRING - }; - struct blob_attr *attr; - const char *path; - struct bbfdm_context *u; - - u = container_of(ctx, struct bbfdm_context, ubus_ctx); - if (u == NULL) { - BBF_ERR("failed to get the bbfdm context"); - return; - } - - if (type && strcmp(type, "ubus.object.add") != 0) - return; - - blobmsg_parse(&policy, 1, &attr, blob_data(msg), blob_len(msg)); - - if (!attr) - return; - - path = blobmsg_data(attr); - if (path && strcmp(path, u->config.out_root_obj) == 0) { - // register micro-service - register_service(ctx); - } -} - static void bbfdm_register_instance_refresh_timer(struct ubus_context *ctx, int start_in_sec) { struct bbfdm_context *u; @@ -1355,7 +1280,39 @@ static int daemon_load_data_model(struct bbfdm_context *daemon_ctx) return 0; } -static struct ubus_event_handler add_event = { .cb = lookup_event_cb }; +static int register_micro_services() +{ + DIR *dir_tmp = NULL; + struct dirent *d_file = NULL; + int err = 0; + + if (dm_is_micro_service() == true) { + return 0; + } + + sysfs_foreach_file(BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH, dir_tmp, d_file) { + char config_name[512] = {0}; + + if (d_file->d_name[0] == '.') + continue; + + snprintf(config_name, sizeof(config_name), "%s/%s", BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH, d_file->d_name); + + if (!file_exists(config_name) || !is_regular_file(config_name)) + continue; + + err = daemon_load_services(d_file->d_name, config_name); + if (err) { + BBF_ERR("Failed to load micro-services %s", d_file->d_name); + break; + } + } + if (dir_tmp) { + closedir (dir_tmp); + } + return err; +} + static struct ubus_event_handler config_change_handler = { .cb = bbf_config_change_cb }; int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) @@ -1385,6 +1342,13 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) return err; } + // Pre-load the services + err = register_micro_services(); + if (err) { + BBF_ERR("Failed to load micro-services"); + return err; + } + err = regiter_ubus_object(&bbfdm_ctx->ubus_ctx); if (err != UBUS_STATUS_OK) return -1; @@ -1397,21 +1361,8 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) return err; err = ubus_register_event_handler(&bbfdm_ctx->ubus_ctx, &config_change_handler, "bbf.config.change"); - if (err != 0) - return err; - if (dm_is_micro_service() == true) { - // Register the micro-service - register_service(&bbfdm_ctx->ubus_ctx); - - // If the micro-service is not registered, listen for "ubus.object.add" event - // and register the micro-service using event handler for it - err = ubus_register_event_handler(&bbfdm_ctx->ubus_ctx, &add_event, "ubus.object.add"); - if (err != 0) - return err; - } - - return 0; + return err; } int bbfdm_ubus_regiter_free(struct bbfdm_context *bbfdm_ctx) @@ -1427,6 +1378,7 @@ int bbfdm_ubus_regiter_free(struct bbfdm_context *bbfdm_ctx) void bbfdm_ubus_set_service_name(struct bbfdm_context *bbfdm_ctx, const char *srv_name) { strncpyt(bbfdm_ctx->config.service_name, srv_name, sizeof(bbfdm_ctx->config.service_name)); + snprintf(bbfdm_ctx->config.out_name, sizeof(bbfdm_ctx->config.out_name), "%s.%s", BBFDM_DEFAULT_UBUS_OBJ, srv_name); dm_set_micro_service(); } diff --git a/libbbfdm-ubus/bbfdm-ubus.h b/libbbfdm-ubus/bbfdm-ubus.h index b3889219..869656dc 100644 --- a/libbbfdm-ubus/bbfdm-ubus.h +++ b/libbbfdm-ubus/bbfdm-ubus.h @@ -19,7 +19,7 @@ struct bbfdm_async_req { typedef struct bbfdm_config { struct list_head list_objs; // Micro-service list of objects to expose - char service_name[16]; // Service name for micro-service identification + char service_name[32]; // Service name for micro-service identification char in_type[32]; // Input type, Possible values: { 'JSON', 'DotSo' } char in_name[128]; // plugin path char in_plugin_dir[128]; // extra plugin directory path diff --git a/test/files/etc/bbfdm/services/netmngr.json b/test/files/etc/bbfdm/services/netmngr.json new file mode 100644 index 00000000..b41b6d2f --- /dev/null +++ b/test/files/etc/bbfdm/services/netmngr.json @@ -0,0 +1,32 @@ +{ + "daemon": { + "enable": "1", + "service_name": "netmngr", + "unified_daemon": false, + "services": [ + { + "parent_dm": "Device.", + "object": "IP" + }, + { + "parent_dm": "Device.", + "object": "GRE" + }, + { + "parent_dm": "Device.", + "object": "PPP" + }, + { + "parent_dm": "Device.", + "object": "Routing" + }, + { + "parent_dm": "Device.", + "object": "RouterAdvertisement" + } + ], + "config": { + "loglevel": "3" + } + } +} diff --git a/test/files/etc/bbfdm/services/sysmngr.json b/test/files/etc/bbfdm/services/sysmngr.json new file mode 100644 index 00000000..d4130ca8 --- /dev/null +++ b/test/files/etc/bbfdm/services/sysmngr.json @@ -0,0 +1,16 @@ +{ + "daemon": { + "enable": "1", + "service_name": "sysmngr", + "unified_daemon": true, + "services": [ + { + "parent_dm": "Device.", + "object": "DeviceInfo" + } + ], + "config": { + "loglevel": "3" + } + } +} diff --git a/test/files/etc/bbfdm/services/wifidmd.json b/test/files/etc/bbfdm/services/wifidmd.json new file mode 100644 index 00000000..83e1f9c3 --- /dev/null +++ b/test/files/etc/bbfdm/services/wifidmd.json @@ -0,0 +1,16 @@ +{ + "daemon": { + "enable": "1", + "service_name": "wifidmd", + "unified_daemon": false, + "services": [ + { + "parent_dm": "Device.", + "object": "WiFi" + } + ], + "config": { + "loglevel": "3" + } + } +}