diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 94325383..6704d3c0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,7 +2,7 @@ variables: DEBUG: 'TRUE' SOURCE_FOLDER: "." FLAWFINDER_OPTIONS: "-m 4 --error-level=5" - CPPCHECK_OPTIONS: "--enable=all --suppress=variableScope --suppress=unusedFunction --suppress=constParameter --suppress=knownConditionTrueFalse -DBBF_VENDOR_PREFIX=X_IOPSYS_EU_ -DBBFDM_ENABLE_DOTSO_PLUGIN -DBBFDM_ENABLE_DOTSO_PLUGIN -DBBF_TR181 -DBBF_VENDOR_IOPSYS -i test/" + CPPCHECK_OPTIONS: "--enable=all --suppress=variableScope --suppress=unusedFunction --suppress=constParameter --suppress=knownConditionTrueFalse -DBBF_VENDOR_PREFIX=X_IOPSYS_EU_ -i test/" include: - project: 'iopsys/gitlab-ci-pipeline' diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c14b50c..a577b67f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ add_subdirectory(libbbfdm-api) add_subdirectory(libbbfdm-ubus) add_subdirectory(libbbfdm) add_subdirectory(bbfdmd) +add_subdirectory(dm-service) # Capture the environment variables set(MY_CC "$ENV{CC}") diff --git a/bbfdmd/ubus/CMakeLists.txt b/bbfdmd/ubus/CMakeLists.txt index b10e8a5f..a2e14f24 100644 --- a/bbfdmd/ubus/CMakeLists.txt +++ b/bbfdmd/ubus/CMakeLists.txt @@ -8,5 +8,5 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_SOURCE_DIR}/ FILE(GLOB BBF_SOURCES *.c) ADD_EXECUTABLE(bbfdmd ${BBF_SOURCES}) -TARGET_LINK_LIBRARIES(bbfdmd bbfdm-ubus) +TARGET_LINK_LIBRARIES(bbfdmd bbfdm-ubus bbfdm) INSTALL(TARGETS bbfdmd DESTINATION usr/sbin) diff --git a/bbfdmd/ubus/bbfdmd.c b/bbfdmd/ubus/bbfdmd.c index 23d89770..84434e9e 100644 --- a/bbfdmd/ubus/bbfdmd.c +++ b/bbfdmd/ubus/bbfdmd.c @@ -15,91 +15,43 @@ #include "bbfdm-ubus.h" #include "cli.h" +#include "libbbfdm/device.h" + static void usage(char *prog) { fprintf(stderr, "Usage: %s [options]\n", prog); fprintf(stderr, "\n"); fprintf(stderr, "options:\n"); - fprintf(stderr, " -s ubus socket\n"); - fprintf(stderr, " -m json input configuration for micro services\n"); fprintf(stderr, " -c Run cli command\n"); - fprintf(stderr, " -h Displays this help\n"); + fprintf(stderr, " -l log verbosity value as per standard syslog\n"); + fprintf(stderr, " -h Displays this help\n"); fprintf(stderr, "\n"); } -static int parse_input_cli_options(bbfdm_config_t *config, json_object *json_obj) -{ - char *opt_val = NULL; - - if (!config || !json_obj) { - fprintf(stderr, "Invalid input options \n"); - return -1; - } - - opt_val = dmjson_get_value(json_obj, 3, "cli", "config", "proto"); - if (DM_STRLEN(opt_val)) { - config->proto = get_proto_type(opt_val); - } else { - config->proto = BBFDM_BOTH; - } - - opt_val = dmjson_get_value(json_obj, 3, "cli", "input", "type"); - if (DM_STRLEN(opt_val)) { - snprintf(config->cli_in_type, sizeof(config->cli_in_type), "%s", opt_val); - } - - opt_val = dmjson_get_value(json_obj, 3, "cli", "input", "name"); - if (DM_STRLEN(opt_val)) { - snprintf(config->cli_in_name, sizeof(config->cli_in_name), "%s", opt_val); - } - - opt_val = dmjson_get_value(json_obj, 3, "cli", "input", "plugin_dir"); - if (DM_STRLEN(opt_val)) { - snprintf(config->cli_in_plugin_dir, sizeof(config->cli_in_plugin_dir), "%s", opt_val); - } - - opt_val = dmjson_get_value(json_obj, 3, "cli", "output", "type"); - if (DM_STRLEN(opt_val)) { - snprintf(config->cli_out_type, sizeof(config->cli_out_type), "%s", opt_val); - } - return 0; -} - -static int load_cli_config(bbfdm_config_t *config) -{ - json_object *json_obj = NULL; - - json_obj = json_object_from_file(BBFDM_JSON_INPUT); - if (!json_obj) { - fprintf(stderr, "Failed to read input %s file \n", BBFDM_JSON_INPUT); - return -1; - } - - parse_input_cli_options(config, json_obj); - - json_object_put(json_obj); - return 0; -} - int main(int argc, char **argv) { struct bbfdm_context bbfdm_ctx = {0}; char *cli_argv[4] = {0}; + int log_level = 3; // Default is LOG_ERR int err = 0, ch, cli_argc = 0, i; memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); - while ((ch = getopt(argc, argv, "hs:m:c:")) != -1) { + while ((ch = getopt(argc, argv, "hc:l:")) != -1) { switch (ch) { - case 'm': - bbfdm_ubus_set_service_name(&bbfdm_ctx, optarg); - break; case 'c': cli_argc = argc-optind+1; for (i = 0; i < cli_argc; i++) { cli_argv[i] = argv[optind - 1 + i]; } break; + case 'l': + if (optarg) { + log_level = (int)strtod(optarg, NULL); + if (log_level < 0 || log_level > 7) + log_level = 3; + } + break; case 'h': usage(argv[0]); exit(0); @@ -109,41 +61,25 @@ int main(int argc, char **argv) } if (cli_argc) { - if (dm_is_micro_service() == true) { - fprintf(stderr, "Failed to run cli with micro-service\n"); - return -1; - } - - err = load_cli_config(&bbfdm_ctx.config); - if (err) { - fprintf(stderr, "Failed to load cli config from json file (%s)\n", BBFDM_JSON_INPUT); - return err; - } - - return bbfdm_cli_exec_command(&bbfdm_ctx.config, cli_argc, cli_argv); + return bbfdm_cli_exec_command(cli_argc, cli_argv); } - openlog("bbfdm", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + bbfdm_ubus_set_log_level(log_level); + bbfdm_ubus_load_data_model(tDynamicObj); + + openlog(BBFDM_DEFAULT_UBUS_OBJ, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); err = bbfdm_ubus_regiter_init(&bbfdm_ctx); if (err != 0) goto exit; - if (dm_is_micro_service() == true) { - char proc_name[32] = {0}; - - // Create process name using service name and prefix "dm_" - snprintf(proc_name, sizeof(proc_name), "dm_%s", bbfdm_ctx.config.service_name); - - // Set process name for the current process - prctl(PR_SET_NAME, proc_name, NULL, NULL, NULL); - } - BBF_INFO("Waiting on uloop...."); uloop_run(); exit: - bbfdm_ubus_regiter_free(&bbfdm_ctx); + if (err != -5) // Error code is not -5, indicating that ubus_ctx is connected, proceed with shutdown + bbfdm_ubus_regiter_free(&bbfdm_ctx); + closelog(); return err; diff --git a/bbfdmd/ubus/cli.c b/bbfdmd/ubus/cli.c index 34aa9c64..cbfde81a 100644 --- a/bbfdmd/ubus/cli.c +++ b/bbfdmd/ubus/cli.c @@ -14,23 +14,9 @@ #include "common.h" #include "plugin.h" -extern struct list_head loaded_json_files; -extern struct list_head json_list; -extern struct list_head json_memhead; - #define UNUSED __attribute__((unused)) -static DMOBJ *CLI_DM_ROOT_OBJ = NULL; - -static void *cli_lib_handle = NULL; - typedef struct { - struct dmctx bbf_ctx; - unsigned int proto; - char in_name[128]; - char in_plugin_dir[128]; - char in_type[32]; - char out_type[32]; char *cmd; bool ubus_status; } cli_data_t; @@ -38,27 +24,22 @@ typedef struct { typedef struct { char *name; int num_args; - int (*exec_cmd)(cli_data_t *cli_data, char *argv[]); + int (*exec_cmd)(cli_data_t *cli_data, const char *path, const char *value); char *usage; } cli_cmd_t; -static int cli_exec_help(cli_data_t *cli_data UNUSED, char *argv[] UNUSED); -static int cli_exec_get(cli_data_t *cli_data, char *argv[]); -static int cli_exec_set(cli_data_t *cli_data, char *argv[]); -static int cli_exec_add(cli_data_t *cli_data, char *argv[]); -static int cli_exec_del(cli_data_t *cli_data, char *argv[]); -static int cli_exec_instances(cli_data_t *cli_data, char *argv[]); -static int cli_exec_schema(cli_data_t *cli_data, char *argv[]); +static int cli_exec_help(cli_data_t *cli_data UNUSED, const char *path UNUSED, const char *value UNUSED); +static int cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *value); cli_cmd_t cli_commands[] = { // Name NumArgs Exec callback Usage String { "help", 0, cli_exec_help, "help" }, - { "get", 1, cli_exec_get, "get [path-expr]" }, - { "set", 2, cli_exec_set, "set [path-expr] [value]"}, - { "add", 1, cli_exec_add, "add [object]"}, - { "del", 1, cli_exec_del, "del [path-expr]"}, - { "instances", 1, cli_exec_instances, "instances [path-expr]" }, - { "schema", 1, cli_exec_schema, "schema [path-expr]"}, + { "get", 1, cli_exec_cmd, "get [path-expr]" }, + { "set", 2, cli_exec_cmd, "set [path-expr] [value]"}, + { "add", 1, cli_exec_cmd, "add [object]"}, + { "del", 1, cli_exec_cmd, "del [path-expr]"}, + { "instances", 1, cli_exec_cmd, "instances [path-expr]" }, + { "schema", 1, cli_exec_cmd, "schema [path-expr]"}, }; typedef void (*__ubus_cb)(struct ubus_request *req, int type, struct blob_attr *msg); @@ -167,7 +148,7 @@ static void __ubus_callback(struct ubus_request *req, int msgtype __attribute__( } } -static int in_ubus_out_cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *value) +static int cli_exec_cmd(cli_data_t *cli_data, const char *path, const char *value) { struct blob_buf b = {0}; void *table = NULL; @@ -181,19 +162,18 @@ static int in_ubus_out_cli_exec_cmd(cli_data_t *cli_data, const char *path, cons if (value) blobmsg_add_string(&b, "value", value); table = blobmsg_open_table(&b, "optional"); - blobmsg_add_string(&b, "proto", (cli_data->proto == BBFDM_CWMP) ? "cwmp" : (cli_data->proto == BBFDM_USP) ? "usp" : "both"); blobmsg_add_string(&b, "format", "raw"); blobmsg_close_table(&b, table); - int e = bbfdm_ubus_invoke(cli_data->in_name, cli_data->cmd, b.head, __ubus_callback, cli_data); + int e = bbfdm_ubus_invoke(BBFDM_DEFAULT_UBUS_OBJ, cli_data->cmd, b.head, __ubus_callback, cli_data); if (e < 0) { - printf("ERROR: ubus invoke for [object:%s method:%s] exit with error(%d)\n", cli_data->in_name, cli_data->cmd, e); + printf("ERROR: ubus invoke for [object:%s method:%s] exit with error(%d)\n", BBFDM_DEFAULT_UBUS_OBJ, cli_data->cmd, e); err = EXIT_FAILURE; } if (cli_data->ubus_status == false) { - printf("ERROR: ubus call for [object:%s method:%s] exit with error\n", cli_data->in_name, cli_data->cmd); + printf("ERROR: ubus call for [object:%s method:%s] exit with error\n", BBFDM_DEFAULT_UBUS_OBJ, cli_data->cmd); err = EXIT_FAILURE; } @@ -202,45 +182,7 @@ static int in_ubus_out_cli_exec_cmd(cli_data_t *cli_data, const char *path, cons return err; } -static int bbfdm_load_cli_config(bbfdm_config_t *bbf_config, cli_data_t *cli_data) -{ - char *opt_val = NULL; - - cli_data->proto = bbf_config->proto; - - opt_val = bbf_config->cli_in_type; - if (opt_val && strlen(opt_val)) { - snprintf(cli_data->in_type, sizeof(cli_data->in_type), "%s", opt_val); - } else { - printf("ERROR: [cli.input.type] not specified\n"); - return -1; - } - - opt_val = bbf_config->cli_in_name; - if (opt_val && strlen(opt_val)) { - snprintf(cli_data->in_name, sizeof(cli_data->in_name), "%s", opt_val); - } else { - printf("ERROR: [cli.input.name] not specified\n"); - return -1; - } - - opt_val = bbf_config->cli_in_plugin_dir; - if (opt_val && strlen(opt_val)) { - snprintf(cli_data->in_plugin_dir, sizeof(cli_data->in_plugin_dir), "%s", opt_val); - } - - opt_val = bbf_config->cli_out_type; - if (opt_val && strlen(opt_val)) { - snprintf(cli_data->out_type, sizeof(cli_data->out_type), "%s", opt_val); - } else { - printf("ERROR: [cli.output.type] not specified\n"); - return -1; - } - - return 0; -} - -static int cli_exec_help(cli_data_t *cli_data UNUSED, char *argv[] UNUSED) +static int cli_exec_help(cli_data_t *cli_data UNUSED, const char *path UNUSED, const char *value UNUSED) { cli_cmd_t *cli_cmd; @@ -255,285 +197,6 @@ static int cli_exec_help(cli_data_t *cli_data UNUSED, char *argv[] UNUSED) return EXIT_SUCCESS; } -static int in_dotso_out_cli_exec_get(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - cli_data->bbf_ctx.in_param = argv[0]; - - err = bbf_entry_method(&cli_data->bbf_ctx, BBF_GET_VALUE); - if (!err) { - struct blob_attr *cur = NULL; - size_t rem = 0; - - blobmsg_for_each_attr(cur, cli_data->bbf_ctx.bb.head, rem) { - struct blob_attr *tb[2] = {0}; - const struct blobmsg_policy p[2] = { - { "path", BLOBMSG_TYPE_STRING }, - { "data", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 2, tb, blobmsg_data(cur), blobmsg_len(cur)); - - char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - char *data = (tb[1]) ? blobmsg_get_string(tb[1]) : ""; - - printf("%s => %s\n", name, data); - } - - // Apply all bbfdm changes - dmuci_commit_bbfdm(); - } else { - printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); - dmuci_revert_bbfdm(); - err = EXIT_FAILURE; - } - - return err; -} - -static int in_ubus_out_cli_exec_get(cli_data_t *cli_data, char *argv[]) -{ - return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); -} - -static int cli_exec_get(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_get(cli_data, argv); - else if (strcasecmp(cli_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_get(cli_data, argv); - else - err = EXIT_FAILURE; - - return err; -} - -static int in_dotso_out_cli_exec_set(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - cli_data->bbf_ctx.in_param = argv[0]; - cli_data->bbf_ctx.in_value = argv[1]; - - err = bbf_entry_method(&cli_data->bbf_ctx, BBF_SET_VALUE); - if (!err) { - printf("%s => Set value is successfully done\n", cli_data->bbf_ctx.in_param); - bbf_entry_services(cli_data->proto, true, true); - } else { - printf("Fault %d: %s\n", err, cli_data->bbf_ctx.fault_msg); - bbf_entry_services(cli_data->proto, false, true); - err = EXIT_FAILURE; - } - - return err; -} - -static int in_ubus_out_cli_exec_set(cli_data_t *cli_data, char *argv[]) -{ - return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); -} - -static int cli_exec_set(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_set(cli_data, argv); - else if (strcasecmp(cli_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_set(cli_data, argv); - else - err = EXIT_FAILURE; - - return err; -} - -static int in_dotso_out_cli_exec_add(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - cli_data->bbf_ctx.in_param = argv[0]; - - err = bbf_entry_method(&cli_data->bbf_ctx, BBF_ADD_OBJECT); - if (!err) { - printf("Added %s%s.\n", cli_data->bbf_ctx.in_param, cli_data->bbf_ctx.addobj_instance); - bbf_entry_services(cli_data->proto, true, false); - } else { - printf("Fault %d: %s\n", err, cli_data->bbf_ctx.fault_msg); - bbf_entry_services(cli_data->proto, false, false); - err = EXIT_FAILURE; - } - - return err; -} - -static int in_ubus_out_cli_exec_add(cli_data_t *cli_data, char *argv[]) -{ - return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); -} - -static int cli_exec_add(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_add(cli_data, argv); - else if (strcasecmp(cli_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_add(cli_data, argv); - else - err = EXIT_FAILURE; - - return err; -} - -static int in_dotso_out_cli_exec_del(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - cli_data->bbf_ctx.in_param = argv[0]; - - err = bbf_entry_method(&cli_data->bbf_ctx, BBF_DEL_OBJECT); - if (!err) { - printf("Deleted %s\n", cli_data->bbf_ctx.in_param); - bbf_entry_services(cli_data->proto, true, true); - } else { - printf("Fault %d: %s\n", err, cli_data->bbf_ctx.fault_msg); - bbf_entry_services(cli_data->proto, false, true); - err = EXIT_FAILURE; - } - - return err; -} - -static int in_ubus_out_cli_exec_del(cli_data_t *cli_data, char *argv[]) -{ - return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); -} - -static int cli_exec_del(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_del(cli_data, argv); - else if (strcasecmp(cli_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_del(cli_data, argv); - else - err = EXIT_FAILURE; - - return err; -} - -static int in_dotso_out_cli_exec_instances(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - cli_data->bbf_ctx.in_param = argv[0]; - cli_data->bbf_ctx.nextlevel = false; - - err = bbf_entry_method(&cli_data->bbf_ctx, BBF_INSTANCES); - if (!err) { - struct blob_attr *cur = NULL; - size_t rem = 0; - - blobmsg_for_each_attr(cur, cli_data->bbf_ctx.bb.head, rem) { - struct blob_attr *tb[1] = {0}; - const struct blobmsg_policy p[1] = { - { "path", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 1, tb, blobmsg_data(cur), blobmsg_len(cur)); - - printf("%s\n", (tb[0]) ? blobmsg_get_string(tb[0]) : ""); - } - } else { - printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); - err = EXIT_FAILURE; - } - - return err; -} - -static int in_ubus_out_cli_exec_instances(cli_data_t *cli_data, char *argv[]) -{ - return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); -} - -static int cli_exec_instances(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_instances(cli_data, argv); - else if (strcasecmp(cli_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_instances(cli_data, argv); - else - err = EXIT_FAILURE; - - return err; -} - -static int in_dotso_out_cli_exec_schema(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - cli_data->bbf_ctx.in_param = argv[0]; - cli_data->bbf_ctx.nextlevel = false; - cli_data->bbf_ctx.iscommand = true; - cli_data->bbf_ctx.isevent = true; - cli_data->bbf_ctx.isinfo = true; - - err = bbf_entry_method(&cli_data->bbf_ctx, BBF_SCHEMA); - if (!err) { - struct blob_attr *cur = NULL; - size_t rem = 0; - - blobmsg_for_each_attr(cur, cli_data->bbf_ctx.bb.head, rem) { - struct blob_attr *tb[3] = {0}; - const struct blobmsg_policy p[3] = { - { "path", BLOBMSG_TYPE_STRING }, - { "data", BLOBMSG_TYPE_STRING }, - { "type", BLOBMSG_TYPE_STRING } - }; - - blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); - - char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; - char *data = (tb[1]) ? blobmsg_get_string(tb[1]) : ""; - char *type = (tb[2]) ? blobmsg_get_string(tb[2]) : ""; - - int cmd = get_dm_type(type); - printf("%s %s %s\n", name, type, (cmd != DMT_EVENT && cmd != DMT_COMMAND) ? data : "0"); - } - } else { - printf("ERROR: %d retrieving %s\n", err, cli_data->bbf_ctx.in_param); - err = EXIT_FAILURE; - } - - return err; -} - -static int in_ubus_out_cli_exec_schema(cli_data_t *cli_data, char *argv[]) -{ - return in_ubus_out_cli_exec_cmd(cli_data, argv[0], argv[1]); -} - -static int cli_exec_schema(cli_data_t *cli_data, char *argv[]) -{ - int err = EXIT_SUCCESS; - - if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) - err = in_dotso_out_cli_exec_schema(cli_data, argv); - else if (strcasecmp(cli_data->in_type, "UBUS") == 0) - err = in_ubus_out_cli_exec_schema(cli_data, argv); - else - err = EXIT_FAILURE; - - return err; -} - static int cli_exec_command(cli_data_t *cli_data, int argc, char *argv[]) { cli_cmd_t *cli_cmd = NULL; @@ -544,34 +207,6 @@ static int cli_exec_command(cli_data_t *cli_data, int argc, char *argv[]) if (!cli_data->cmd || strlen(cli_data->cmd) == 0) return EXIT_FAILURE; - if (strcasecmp(cli_data->in_type, "DotSO") == 0 || strcasecmp(cli_data->in_type, "JSON") == 0) { - - if (strcasecmp(cli_data->in_type, "DotSO") == 0) { - if (load_dotso_plugin(&cli_lib_handle, cli_data->in_name, NULL, &CLI_DM_ROOT_OBJ) != 0) { - err = EXIT_FAILURE; - goto end; - } - } else { - if (load_json_plugin(&loaded_json_files, &json_list, &json_memhead, cli_data->in_name, NULL, &CLI_DM_ROOT_OBJ) != 0) { - err = EXIT_FAILURE; - goto end; - } - } - - if (CLI_DM_ROOT_OBJ == NULL) { - err = EXIT_FAILURE; - goto end; - } - - bbf_global_init(CLI_DM_ROOT_OBJ, cli_data->in_plugin_dir); - - bbf_ctx_init(&cli_data->bbf_ctx, CLI_DM_ROOT_OBJ); - - cli_data->bbf_ctx.dm_type = cli_data->proto; - } else if (strcasecmp(cli_data->in_type, "UBUS") != 0) { - return -1; - } - for (size_t i = 0; i < ARRAY_SIZE(cli_commands); i++) { cli_cmd = &cli_commands[i]; @@ -579,12 +214,12 @@ static int cli_exec_command(cli_data_t *cli_data, int argc, char *argv[]) if (argc-1 < cli_cmd->num_args) { printf("ERROR: Number of arguments for %s method is wrong(%d), it should be %d\n", cli_cmd->name, argc-1, cli_cmd->num_args); - cli_commands[0].exec_cmd(cli_data, NULL); + cli_commands[0].exec_cmd(cli_data, NULL, NULL); err = EXIT_FAILURE; goto end; } - err = cli_cmd->exec_cmd(cli_data, &argv[1]); + err = cli_cmd->exec_cmd(cli_data, argv[1], argv[2]); registred_command = true; break; } @@ -592,33 +227,18 @@ static int cli_exec_command(cli_data_t *cli_data, int argc, char *argv[]) if (!registred_command) { printf("ERROR: Unknown command: %s\n", cli_data->cmd); - cli_commands[0].exec_cmd(cli_data, NULL); + cli_commands[0].exec_cmd(cli_data, NULL, NULL); err = EXIT_FAILURE; } end: - if (strcasecmp(cli_data->in_type, "DotSO") == 0) { - if (CLI_DM_ROOT_OBJ) { - bbf_ctx_clean(&cli_data->bbf_ctx); - bbf_global_clean(CLI_DM_ROOT_OBJ); - } - free_dotso_plugin(cli_lib_handle); - cli_lib_handle = NULL; - } else if (strcasecmp(cli_data->in_type, "JSON") == 0) { - if (CLI_DM_ROOT_OBJ) { - bbf_ctx_clean(&cli_data->bbf_ctx); - bbf_global_clean(CLI_DM_ROOT_OBJ); - } - free_json_plugin(); - } return err; } -int bbfdm_cli_exec_command(bbfdm_config_t *bbf_config, int argc, char *argv[]) +int bbfdm_cli_exec_command(int argc, char *argv[]) { cli_data_t cli_data = {0}; - int err = EXIT_SUCCESS; // Exit if no command specified if (argc < 1) { @@ -628,12 +248,5 @@ int bbfdm_cli_exec_command(bbfdm_config_t *bbf_config, int argc, char *argv[]) memset(&cli_data, 0, sizeof(cli_data_t)); - err = bbfdm_load_cli_config(bbf_config, &cli_data); - if (err) { - printf("ERROR: required cli config missing\n"); - return EXIT_FAILURE; - } - - err = cli_exec_command(&cli_data, argc, argv); - return err; + return cli_exec_command(&cli_data, argc, argv); } diff --git a/bbfdmd/ubus/cli.h b/bbfdmd/ubus/cli.h index cd2d53ad..8de5a907 100644 --- a/bbfdmd/ubus/cli.h +++ b/bbfdmd/ubus/cli.h @@ -8,4 +8,4 @@ * See LICENSE file for license related information. */ -int bbfdm_cli_exec_command(bbfdm_config_t *bbf_config, int argc, char *argv[]); +int bbfdm_cli_exec_command(int argc, char *argv[]); diff --git a/dm-service/CMakeLists.txt b/dm-service/CMakeLists.txt new file mode 100644 index 00000000..90126965 --- /dev/null +++ b/dm-service/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.0) + +PROJECT(dm-service C) + +ADD_DEFINITIONS(-fstrict-aliasing -Wall -Wextra -Werror -Wformat -Wformat-signedness -fPIC -D_GNU_SOURCE) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_SOURCE_DIR}/libbbfdm-api/ -I${CMAKE_SOURCE_DIR}/libbbfdm-ubus/") + +FILE(GLOB BBF_SOURCES *.c) +ADD_EXECUTABLE(dm-service ${BBF_SOURCES}) +TARGET_LINK_LIBRARIES(dm-service bbfdm-ubus) +INSTALL(TARGETS dm-service DESTINATION usr/sbin) \ No newline at end of file diff --git a/dm-service/dm_service.c b/dm-service/dm_service.c new file mode 100644 index 00000000..09369e39 --- /dev/null +++ b/dm-service/dm_service.c @@ -0,0 +1,85 @@ +/* + * dm_service.c: dm-service deamon + * + * Copyright (C) 2024 IOPSYS Software Solutions AB. All rights reserved. + * + * Author: Amin Ben Romdhane + * + * See LICENSE file for license related information. + */ + +#include + +#include "common.h" +#include "bbfdm-ubus.h" + +static void usage(char *prog) +{ + fprintf(stderr, "Usage: %s [options]\n", prog); + fprintf(stderr, "\n"); + fprintf(stderr, "options:\n"); + fprintf(stderr, " -m micro-service name\n"); + fprintf(stderr, " -l log verbosity value as per standard syslog\n"); + fprintf(stderr, " -h Displays this help\n"); + fprintf(stderr, "\n"); +} + +int main(int argc, char **argv) +{ + struct bbfdm_context bbfdm_ctx = {0}; + char proc_name[32] = {0}; + int log_level = 3; // Default is LOG_ERR + int err = 0, ch; + + memset(&bbfdm_ctx, 0, sizeof(struct bbfdm_context)); + + while ((ch = getopt(argc, argv, "hl:m:")) != -1) { + switch (ch) { + case 'm': + bbfdm_ubus_set_service_name(&bbfdm_ctx, optarg); + break; + case 'l': + if (optarg) { + log_level = (int)strtod(optarg, NULL); + if (log_level < 0 || log_level > 7) + log_level = 3; + } + break; + case 'h': + usage(argv[0]); + exit(0); + default: + break; + } + } + + if (dm_is_micro_service() == false) { + fprintf(stderr, "Failed to start micro-service without providing the name using '-m' option\n"); + exit(-1); + } + + bbfdm_ubus_set_log_level(log_level); + + openlog(bbfdm_ctx.config.service_name, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); + + err = bbfdm_ubus_regiter_init(&bbfdm_ctx); + if (err != 0) + goto exit; + + // Create process name using service name and prefix "dm_" + snprintf(proc_name, sizeof(proc_name), "dm_%s", bbfdm_ctx.config.service_name); + + // Set process name for the current process + prctl(PR_SET_NAME, proc_name, NULL, NULL, NULL); + + BBF_INFO("Waiting on uloop...."); + uloop_run(); + +exit: + if (err != -5) // Error code is not -5, indicating that ubus_ctx is connected, proceed with shutdown + bbfdm_ubus_regiter_free(&bbfdm_ctx); + + closelog(); + + return err; +} diff --git a/docs/api/uci/bbfdm.json b/docs/api/uci/bbfdm.json index ce90d289..31d1781d 100644 --- a/docs/api/uci/bbfdm.json +++ b/docs/api/uci/bbfdm.json @@ -25,27 +25,6 @@ "required": "no", "default": "", "description": "Path for ubus socket to register bbfdmd services" - }, - { - "name": "loglevel", - "type": "integer", - "required": "no", - "default": "3", - "description": "Internal loglevel for debugging {0: No Logs; 1: Alert; 2: Critical; 3: Error; 4: Warning; 5: Notice; 6: Info; 7: Debug}" - }, - { - "name": "subprocess_level", - "type": "integer", - "required": "no", - "default": "2", - "description": "This parameter configures when subprocess can be used for get operation. Level here denotes the Datamodel object depth up-to which subprocess will be used to collect the get data. For example, if this is configured to 1, then only get for 'Device.' shall be called within the subprocess. If configured as level 2, then all the get with up-to depth 2 like 'Device.WiFi.', 'Device.IP.' shall be called in subprocess." - }, - { - "name": "refresh_time", - "type": "integer", - "required": "no", - "default": "5", - "description": "The time period in seconds after which bbfdmd will refresh the datamodel instances in a periodic manner. If configured to '0' then instance updater will be disabled. If not configured at all then after every 5 seconds datamodel instances will be refreshed." } ] }, diff --git a/docs/api/uci/bbfdm.md b/docs/api/uci/bbfdm.md index 4e4ec169..95cde32c 100644 --- a/docs/api/uci/bbfdm.md +++ b/docs/api/uci/bbfdm.md @@ -84,57 +84,6 @@
Path for ubus socket to register bbfdmd services
- - -
loglevel
- - -
integer
- - -
no
- - -
1
- - -
Internal loglevel for debugging {0: No Logs; 1: Alert; 2: Critical; 3: Error; 4: Warning; 5: Notice; 6: Info; 7: Debug}
- - - - -
subprocess_level
- - -
integer
- - -
no
- - -
2
- - -
This parameter configures when subprocess can be used for get operation. Level here denotes the Datamodel object depth up-to which subprocess will be used to collect the get data. For example, if this is configured to 1, then only get for 'Device.' shall be called within the subprocess. If configured as level 2, then all the get with up-to depth 2 like 'Device.WiFi.', 'Device.IP.' shall be called in subprocess.
- - - - -
refresh_time
- - -
integer
- - -
no
- - -
5
- - -
The time period in seconds after which bbfdmd will refresh the datamodel instances in a periodic manner. If configured to '0' then instance updater will be disabled. If not configured at all then after every 5 seconds datamodel instances will be refreshed.
- - diff --git a/docs/guide/How_to_extend_datamodel_with_C_Code.md b/docs/guide/How_to_extend_datamodel_with_C_Code.md index 1afea889..50a4ccac 100644 --- a/docs/guide/How_to_extend_datamodel_with_C_Code.md +++ b/docs/guide/How_to_extend_datamodel_with_C_Code.md @@ -30,7 +30,7 @@ As per TR181, the root of the tree is 'Device.', which can be defined by using b ```bash DM_MAP_OBJ tDynamicObj[] = { -{"Device.", tDeviceObj, tDeviceParams}, +{"Device.", tDMRootObj, tDMRootParams}, {0} }; ``` @@ -74,7 +74,7 @@ Each object in the **DMOBJ** table contains the following arguments: example: ```bash /* *** Device. *** */ -DMOBJ tDeviceObj[] = { +DMOBJ tDMRootObj[] = { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type*/ {"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH, NULL}, {0} @@ -209,7 +209,7 @@ DMLEAF tWiFiDataElementsAssociationEventParams[] = { More leaf Example(s): ```bash -DMLEAF tDeviceParams[] = { +DMLEAF tDMRootParams[] = { /* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ {"RootDataModelVersion", &DMREAD, DMT_STRING, get_Device_RootDataModelVersion, NULL, BBFDM_BOTH}, {"Reboot()", &DMSYNC, DMT_COMMAND, NULL, operate_Device_Reboot, BBFDM_USP}, diff --git a/docs/guide/How_to_extend_datamodel_with_JSON.md b/docs/guide/How_to_extend_datamodel_with_JSON.md index 93e1fd43..5ae73e8f 100644 --- a/docs/guide/How_to_extend_datamodel_with_JSON.md +++ b/docs/guide/How_to_extend_datamodel_with_JSON.md @@ -2,7 +2,7 @@ `bbfdm` provides tools to convert Broadband-forum's xml datamodel definition for cwmp and usp to a combined JSON file. -JSON definition of datamodel with latest release available in [datamodel.json](../../libbbfdm/dmtree/json/datamodel.json) +JSON definition of datamodel with latest release available in [datamodel.json](../../tools/datamodel.json) Now, a partial node from this file can be used to create a JSON datamodel definition, provided user adds a mapping to all LEAF parameters and multi-instance object. diff --git a/docs/guide/bbfdmd.md b/docs/guide/bbfdmd.md index 6a16b13a..6c51eec9 100644 --- a/docs/guide/bbfdmd.md +++ b/docs/guide/bbfdmd.md @@ -12,13 +12,8 @@ { "daemon": { "config": { - "loglevel": "1", - "refresh_time": "120", - "subprocess_level": "2" }, "input": { - "type": "DotSo", - "name": "/usr/share/bbfdm/libbbfdm.so", "plugin_dir": "/usr/share/bbfdm/plugins" }, "output": { @@ -260,8 +255,6 @@ Some datamodel operations takes less time to execute compared to other, like executing/serializing operations simplifies the code from developer perspective, but its not suitable for deployments. To make it suitable `bbfdmd` support parallel calls. - All datamodel `operate` commands are running in parallel -- `get` calls depends on uci option 'bbfdm.bbfdmd.subprocess_level' (default: 2) - example(s): diff --git a/gitlab-ci/shared.sh b/gitlab-ci/shared.sh index 65564e27..17cddaaa 100755 --- a/gitlab-ci/shared.sh +++ b/gitlab-ci/shared.sh @@ -55,7 +55,6 @@ function install_libbbf() COV_LDFLAGS='--coverage' fi - VENDOR_LIST='iopsys' VENDOR_PREFIX='X_IOPSYS_EU_' echo "Compiling libbbf" @@ -65,7 +64,7 @@ function install_libbbf() mkdir -p build cd build - cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm" -DBBF_VENDOR_LIST="$VENDOR_LIST" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/ + cmake ../ -DCMAKE_C_FLAGS="$COV_CFLAGS " -DCMAKE_EXE_LINKER_FLAGS="$COV_LDFLAGS -lm" -DBBF_VENDOR_PREFIX="$VENDOR_PREFIX" -DBBF_MAX_OBJECT_INSTANCES=255 -DBBFDMD_MAX_MSG_LEN=1048576 -DCMAKE_INSTALL_PREFIX=/ exec_cmd_verbose make echo "installing libbbf" diff --git a/gitlab-ci/tools-test.sh b/gitlab-ci/tools-test.sh index a348f55f..6672bf94 100755 --- a/gitlab-ci/tools-test.sh +++ b/gitlab-ci/tools-test.sh @@ -15,7 +15,7 @@ exec_cmd_verbose pylint -d R,C,W0603 tools/*.py echo "********* Validate JSON Plugin *********" echo "Validate BBF Data Model JSON Plugin" -./tools/validate_json_plugin.py libbbfdm/dmtree/json/datamodel.json +./tools/validate_json_plugin.py tools/datamodel.json check_ret $? echo "Validating plugins" diff --git a/libbbfdm-ubus/bbfdm-ubus.c b/libbbfdm-ubus/bbfdm-ubus.c index 4b259929..cc4ff25b 100644 --- a/libbbfdm-ubus/bbfdm-ubus.c +++ b/libbbfdm-ubus/bbfdm-ubus.c @@ -28,14 +28,10 @@ #include "get_helper.h" #include "plugin.h" +#define BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH "/etc/bbfdm/micro_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" -#define BBFDM_DEFAULT_UBUS_OBJ "bbfdm" - -extern struct list_head loaded_json_files; -extern struct list_head json_list; -extern struct list_head json_memhead; LIST_HEAD(head_registered_service); @@ -51,6 +47,7 @@ static void bbfdm_ctx_cleanup(struct bbfdm_context *u) free_path_list(&u->instances); free_path_list(&u->old_instances); + free_path_list(&u->config.list_objs); /* Main daemon */ if (dm_is_micro_service() == false) { @@ -58,11 +55,10 @@ static void bbfdm_ctx_cleanup(struct bbfdm_context *u) } /* DotSo Plugin */ - free_dotso_plugin(deamon_lib_handle); - deamon_lib_handle = NULL; + bbfdm_free_dotso_plugin(&deamon_lib_handle); /* JSON Plugin */ - free_json_plugin(); + bbfdm_free_json_plugin(); } static bool is_sync_operate_cmd(bbfdm_data_t *data __attribute__((unused))) @@ -70,21 +66,6 @@ static bool is_sync_operate_cmd(bbfdm_data_t *data __attribute__((unused))) return false; } -static bool is_subprocess_required(int subprocess_level, const char *path) -{ - bool ret = false; - size_t len = DM_STRLEN(path); - if (len == 0) - return ret; - - if (count_delim(path) < subprocess_level) { - if (path[len - 1] == '.') - ret = true; - } - - return ret; -} - static void fill_optional_data(bbfdm_data_t *data, struct blob_attr *msg) { struct blob_attr *attr; @@ -269,7 +250,6 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ LIST_HEAD(paths_list); bbfdm_data_t data; uint8_t maxdepth = 0; - bool is_subprocess_needed = false; struct bbfdm_context *u; u = container_of(ctx, struct bbfdm_context, ubus_ctx); @@ -291,7 +271,6 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ if (tb[DM_GET_PATH]) { char *path = blobmsg_get_string(tb[DM_GET_PATH]); add_path_list(path, &paths_list); - is_subprocess_needed = is_subprocess_required(u->config.subprocess_level, path); } if (tb[DM_GET_PATHS]) { @@ -303,8 +282,6 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ char *path_str = blobmsg_get_string(path); add_path_list(path_str, &paths_list); - if (!is_subprocess_needed) - is_subprocess_needed = is_subprocess_required(u->config.subprocess_level, path_str); } } @@ -318,12 +295,7 @@ static int bbfdm_get_handler(struct ubus_context *ctx, struct ubus_object *obj _ fill_optional_data(&data, tb[DM_GET_OPTIONAL]); - if (is_subprocess_needed) { - BBF_INFO("Creating subprocess for get method"); - bbfdm_start_deferred(&data, bbfdm_get_value, false); - } else { - bbfdm_get_value(&data, NULL); - } + bbfdm_get_value(&data, NULL); free_path_list(&paths_list); return 0; @@ -1059,6 +1031,7 @@ 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) { @@ -1078,8 +1051,11 @@ static int register_service(struct ubus_context *ctx) blobmsg_add_string(&bb, "parent_dm", u->config.out_parent_dm); void *arr = blobmsg_open_array(&bb, "objects"); - for (int i = 0; i < MAX_OBJS && DM_STRLEN(u->config.out_objects[i]) != 0; i++) - blobmsg_add_string(&bb, NULL, u->config.out_objects[i]); + + 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); @@ -1088,162 +1064,85 @@ static int register_service(struct ubus_context *ctx) return 0; } -static int _parse_daemon_config_options(bbfdm_config_t *config, json_object *daemon_obj) -{ - char *opt_val = NULL; - - if (!config || !daemon_obj) { - fprintf(stderr, "Invalid input options \n"); - return -1; - } - - opt_val = dmjson_get_value(daemon_obj, 2, "config", "loglevel"); - if (DM_STRLEN(opt_val)) { - int log_level = (int) strtoul(opt_val, NULL, 10); - bbfdm_ubus_set_log_level(log_level); - } else { - bbfdm_ubus_set_log_level(LOG_ERR); - } - - opt_val = dmjson_get_value(daemon_obj, 2, "config", "subprocess_level"); - if (DM_STRLEN(opt_val)) { - config->subprocess_level = (unsigned int) strtoul(opt_val, NULL, 10); - } else { - config->subprocess_level = 0; - } - return 0; -} - -static int _parse_daemon_input_options(bbfdm_config_t *config, json_object *daemon_obj) -{ - char *opt_val = NULL; - - if (!config || !daemon_obj) { - fprintf(stderr, "Invalid input options \n"); - return -1; - } - - opt_val = dmjson_get_value(daemon_obj, 2, "input", "plugin_dir"); - if (DM_STRLEN(opt_val)) { - strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); - } else if(dm_is_micro_service() == false) { - strncpyt(config->in_plugin_dir, BBFDM_DEFAULT_PLUGINS_PATH, sizeof(config->in_plugin_dir)); - } - - opt_val = dmjson_get_value(daemon_obj, 2, "input", "name"); - if (DM_STRLEN(opt_val)) { - strncpyt(config->in_name, opt_val, sizeof(config->in_name)); - - opt_val = strrchr(opt_val, '/'); - if (opt_val) { - strncpyt(config->service_name, opt_val + 1, sizeof(config->service_name)); - } - } else if (dm_is_micro_service() == false) { // default value for main process - snprintf(config->in_name, sizeof(config->in_name), "%s/libbbfdm.so", BBFDM_DEFAULT_MODULES_PATH); - strncpyt(config->service_name, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->service_name)); - } - return 0; -} - -static int _fill_daemon_input_option(bbfdm_config_t *config, char *sname) +static int _fill_daemon_input_option(json_object *daemon_obj, bbfdm_config_t *config) { char opt_val[MAX_DM_PATH] = {0}; - if (!config || !sname || strlen(sname) == 0) { - fprintf(stderr, "Invalid input options for service name \n"); + if (!config || strlen(config->service_name) == 0) { + BBF_ERR("Invalid input options for service name \n"); return -1; } - strncpyt(config->service_name, sname, sizeof(config->service_name)); + if (strchr(config->service_name, '/')) { // absolute path + char *srv_name = dmjson_get_value(daemon_obj, 1, "service_name"); + if (strlen(srv_name)) { + strncpyt(config->service_name, srv_name, sizeof(config->service_name)); + } + } // check if the service plugin is DotSO plugin - snprintf(opt_val, MAX_DM_PATH, "%s/%s.so", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, sname); + snprintf(opt_val, MAX_DM_PATH, "%s/%s.so", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); if (!file_exists(opt_val)) { - snprintf(opt_val, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, sname); + snprintf(opt_val, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); } if (!file_exists(opt_val)) { - fprintf(stderr, "Failed to load service plugin %s opt_val=%s\n", sname, opt_val); + BBF_ERR("Failed to load service plugin %s opt_val=%s\n", config->service_name, opt_val); return -1; } strncpyt(config->in_name, opt_val, sizeof(config->in_name)); - snprintf(opt_val, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, sname); - if (folder_exists(opt_val)) { - strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); - } - - return 0; -} - -static int _parse_daemon_output_options(bbfdm_config_t *config, json_object *daemon_obj) -{ - char *opt_val = NULL; - - if (!config || !daemon_obj) { - fprintf(stderr, "Invalid input options \n"); - return -1; - } - - opt_val = dmjson_get_value(daemon_obj, 2, "output", "root_obj"); - if (DM_STRLEN(opt_val)) { - strncpyt(config->out_root_obj, opt_val, sizeof(config->out_root_obj)); - } else if (dm_is_micro_service() == true) { // for main process, there is no root obj - strncpyt(config->out_root_obj, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->out_root_obj)); - } - - opt_val = dmjson_get_value(daemon_obj, 2, "output", "name"); - if (strlen(opt_val)) { - snprintf(config->out_name, sizeof(config->out_name), "%s%s%s", - dm_is_micro_service() ? config->out_root_obj : opt_val, - dm_is_micro_service() ? "." : "", - dm_is_micro_service() ? opt_val : ""); - } else { - snprintf(config->out_name, sizeof(config->out_name), "%s", dm_is_micro_service() ? "" : BBFDM_DEFAULT_UBUS_OBJ); - } - - return 0; -} - -static int _parse_daemon_internal_data_model(bbfdm_config_t *config) -{ - char opt_val[MAX_DM_PATH] = {0}; - - if (!config || !strlen(config->service_name)) - return -1; - - strncpyt(config->in_name, "internal_dm.so", sizeof(config->in_name)); - snprintf(opt_val, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); if (folder_exists(opt_val)) { strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); } - strncpyt(config->out_root_obj, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->out_root_obj)); + return 0; +} + +static int _fill_daemon_output_options(json_object *daemon_obj, bbfdm_config_t *config) +{ + char *opt_val = NULL; + + if (!config || !daemon_obj) { + BBF_ERR("Invalid input options \n"); + return -1; + } + + opt_val = dmjson_get_value(daemon_obj, 2, "output", "root_obj"); + if (DM_STRLEN(opt_val)) { + strncpyt(config->out_root_obj, opt_val, sizeof(config->out_root_obj)); + } else { // for main process, there is no root obj + strncpyt(config->out_root_obj, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->out_root_obj)); + } + + opt_val = dmjson_get_value(daemon_obj, 2, "output", "name"); + if (strlen(opt_val)) { + snprintf(config->out_name, sizeof(config->out_name), "%s.%s", BBFDM_DEFAULT_UBUS_OBJ, opt_val); + } return 0; } -static int bbfdm_load_deamon_config(bbfdm_config_t *config) +static int daemon_load_config_external_plugin(bbfdm_config_t *config) { json_object *json_obj = NULL; char json_path[MAX_DM_PATH] = {0}; int err = 0; - if (INTERNAL_ROOT_TREE) { // internal data model - return _parse_daemon_internal_data_model(config); - } + if (!config || !strlen(config->service_name)) + return -1; - if (dm_is_micro_service() == false) { // Main daemon - strncpyt(json_path, BBFDM_JSON_INPUT, MAX_DM_PATH); - } else { // Micro-services + if (strchr(config->service_name, '/')) { // absolute path + strncpyt(json_path, config->service_name, MAX_DM_PATH); + } else { snprintf(json_path, MAX_DM_PATH, "%s/%s.json", BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH, config->service_name); } json_obj = json_object_from_file(json_path); if (!json_obj) { - fprintf(stderr, "Failed to read input %s file \n", json_path); + BBF_ERR("Failed to read input %s file \n", json_path); return -1; } @@ -1253,23 +1152,13 @@ static int bbfdm_load_deamon_config(bbfdm_config_t *config) goto exit; } - _parse_daemon_config_options(config, daemon_obj); - - char *opt_val = dmjson_get_value(daemon_obj, 1, "service_name"); - if (strlen(opt_val)) { - err = _fill_daemon_input_option(config, opt_val); - } else { - err = _parse_daemon_input_options(config, daemon_obj); - } - + err = _fill_daemon_input_option(daemon_obj, config); if (err == -1) { goto exit; } - _parse_daemon_output_options(config, daemon_obj); + err = _fill_daemon_output_options(daemon_obj, config); - json_object_put(json_obj); - return err; exit: if (json_obj) { json_object_put(json_obj); @@ -1278,7 +1167,51 @@ exit: return err; } -static int bbfdm_regiter_ubus(struct ubus_context *ctx) +static int daemon_load_config_internal_plugin(bbfdm_config_t *config) +{ + char opt_val[MAX_DM_PATH] = {0}; + + if (strlen(config->service_name) == 0 && dm_is_micro_service() == false) { // default value for main process + strncpyt(config->service_name, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->service_name)); + } + + if (!config || strlen(config->service_name) == 0) { + BBF_ERR("Invalid input options for service name \n"); + return -1; + } + + if(dm_is_micro_service() == false) { + strncpyt(config->in_plugin_dir, BBFDM_DEFAULT_PLUGINS_PATH, sizeof(config->in_plugin_dir)); + snprintf(config->out_name, sizeof(config->out_name), "%s", BBFDM_DEFAULT_UBUS_OBJ); + } else { + snprintf(opt_val, MAX_DM_PATH, "%s/%s", BBFDM_DEFAULT_MICROSERVICE_MODULE_PATH, config->service_name); + if (folder_exists(opt_val)) { + strncpyt(config->in_plugin_dir, opt_val, sizeof(config->in_plugin_dir)); + } + + strncpyt(config->out_root_obj, BBFDM_DEFAULT_UBUS_OBJ, sizeof(config->out_root_obj)); + } + + return 0; +} + +static int daemon_load_config(bbfdm_config_t *config) +{ + int err = -1; + + if (INTERNAL_ROOT_TREE) { + err = daemon_load_config_internal_plugin(config); + BBF_INFO("Loading Config Internal plugin (%s)", config->service_name); + } else { + // This API will only be called with micro-services + err = daemon_load_config_external_plugin(config); + BBF_INFO("Loading Config External plugin (%s)", config->service_name); + } + + return err; +} + +static int regiter_ubus_object(struct ubus_context *ctx) { int ret; struct bbfdm_context *u; @@ -1385,37 +1318,26 @@ static void bbfdm_ctx_init(struct bbfdm_context *bbfdm_ctx) INIT_LIST_HEAD(&bbfdm_ctx->instances); INIT_LIST_HEAD(&bbfdm_ctx->old_instances); INIT_LIST_HEAD(&bbfdm_ctx->event_handlers); + INIT_LIST_HEAD(&bbfdm_ctx->config.list_objs); } -static int daemon_load_datamodel(struct bbfdm_context *daemon_ctx) +static int daemon_load_data_model(struct bbfdm_context *daemon_ctx) { int err = -1; - char *file_path = daemon_ctx->config.in_name; - if (DM_STRLEN(file_path) == 0) { - BBF_ERR("Input type/name not supported or defined"); - return -1; - } - - char *ext = strrchr(file_path, '.'); - if (ext == NULL) { - BBF_ERR("Input file without extension"); - } else if (strcasecmp(ext, ".json") == 0) { - BBF_INFO("Loading JSON plugin %s", file_path); - err = load_json_plugin(&loaded_json_files, &json_list, &json_memhead, file_path, &daemon_ctx->config, &DEAMON_DM_ROOT_OBJ); - } else if (strcasecmp(ext, ".so") == 0) { - BBF_INFO("Loading DotSo plugin %s", file_path); - err = load_dotso_plugin(&deamon_lib_handle, file_path, &daemon_ctx->config, &DEAMON_DM_ROOT_OBJ); + if (INTERNAL_ROOT_TREE) { + BBF_INFO("Loading Data Model Internal plugin (%s)", daemon_ctx->config.service_name); + err = bbfdm_load_internal_plugin(INTERNAL_ROOT_TREE, &daemon_ctx->config, &DEAMON_DM_ROOT_OBJ); } else { - BBF_ERR("Input type %s not supported", ext); + BBF_INFO("Loading Data Model External plugin (%s)", daemon_ctx->config.service_name); + err = bbfdm_load_external_plugin(daemon_ctx->config.in_name, &deamon_lib_handle, &daemon_ctx->config, &DEAMON_DM_ROOT_OBJ); } - if (!err) { - BBF_INFO("Loading sub-modules %s", daemon_ctx->config.in_plugin_dir); - bbf_global_init(DEAMON_DM_ROOT_OBJ, daemon_ctx->config.in_plugin_dir); - } else { - BBF_ERR("Failed loading %s", file_path); - } + if (err) + return err; + + BBF_INFO("Loading sub-modules %s", daemon_ctx->config.in_plugin_dir); + bbf_global_init(DEAMON_DM_ROOT_OBJ, daemon_ctx->config.in_plugin_dir); if (DM_STRLEN(daemon_ctx->config.out_name) == 0) { BBF_ERR("output name not defined"); @@ -1428,7 +1350,7 @@ static int daemon_load_datamodel(struct bbfdm_context *daemon_ctx) return -1; } - if (DM_STRLEN(daemon_ctx->config.out_objects[0]) == 0) { + if (list_empty(&daemon_ctx->config.list_objs)) { BBF_ERR("output objects is not defined"); return -1; } @@ -1437,14 +1359,9 @@ static int daemon_load_datamodel(struct bbfdm_context *daemon_ctx) BBF_ERR("output root obj not defined"); return -1; } - - if (DM_STRLEN(daemon_ctx->config.out_name) == 0) { - BBF_ERR("output name obj not defined"); - return -1; - } } - return err; + return 0; } static struct ubus_event_handler add_event = { .cb = lookup_event_cb }; @@ -1456,8 +1373,8 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) err = ubus_connect_ctx(&bbfdm_ctx->ubus_ctx, NULL); if (err != UBUS_STATUS_OK) { - fprintf(stderr, "Failed to connect to ubus"); - return err; + BBF_ERR("Failed to connect to ubus"); + return -5; // Error code -5 indicating that ubus_ctx is connected } uloop_init(); @@ -1465,19 +1382,19 @@ int bbfdm_ubus_regiter_init(struct bbfdm_context *bbfdm_ctx) bbfdm_ctx_init(bbfdm_ctx); - err = bbfdm_load_deamon_config(&bbfdm_ctx->config); + err = daemon_load_config(&bbfdm_ctx->config); if (err) { - fprintf(stderr, "Failed to load %s deamon config\n", bbfdm_ctx->config.service_name); + BBF_ERR("Failed to load config"); return err; } - err = daemon_load_datamodel(bbfdm_ctx); + err = daemon_load_data_model(bbfdm_ctx); if (err) { - BBF_ERR("Failed to load datamodel"); + BBF_ERR("Failed to load data_model"); return err; } - err = bbfdm_regiter_ubus(&bbfdm_ctx->ubus_ctx); + err = regiter_ubus_object(&bbfdm_ctx->ubus_ctx); if (err != UBUS_STATUS_OK) return -1; diff --git a/libbbfdm-ubus/bbfdm-ubus.h b/libbbfdm-ubus/bbfdm-ubus.h index d640d622..5f4993ae 100644 --- a/libbbfdm-ubus/bbfdm-ubus.h +++ b/libbbfdm-ubus/bbfdm-ubus.h @@ -7,14 +7,7 @@ #include -#define BBFDM_DEFAULT_MICROSERVICE_INPUT_PATH "/etc/bbfdm/micro_services" -#define MAX_OBJS 7 - -#ifndef DAEMON_JSON_INPUT -#define BBFDM_JSON_INPUT "/tmp/bbfdm/input.json" -#else -#define BBFDM_JSON_INPUT DAEMON_JSON_INPUT -#endif +#define BBFDM_DEFAULT_UBUS_OBJ "bbfdm" struct bbfdm_async_req { struct ubus_context *ctx; @@ -25,21 +18,14 @@ struct bbfdm_async_req { }; typedef struct bbfdm_config { - int proto; // Protocol identifier, Possible values: { '0', '1', '2' } - int subprocess_level; // Subprocess level - uint32_t refresh_time; // Refresh time + struct list_head list_objs; // Micro-service list of objects to expose char service_name[16]; // 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 char out_name[128]; // Ubus name to use char out_parent_dm[32]; // Parent device for micro-service - char out_objects[MAX_OBJS][32]; // Micro-service objects to expose char out_root_obj[32]; // Ubus name to use as root data model - char cli_in_type[32]; // CLI input type, Possible values: { 'UBUS', 'JSON', 'DotSo' } - char cli_in_name[128]; // CLI input name - char cli_in_plugin_dir[128]; // CLI input plugin directory - char cli_out_type[32]; // CLI output type, Possible values: { 'CLI' } } bbfdm_config_t; struct bbfdm_context { diff --git a/libbbfdm-ubus/plugin.c b/libbbfdm-ubus/plugin.c index a085f1cc..c1097dba 100644 --- a/libbbfdm-ubus/plugin.c +++ b/libbbfdm-ubus/plugin.c @@ -13,9 +13,14 @@ #include #include "common.h" +#include "get_helper.h" #include "plugin/json_plugin.h" +extern struct list_head loaded_json_files; +extern struct list_head json_list; +extern struct list_head json_memhead; + static LIST_HEAD(plugin_mem); static uint8_t find_number_of_objects(DM_MAP_OBJ *dynamic_obj) @@ -31,21 +36,18 @@ static uint8_t find_number_of_objects(DM_MAP_OBJ *dynamic_obj) return len; } -static void fill_dotso_micro_service_out_args(bbfdm_config_t *config, DMOBJ *entryobj, char *parent_dm, int *idx) +static void fill_dotso_micro_service_out_args(bbfdm_config_t *config, DMOBJ *entryobj, char *parent_dm) { char ms_name[128] = {0}; - if (!config || !entryobj || !parent_dm || !idx || *idx >= MAX_OBJS) + if (!config || !entryobj || !parent_dm) return; strncpyt(config->out_parent_dm, parent_dm, sizeof(config->out_parent_dm)); for (; (entryobj && entryobj->obj); entryobj++) { - if (*idx >= MAX_OBJS) - break; - - strncpyt(config->out_objects[(*idx)++], entryobj->obj, sizeof(config->out_objects[0])); + add_path_list(entryobj->obj, &config->list_objs); int len = DM_STRLEN(ms_name); if (len == 0) { @@ -59,93 +61,94 @@ static void fill_dotso_micro_service_out_args(bbfdm_config_t *config, DMOBJ *ent strncpyt(config->out_name, ms_name, sizeof(config->out_name)); } -int load_dotso_plugin(void **lib_handle, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry) +int bbfdm_load_internal_plugin(DM_MAP_OBJ *dynamic_obj, bbfdm_config_t *config, DMOBJ **main_entry) { - if (!lib_handle || !file_path || !strlen(file_path) || !main_entry) { - BBF_ERR("Input validation failed\n"); + if (!dynamic_obj || !config || !main_entry) { + BBF_ERR("Input validation failed"); + return -1; + } + + uint8_t obj_num = find_number_of_objects(dynamic_obj); + if (obj_num == 0) { + BBF_ERR("No Object defined in the required DotSo Plugin\n"); return -1; } dm_dynamic_initmem(&plugin_mem); - DM_MAP_OBJ *dynamic_obj = NULL; - if (strcmp(file_path, "internal_dm.so") == 0) { - dynamic_obj = INTERNAL_ROOT_TREE; - } else { - void *handle = dlopen(file_path, RTLD_NOW|RTLD_LOCAL); - if (!handle) { - BBF_ERR("Plugin failed [%s]\n", dlerror()); - return -1; - } - - *lib_handle = handle; - - //Dynamic Object - *(void **) (&dynamic_obj) = dlsym(handle, "tDynamicObj"); - } - - if (dynamic_obj) { - uint8_t obj_num = find_number_of_objects(dynamic_obj); - if (obj_num == 0) { - BBF_ERR("No Object defined in the required DotSo Plugin\n"); - return -1; - } - - DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(&plugin_mem, obj_num + 1, sizeof(DMOBJ)); - if (dm_entryobj == NULL) { - BBF_ERR("No Memory exists\n"); - return -1; - } - - int out_obj_idx = 0; - - for (int i = 0; dynamic_obj[i].path; i++) { - char *node_obj = dm_dynamic_strdup(&plugin_mem, dynamic_obj[i].path); - unsigned int len = strlen(node_obj); - - if (strncmp(node_obj, ROOT_NODE, strlen(ROOT_NODE)) != 0 || node_obj[len-1] != '.') { - BBF_ERR("Object (%s) not valid\n", node_obj); - return -1; - } - - // Fill out arguments if it is running as micro-service - if (dm_is_micro_service() == true) - fill_dotso_micro_service_out_args(config, dynamic_obj[i].root_obj, node_obj, &out_obj_idx); - - node_obj[len-1] = 0; - - dm_entryobj[i].obj = node_obj; - dm_entryobj[i].permission = &DMREAD; - dm_entryobj[i].nextobj = dynamic_obj[i].root_obj; - dm_entryobj[i].leaf = dynamic_obj[i].root_leaf; - dm_entryobj[i].bbfdm_type = BBFDM_BOTH; - } - - *main_entry = dm_entryobj; - } else { - BBF_ERR("Main entry not available"); + DMOBJ *dm_entryobj = (DMOBJ *)dm_dynamic_calloc(&plugin_mem, obj_num + 1, sizeof(DMOBJ)); + if (dm_entryobj == NULL) { + BBF_ERR("No Memory exists\n"); return -1; } + for (int i = 0; dynamic_obj[i].path; i++) { + char *node_obj = dm_dynamic_strdup(&plugin_mem, dynamic_obj[i].path); + unsigned int len = strlen(node_obj); + + if (strncmp(node_obj, ROOT_NODE, strlen(ROOT_NODE)) != 0 || node_obj[len-1] != '.') { + BBF_ERR("Object (%s) not valid\n", node_obj); + return -1; + } + + // Fill out arguments if it is running as micro-service + if (dm_is_micro_service() == true) + fill_dotso_micro_service_out_args(config, dynamic_obj[i].root_obj, node_obj); + + node_obj[len-1] = 0; + + dm_entryobj[i].obj = node_obj; + dm_entryobj[i].permission = &DMREAD; + dm_entryobj[i].nextobj = dynamic_obj[i].root_obj; + dm_entryobj[i].leaf = dynamic_obj[i].root_leaf; + dm_entryobj[i].bbfdm_type = BBFDM_BOTH; + } + + *main_entry = dm_entryobj; return 0; } -int free_dotso_plugin(void *lib_handle) +int bbfdm_load_dotso_plugin(void **lib_handle, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry) { - if (lib_handle) - dlclose(lib_handle); + if (!lib_handle || !file_path || !strlen(file_path) || !config || !main_entry) { + BBF_ERR("Input validation failed"); + return -1; + } + + DM_MAP_OBJ *dynamic_obj = NULL; + + void *handle = dlopen(file_path, RTLD_NOW|RTLD_LOCAL); + if (!handle) { + BBF_ERR("Plugin failed [%s]\n", dlerror()); + return -1; + } + + *lib_handle = handle; + + //Dynamic Object + *(void **) (&dynamic_obj) = dlsym(handle, "tDynamicObj"); + + return bbfdm_load_internal_plugin(dynamic_obj, config, main_entry); +} + +int bbfdm_free_dotso_plugin(void **lib_handle) +{ + if (*lib_handle) { + dlclose(*lib_handle); + *lib_handle = NULL; + } dm_dynamic_cleanmem(&plugin_mem); return 0; } -static void fill_json_micro_service_out_args(bbfdm_config_t *config, char *parent_dm, char *obj, int idx, char *ms_name, size_t ms_name_len) +static void fill_json_micro_service_out_args(bbfdm_config_t *config, char *parent_dm, char *obj, char *ms_name, size_t ms_name_len) { - if (!config || !obj || idx >= MAX_OBJS) + if (!config || !obj) return; strncpyt(config->out_parent_dm, parent_dm, sizeof(config->out_parent_dm)); - strncpyt(config->out_objects[idx], obj, sizeof(config->out_objects[idx])); + add_path_list(obj, &config->list_objs); int len = DM_STRLEN(ms_name); if (len == 0) { @@ -155,7 +158,7 @@ static void fill_json_micro_service_out_args(bbfdm_config_t *config, char *paren } } -int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, +int bbfdm_load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry) { DMOBJ *dm_entryobj = NULL; @@ -213,7 +216,7 @@ int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, // Fill out arguments if it is running as micro-service if (dm_is_micro_service() == true) - fill_json_micro_service_out_args(config, obj_prefix, obj_name, idx, ms_name, sizeof(ms_name)); + fill_json_micro_service_out_args(config, obj_prefix, obj_name, ms_name, sizeof(ms_name)); // Remove '.' from object prefix if (obj_prefix[obj_prefix_len - 1] == '.') @@ -248,7 +251,32 @@ int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, return 0; } -int free_json_plugin(void) +int bbfdm_free_json_plugin(void) { return free_json_plugins(); } + +int bbfdm_load_external_plugin(const char *file_path, void **lib_handle, bbfdm_config_t *config, DMOBJ **main_entry) +{ + int err = -1; + + if (DM_STRLEN(file_path) == 0) { + BBF_ERR("Input type/name not supported or defined"); + return -1; + } + + char *ext = strrchr(file_path, '.'); + if (ext == NULL) { + BBF_ERR("Input file without extension"); + } else if (strcasecmp(ext, ".json") == 0) { + BBF_INFO("Loading JSON plugin %s", file_path); + err = bbfdm_load_json_plugin(&loaded_json_files, &json_list, &json_memhead, file_path, config, main_entry); + } else if (strcasecmp(ext, ".so") == 0) { + BBF_INFO("Loading DotSo plugin %s", file_path); + err = bbfdm_load_dotso_plugin(lib_handle, file_path, config, main_entry); + } else { + BBF_ERR("Input type %s not supported", ext); + } + + return err; +} diff --git a/libbbfdm-ubus/plugin.h b/libbbfdm-ubus/plugin.h index 6d7b518c..7f92c1f2 100644 --- a/libbbfdm-ubus/plugin.h +++ b/libbbfdm-ubus/plugin.h @@ -10,11 +10,14 @@ #ifndef PLUGIN_H -int load_dotso_plugin(void **lib_handle, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry); -int free_dotso_plugin(void *lib_handle); +int bbfdm_load_internal_plugin(DM_MAP_OBJ *Dynamic_Obj, bbfdm_config_t *config, DMOBJ **main_entry); +int bbfdm_load_external_plugin(const char *file_path, void **lib_handle, bbfdm_config_t *config, DMOBJ **main_entry); -int load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, +int bbfdm_load_dotso_plugin(void **lib_handle, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry); +int bbfdm_free_dotso_plugin(void *lib_handle); + +int bbfdm_load_json_plugin(struct list_head *json_plugin, struct list_head *json_list, struct list_head *json_memhead, const char *file_path, bbfdm_config_t *config, DMOBJ **main_entry); -int free_json_plugin(void); +int bbfdm_free_json_plugin(void); #endif /* PLUGIN_H */ diff --git a/libbbfdm/CMakeLists.txt b/libbbfdm/CMakeLists.txt index cd4ca027..732819b0 100644 --- a/libbbfdm/CMakeLists.txt +++ b/libbbfdm/CMakeLists.txt @@ -2,40 +2,31 @@ cmake_minimum_required(VERSION 3.0) PROJECT(libbbfdm) -ADD_DEFINITIONS(-Wall -Werror -D_GNU_SOURCE) -ADD_DEFINITIONS(-DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}") +OPTION(BBF_VENDOR_EXTENSION "build with vendor extension" ON) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}/dmtree") +ADD_DEFINITIONS(-Wall -Werror -D_GNU_SOURCE -DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}") -OPTION(BBF_TR181 "build with tr181 datamodel" ON) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_SOURCE_DIR} -I${CMAKE_CURRENT_SOURCE_DIR}") +FILE(GLOB BBF_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.c) -IF(BBF_TR181) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/dmtree/tr181") - FILE(GLOB BBF_TR181_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/dmtree/tr181/*.c) - add_compile_definitions(BBF_TR181) -ENDIF(BBF_TR181) - -ADD_LIBRARY(bbfdm SHARED ${BBF_TR181_SOURCES}) +ADD_LIBRARY(bbfdm STATIC ${BBF_SOURCES}) TARGET_LINK_LIBRARIES(bbfdm uci ubus ubox json-c blobmsg_json m bbfdm-api ssl crypto) INSTALL(TARGETS bbfdm - LIBRARY DESTINATION usr/share/bbfdm) - -INSTALL(TARGETS bbfdm - LIBRARY DESTINATION usr/lib) + LIBRARY DESTINATION usr/lib +) INSTALL(DIRECTORY DESTINATION etc/bbfdm) INSTALL(DIRECTORY DESTINATION etc/bbfdm/dmmap) +INSTALL(DIRECTORY DESTINATION usr/share/bbfdm) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/scripts) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/plugins) INSTALL(DIRECTORY DESTINATION usr/share/bbfdm/micro_services) - -INSTALL(DIRECTORY DESTINATION usr/share/bbfdm) INSTALL(DIRECTORY DESTINATION usr/libexec/rpcd) -string(REPLACE "," ";" VENDOR_LIST ${BBF_VENDOR_LIST}) - -foreach(VENDOR ${VENDOR_LIST}) - add_subdirectory(dmtree/vendor/${VENDOR}) -endforeach() +IF(BBF_VENDOR_EXTENSION) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/vendor/vendor.json + DESTINATION usr/share/bbfdm/plugins + ) +ENDIF(BBF_VENDOR_EXTENSION) diff --git a/libbbfdm/dmtree/tr181/device.c b/libbbfdm/device.c similarity index 97% rename from libbbfdm/dmtree/tr181/device.c rename to libbbfdm/device.c index 31823500..c1ca4edd 100644 --- a/libbbfdm/dmtree/tr181/device.c +++ b/libbbfdm/device.c @@ -48,12 +48,12 @@ static int operate_Device_FactoryReset(char *refparam, struct dmctx *ctx, void * /* *** BBFDM *** */ DM_MAP_OBJ tDynamicObj[] = { /* parentobj, nextobject, parameter */ -{"Device.", tDeviceObj, tDeviceParams}, +{"Device.", tDMRootObj, tDMRootParams}, {0} }; /* *** Device. *** */ -DMOBJ tDeviceObj[] = { +DMOBJ tDMRootObj[] = { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys, version*/ {"DeviceInfo", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceInfoObj, tDeviceInfoParams, NULL, BBFDM_BOTH, NULL}, {"LANConfigSecurity", &DMREAD, NULL, NULL, "file:/etc/config/users", NULL, NULL, NULL, NULL, tLANConfigSecurityParams, NULL, BBFDM_BOTH, NULL}, @@ -63,7 +63,7 @@ DMOBJ tDeviceObj[] = { {0} }; -DMLEAF tDeviceParams[] = { +DMLEAF tDMRootParams[] = { /* PARAM, permission, type, getvalue, setvalue, bbfdm_type, version*/ {"RootDataModelVersion", &DMREAD, DMT_STRING, get_Device_RootDataModelVersion, NULL, BBFDM_BOTH}, {"Reboot()", &DMSYNC, DMT_COMMAND, NULL, operate_Device_Reboot, BBFDM_USP}, diff --git a/libbbfdm/dmtree/tr181/device.h b/libbbfdm/device.h similarity index 90% rename from libbbfdm/dmtree/tr181/device.h rename to libbbfdm/device.h index df3524f8..b6d5da37 100644 --- a/libbbfdm/dmtree/tr181/device.h +++ b/libbbfdm/device.h @@ -17,7 +17,7 @@ extern DM_MAP_OBJ tDynamicObj[]; -extern DMOBJ tDeviceObj[]; -extern DMLEAF tDeviceParams[]; +extern DMOBJ tDMRootObj[]; +extern DMLEAF tDMRootParams[]; #endif diff --git a/libbbfdm/dmtree/tr181/deviceinfo.c b/libbbfdm/deviceinfo.c similarity index 100% rename from libbbfdm/dmtree/tr181/deviceinfo.c rename to libbbfdm/deviceinfo.c diff --git a/libbbfdm/dmtree/tr181/deviceinfo.h b/libbbfdm/deviceinfo.h similarity index 100% rename from libbbfdm/dmtree/tr181/deviceinfo.h rename to libbbfdm/deviceinfo.h diff --git a/libbbfdm/dmtree/vendor/iopsys/CMakeLists.txt b/libbbfdm/dmtree/vendor/iopsys/CMakeLists.txt deleted file mode 100644 index 6c878b1a..00000000 --- a/libbbfdm/dmtree/vendor/iopsys/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -cmake_minimum_required(VERSION 3.0) - -PROJECT(libbbfdm_iopsys_ext) - -ADD_DEFINITIONS(-Wall -Werror -D_GNU_SOURCE) -ADD_DEFINITIONS(-DBBF_VENDOR_PREFIX="${BBF_VENDOR_PREFIX}") - -FILE(GLOB BBF_IOPSYS_VENDOR_EXTENSION_SOURCES ../../../dmlayer.c *.c) - -ADD_LIBRARY(bbfdm_iopsys_ext SHARED ${BBF_IOPSYS_VENDOR_EXTENSION_SOURCES}) - -INSTALL(TARGETS bbfdm_iopsys_ext - LIBRARY DESTINATION usr/share/bbfdm/plugins) diff --git a/libbbfdm/dmtree/vendor/iopsys/deviceinfo.c b/libbbfdm/dmtree/vendor/iopsys/deviceinfo.c deleted file mode 100644 index b3e67c44..00000000 --- a/libbbfdm/dmtree/vendor/iopsys/deviceinfo.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author Amin Ben Ramdhane - * - */ - -#include "deviceinfo.h" - -static int get_base_mac_addr(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - db_get_value_string("device", "deviceinfo", "BaseMACAddress", value); - return 0; -} - -/********************************************************************************************************************************** -* OBJ & PARAM DEFINITION -***********************************************************************************************************************************/ -DMLEAF tIOPSYS_DeviceInfoParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -{BBF_VENDOR_PREFIX"BaseMACAddress", &DMREAD, DMT_STRING, get_base_mac_addr, NULL, BBFDM_BOTH}, -{0} -}; diff --git a/libbbfdm/dmtree/vendor/iopsys/deviceinfo.h b/libbbfdm/dmtree/vendor/iopsys/deviceinfo.h deleted file mode 100644 index 7b8a7ff6..00000000 --- a/libbbfdm/dmtree/vendor/iopsys/deviceinfo.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author Amin Ben Ramdhane - * - */ - -#ifndef __IOPSYS_DEVICEINFO_H -#define __IOPSYS_DEVICEINFO_H - -#include "libbbfdm-api/dmcommon.h" - -extern DMLEAF tIOPSYS_DeviceInfoParams[]; - -#endif //__IOPSYS_DEVICEINFO_H diff --git a/libbbfdm/dmtree/vendor/iopsys/extension.c b/libbbfdm/dmtree/vendor/iopsys/extension.c deleted file mode 100644 index 83106f72..00000000 --- a/libbbfdm/dmtree/vendor/iopsys/extension.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author Amin Ben Ramdhane - * - */ - -#include "deviceinfo.h" -#include "extension.h" - -DM_MAP_OBJ tDynamicObj[] = { -/* parentobj, nextobject, parameter */ -{"Device.DeviceInfo.", NULL, tIOPSYS_DeviceInfoParams}, -{0} -}; diff --git a/libbbfdm/dmtree/vendor/iopsys/extension.h b/libbbfdm/dmtree/vendor/iopsys/extension.h deleted file mode 100644 index 031b741e..00000000 --- a/libbbfdm/dmtree/vendor/iopsys/extension.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author Amin Ben Ramdhane - * - */ - -#ifndef __IOPSYS_VENDOR_H -#define __IOPSYS_VENDOR_H - -#include "libbbfdm-api/dmcommon.h" - -extern DM_MAP_OBJ tVendorExtensionIOPSYS[]; - -#endif //__IOPSYS_VENDOR_H diff --git a/libbbfdm/dmtree/vendor/iopsys/vendor.json b/libbbfdm/dmtree/vendor/iopsys/vendor.json deleted file mode 100644 index 87dbd752..00000000 --- a/libbbfdm/dmtree/vendor/iopsys/vendor.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "Device.": { - "type": "object", - "protocols": [ - "cwmp", - "usp" - ], - "description": "The top-level object for a Device.", - "access": false, - "array": false, - "Device.DeviceInfo.": { - "type": "object", - "protocols": [ - "cwmp", - "usp" - ], - "description": "This object contains general device information.", - "access": false, - "array": false, - "{BBF_VENDOR_PREFIX}BaseMACAddress": { - "type": "string", - "read": true, - "write": false, - "protocols": [ - "cwmp", - "usp" - ], - "description": "The MAC Address of the device.", - "datatype": "MACAddress", - "range": [ - { - "max": 17 - } - ], - "pattern": [ - "", - "([0-9A-Fa-f][0-9A-Fa-f]:){5}([0-9A-Fa-f][0-9A-Fa-f])" - ] - } - } - } -} - diff --git a/libbbfdm/dmtree/tr181/gatewayinfo.c b/libbbfdm/gatewayinfo.c similarity index 100% rename from libbbfdm/dmtree/tr181/gatewayinfo.c rename to libbbfdm/gatewayinfo.c diff --git a/libbbfdm/dmtree/tr181/gatewayinfo.h b/libbbfdm/gatewayinfo.h similarity index 100% rename from libbbfdm/dmtree/tr181/gatewayinfo.h rename to libbbfdm/gatewayinfo.h diff --git a/libbbfdm/dmtree/tr181/lanconfigsecurity.c b/libbbfdm/lanconfigsecurity.c similarity index 100% rename from libbbfdm/dmtree/tr181/lanconfigsecurity.c rename to libbbfdm/lanconfigsecurity.c diff --git a/libbbfdm/dmtree/tr181/lanconfigsecurity.h b/libbbfdm/lanconfigsecurity.h similarity index 100% rename from libbbfdm/dmtree/tr181/lanconfigsecurity.h rename to libbbfdm/lanconfigsecurity.h diff --git a/libbbfdm/dmtree/tr181/security.c b/libbbfdm/security.c similarity index 100% rename from libbbfdm/dmtree/tr181/security.c rename to libbbfdm/security.c diff --git a/libbbfdm/dmtree/tr181/security.h b/libbbfdm/security.h similarity index 100% rename from libbbfdm/dmtree/tr181/security.h rename to libbbfdm/security.h diff --git a/libbbfdm/vendor/vendor.json b/libbbfdm/vendor/vendor.json new file mode 100644 index 00000000..1ae730c4 --- /dev/null +++ b/libbbfdm/vendor/vendor.json @@ -0,0 +1,47 @@ +{ + "json_plugin_version": 2, + "Device.DeviceInfo.": { + "type": "object", + "protocols": [ + "cwmp", + "usp" + ], + "description": "This object contains general device information.", + "access": false, + "array": false, + "{BBF_VENDOR_PREFIX}BaseMACAddress": { + "type": "string", + "read": true, + "write": false, + "protocols": [ + "cwmp", + "usp" + ], + "description": "The MAC Address of the device.", + "datatype": "MACAddress", + "range": [ + { + "max": 17 + } + ], + "pattern": [ + "", + "([0-9A-Fa-f][0-9A-Fa-f]:){5}([0-9A-Fa-f][0-9A-Fa-f])" + ], + "mapping": [ + { + "type": "uci", + "uci": { + "file": "/etc/board-db/config/device", + "section": { + "name": "deviceinfo" + }, + "option": { + "name":"BaseMACAddress" + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile index a16d45ad..fea8e37c 100644 --- a/test/cmocka/Makefile +++ b/test/cmocka/Makefile @@ -1,6 +1,6 @@ CC = gcc -CFLAGS = -g -Wall -Werror -LDFLAGS = -lcmocka -lbbfdm-api -lbbfdm -lubox -lblobmsg_json +CFLAGS = -g -Wall -Werror +LDFLAGS = -lcmocka -lbbfdm-api -lbbfdm -lubox -lblobmsg_json -ljson-c -lssl -lcrypto --coverage UNIT_TESTS = unit_test_bbfd FUNCTIONAL_TESTS = functional_test_bbfd FUNCTIONAL_API_TESTS = functional_api_test_bbfd diff --git a/test/cmocka/functional_test_bbfd.c b/test/cmocka/functional_test_bbfd.c index 68f9b692..8d763696 100644 --- a/test/cmocka/functional_test_bbfd.c +++ b/test/cmocka/functional_test_bbfd.c @@ -7,11 +7,11 @@ #include #include -#include "../../libbbfdm/dmtree/tr181/device.h" +#include "../../libbbfdm/device.h" static DMOBJ TR181_ROOT_TREE[] = { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/ -{"Device", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceObj, tDeviceParams, NULL, BBFDM_BOTH}, +{"Device", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDMRootObj, tDMRootParams, NULL, BBFDM_BOTH}, {0} }; @@ -1304,7 +1304,9 @@ static void test_api_bbfdm_valid_standard_list_operate(void **state) if (DM_STRCMP(name, "Device.FactoryReset()") == 0) { assert_string_equal(type, "xsd:command"); assert_string_equal(data, "sync"); - assert_null(data); + assert_non_null(data); + assert_null(command_in); + assert_null(command_out); } if (DM_STRCMP(name, "Device.DeviceInfo.VendorLogFile.{i}.Upload()") == 0) { diff --git a/test/cmocka/unit_test_bbfd.c b/test/cmocka/unit_test_bbfd.c index 1c309c0d..7b7018c0 100644 --- a/test/cmocka/unit_test_bbfd.c +++ b/test/cmocka/unit_test_bbfd.c @@ -7,11 +7,11 @@ #include #include -#include "../../libbbfdm/dmtree/tr181/device.h" +#include "../../libbbfdm/device.h" static DMOBJ TR181_ROOT_TREE[] = { /* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/ -{"Device", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDeviceObj, tDeviceParams, NULL, BBFDM_BOTH}, +{"Device", &DMREAD, NULL, NULL, NULL, NULL, NULL, NULL, tDMRootObj, tDMRootParams, NULL, BBFDM_BOTH}, {0} }; diff --git a/test/files/tmp/bbfdm/input.json b/test/files/tmp/bbfdm/input.json index ce96f7da..d113f79c 100755 --- a/test/files/tmp/bbfdm/input.json +++ b/test/files/tmp/bbfdm/input.json @@ -1,19 +1,4 @@ { - "daemon": { - "config": { - "loglevel": "3", - "subprocess_level": "2" - }, - "input": { - "type": "DotSo", - "name": "/usr/share/bbfdm/libbbfdm.so", - "plugin_dir": "/usr/share/bbfdm/plugins" - }, - "output": { - "type": "UBUS", - "name": "bbfdm" - } - }, "cli": { "config": { "proto": "both" diff --git a/test/tools/dm-cli.c b/test/tools/dm-cli.c new file mode 100644 index 00000000..910b8d24 --- /dev/null +++ b/test/tools/dm-cli.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include + +#include "../../libbbfdm-api/dmapi.h" +#include "../../libbbfdm-ubus/bbfdm-ubus.h" +#include "../../libbbfdm-api/dmentry.h" +#include "../../libbbfdm-ubus/plugin.h" + +#include "../../libbbfdm/device.h" + +static int cli_exec_schema(struct dmctx *bbfdm_ctx, char *in_path) +{ + int err = 0; + + bbfdm_ctx->in_param = in_path; + bbfdm_ctx->nextlevel = false; + bbfdm_ctx->iscommand = true; + bbfdm_ctx->isevent = true; + bbfdm_ctx->isinfo = true; + + err = bbf_entry_method(bbfdm_ctx, BBF_SCHEMA); + if (!err) { + struct blob_attr *cur = NULL; + size_t rem = 0; + + blobmsg_for_each_attr(cur, bbfdm_ctx->bb.head, rem) { + struct blob_attr *tb[3] = {0}; + const struct blobmsg_policy p[3] = { + { "path", BLOBMSG_TYPE_STRING }, + { "data", BLOBMSG_TYPE_STRING }, + { "type", BLOBMSG_TYPE_STRING } + }; + + blobmsg_parse(p, 3, tb, blobmsg_data(cur), blobmsg_len(cur)); + + char *name = (tb[0]) ? blobmsg_get_string(tb[0]) : ""; + char *data = (tb[1]) ? blobmsg_get_string(tb[1]) : ""; + char *type = (tb[2]) ? blobmsg_get_string(tb[2]) : ""; + + printf("%s %s %s\n", name, type, data); + } + } else { + printf("ERROR: %d retrieving %s\n", err, bbfdm_ctx->in_param); + err = -1; + } + + return err; +} + +int main(int argc, char **argv) +{ + DMOBJ *CLI_DM_ROOT_OBJ = NULL; + void *cli_lib_handle = NULL; + struct dmctx bbfdm_ctx = {0}; + bbfdm_config_t bbfdm_config = {0}; + char *plugin_path = NULL, *plugin_dir = NULL, *dm_path = NULL; + unsigned int proto = BBFDM_BOTH; + int err = 0, ch; + + memset(&bbfdm_ctx, 0, sizeof(struct dmctx)); + + while ((ch = getopt(argc, argv, "hc:u:l:p:")) != -1) { + switch (ch) { + case 'c': + bbfdm_ctx.dm_type = BBFDM_CWMP; + dm_path = argv[optind - 1]; + break; + case 'u': + bbfdm_ctx.dm_type = BBFDM_USP; + dm_path = argv[optind - 1]; + break; + case 'l': + plugin_path = optarg; + break; + case 'p': + plugin_dir = optarg; + break; + default: + break; + } + } + + if (plugin_path == NULL) { + err = bbfdm_load_internal_plugin(tDynamicObj, &bbfdm_config, &CLI_DM_ROOT_OBJ); + } else { + err = bbfdm_load_dotso_plugin(&cli_lib_handle, plugin_path, &bbfdm_config, &CLI_DM_ROOT_OBJ); + } + + if (err || !CLI_DM_ROOT_OBJ) { + printf("ERROR: Failed to load plugin\n"); + return -1; + } + + if (!dm_path) { + printf("ERROR: Data Model path should be defined\n"); + return -1; + } + + // Initialize global context + bbf_global_init(CLI_DM_ROOT_OBJ, plugin_dir); + + // Initialize the bbfdm context + bbf_ctx_init(&bbfdm_ctx, CLI_DM_ROOT_OBJ); + + err = cli_exec_schema(&bbfdm_ctx, dm_path); + + // Clean up the context and global resources + bbf_ctx_clean(&bbfdm_ctx); + bbf_global_clean(CLI_DM_ROOT_OBJ); + + // Free plugin handle + bbfdm_free_dotso_plugin(&cli_lib_handle); + + return err; +} diff --git a/tools/README.md b/tools/README.md index b21d7332..1fc5c46d 100644 --- a/tools/README.md +++ b/tools/README.md @@ -93,7 +93,7 @@ This tool helps in validating the json schema, which is very helpful in the deve ```bash $ ./tools/validate_json_plugin.py test/files/etc/bbfdm/json/X_IOPSYS_EU_TEST.json -$ ./tools/validate_json_plugin.py dmtree/json/datamodel.json +$ ./tools/validate_json_plugin.py tools/datamodel.json ``` More examples available in [this path](../test/files/usr/share/bbfdm/plugins). @@ -135,7 +135,6 @@ The parameters/keys used in tools_input.json file are mostly self-explanatory bu | product_class" | The product class, e.g., "DG400PRIME" | | model_name | The model name, e.g., "DG400PRIME-A" | | software_version | The software version, e.g., "1.2.3.4" | -| vendor_list | This option should have the same name of the vendor directory names, e.g., ["iopsys"] | | dm_json_files | This should contain the list of json file path, where each file contains the definition of DM objects/parameters | | vendor_prefix | The prefix used by vendor for vendor extension in DM objects/parameters, e.g., "X_IOPSYS_EU_" | | plugins | A list of plugins with associated repositories and data model files | @@ -153,7 +152,7 @@ The parameters/keys used in tools_input.json file are mostly self-explanatory bu > Note: -> To add more description about the vendor extended DM objects/parameters, it is required to add the definition of the required/related DM objects/parameters in a json file (The json structure should follow same format as given in [datamodel.json](../libbbfdm/dmtree/json/datamodel.json)), The same json file need to be defined in dm_json_files list. +> To add more description about the vendor extended DM objects/parameters, it is required to add the definition of the required/related DM objects/parameters in a json file (The json structure should follow same format as given in [datamodel.json](datamodel.json)), The same json file need to be defined in dm_json_files list. The input json file should be defined as follow: @@ -166,12 +165,8 @@ The input json file should be defined as follow: "product_class": "DG400PRIME", "model_name": "DG400PRIME-A", "software_version": "1.2.3.4", - "vendor_list": [ - "iopsys", - "test" - ], "dm_json_files": [ - "../libbbfdm/dmtree/json/datamodel.json" + "tools/datamodel.json" ] "vendor_prefix": "X_IOPSYS_EU_", "plugins": [ diff --git a/tools/bbf_common.py b/tools/bbf_common.py index a0f8c336..5890e3e8 100755 --- a/tools/bbf_common.py +++ b/tools/bbf_common.py @@ -7,7 +7,6 @@ import sys import os import subprocess import shutil -import json import glob # Constants @@ -16,7 +15,7 @@ CURRENT_PATH = os.getcwd() BBF_PLUGIN_DIR = "/usr/share/bbfdm/plugins/" BBF_MS_DIR = "/usr/share/bbfdm/micro_services/" -DM_JSON_FILE = os.path.join(CURRENT_PATH, "libbbfdm", "dmtree", "json", "datamodel.json") +DM_JSON_FILE = os.path.join(CURRENT_PATH, "tools", "datamodel.json") LIST_SUPPORTED_USP_DM = [] LIST_SUPPORTED_CWMP_DM = [] @@ -97,15 +96,6 @@ def obj_has_param(value): return False -def get_vendor_list(val): - vendor_list = "" - if isinstance(val, list): - for vendor in val: - vendor_list = vendor if not vendor_list else ( - vendor_list + "," + vendor) - return vendor_list - - def get_option_value(value, option, default=None): if isinstance(value, dict): for obj, val in value.items(): @@ -184,7 +174,7 @@ def generate_shared_library(dm_name, source_files, vendor_prefix, extra_dependen return False -def build_and_install_bbfdm(vendor_prefix, vendor_list): +def build_and_install_bbfdm(vendor_prefix): print("Compiling and installing bbfdmd in progress ...") create_folder(os.path.join(CURRENT_PATH, "build")) @@ -196,18 +186,11 @@ def build_and_install_bbfdm(vendor_prefix, vendor_list): else: VENDOR_PREFIX = "X_IOPSYS_EU_" - # Set vendor list - if vendor_list is None: - VENDOR_LIST = "iopsys" - else: - VENDOR_LIST = get_vendor_list(vendor_list) - # Build and install bbfdm cmake_command = [ "cmake", "../", "-DBBF_SCHEMA_FULL_TREE=ON", - f"-DBBF_VENDOR_LIST={VENDOR_LIST}", f"-DBBF_VENDOR_PREFIX={VENDOR_PREFIX}", "-DBBF_MAX_OBJECT_INSTANCES=255", "-DBBFDMD_MAX_MSG_LEN=1048576", @@ -229,41 +212,52 @@ def build_and_install_bbfdm(vendor_prefix, vendor_list): print('Compiling and installing bbfdmd done') -def create_bbfdm_input_json_file(proto, dm_name=None): - data = { - "daemon": { - }, - "cli": { - "config": { - "proto": proto - }, - "input": { - "type": "DotSo", - "name": "/usr/share/bbfdm/libbbfdm.so", - "plugin_dir": "/usr/share/bbfdm/plugins" - }, - "output": { - "type": "CLI" - } - } - } +def build_and_install_dmcli(): + print("Compiling and installing dm-cli in progress ...") + create_folder(os.path.join(CURRENT_PATH, "build")) + cd_dir(os.path.join(CURRENT_PATH, "build")) + + # GCC command to compile dm-cli + gcc_command = [ + "gcc", + "../test/tools/dm-cli.c", + "-lbbfdm-api", + "-lbbfdm-ubus", + "-lubox", + "-lblobmsg_json", + "-lbbfdm", + "-ljson-c", + "-lssl", + "-lcrypto", + "-o", "dm-cli" + ] + + try: + subprocess.check_call(gcc_command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + subprocess.check_call(["mv", "dm-cli", "/usr/sbin/dm-cli"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as e: + print(f"Error running commands: {e}") + sys.exit(1) + + cd_dir(CURRENT_PATH) + remove_folder(os.path.join(CURRENT_PATH, "build")) + print('Compiling and installing dm-cli done') + + +def fill_list_dm(proto, dm_list, dm_name=None): + # Determine the base command depending on the presence of dm_name if dm_name: - del data["cli"]["input"]["plugin_dir"] - data["cli"]["input"]["name"] = dm_name + command = f"dm-cli -l {dm_name}" + else: + command = "dm-cli -p /usr/share/bbfdm/plugins" - file_path = '/tmp/bbfdm/input.json' - - # Ensure the directory exists - os.makedirs(os.path.dirname(file_path), exist_ok=True) + # Add the appropriate flag (-c or -u) based on the proto value + if proto == "cwmp": + command += " -c Device." + elif proto == "usp": + command += " -u Device." - # Open the file in 'w' mode (create or truncate) - with open(file_path, 'w', encoding='utf-8') as json_file: - json.dump(data, json_file, indent=4) - - -def fill_list_dm(dm_list): - command = "bbfdmd -c schema Device." try: # Run the command result = subprocess.run(command, shell=True, text=True, capture_output=True, check=True) @@ -308,8 +302,7 @@ def remove_duplicate_elements(input_list): def fill_list_supported_dm(): for proto, DB in [("usp", LIST_SUPPORTED_USP_DM), ("cwmp", LIST_SUPPORTED_CWMP_DM)]: - create_bbfdm_input_json_file(proto) - fill_list_dm(DB) + fill_list_dm(proto, DB) DB.sort(key=lambda x: x['param'], reverse=False) DB[:] = remove_duplicate_elements(DB) @@ -318,8 +311,7 @@ def fill_list_supported_dm(): if os.path.isfile(f): for proto, DB in [("usp", LIST_SUPPORTED_USP_DM), ("cwmp", LIST_SUPPORTED_CWMP_DM)]: - create_bbfdm_input_json_file(proto, f) - fill_list_dm(DB) + fill_list_dm(proto, DB, f) DB.sort(key=lambda x: x['param'], reverse=False) DB[:] = remove_duplicate_elements(DB) @@ -428,18 +420,20 @@ def download_and_build_plugins(plugins, vendor_prefix): print('Generating plugins completed.') -def generate_supported_dm(vendor_prefix=None, vendor_list=None, plugins=None): +def generate_supported_dm(vendor_prefix=None, plugins=None): ''' Generates supported data models and performs necessary actions. Args: vendor_prefix (str, optional): Vendor prefix for shared libraries. - vendor_list (list, optional): List of vendor data models. plugins (list, optional): List of plugin configurations. ''' # Build && Install bbfdm - build_and_install_bbfdm(vendor_prefix, vendor_list) + build_and_install_bbfdm(vendor_prefix) + + # Build && Install dm-cli + build_and_install_dmcli() # Download && Build Plugins Data Models download_and_build_plugins(plugins, vendor_prefix) diff --git a/libbbfdm/dmtree/json/datamodel.json b/tools/datamodel.json similarity index 100% rename from libbbfdm/dmtree/json/datamodel.json rename to tools/datamodel.json diff --git a/tools/generate_dm.py b/tools/generate_dm.py index a34c41fc..202b0403 100755 --- a/tools/generate_dm.py +++ b/tools/generate_dm.py @@ -25,7 +25,6 @@ if len(sys.argv) < 2: print_dm_usage() VENDOR_PREFIX = None -VENDOR_LIST = None PLUGINS = None OUTPUT = None DM_JSON_FILES = None @@ -67,10 +66,6 @@ for option, value in json_data.items(): VENDOR_PREFIX = value continue - elif option == "vendor_list": - VENDOR_LIST = value - continue - elif option == "dm_json_files": DM_JSON_FILES = value continue @@ -90,7 +85,7 @@ for option, value in json_data.items(): if OUTPUT is None: bbf.download_and_build_plugins(PLUGINS, VENDOR_PREFIX) else: - bbf.generate_supported_dm(VENDOR_PREFIX, VENDOR_LIST, PLUGINS) + bbf.generate_supported_dm(VENDOR_PREFIX, PLUGINS) file_format = bbf.get_option_value(OUTPUT, "file_format", ['xml']) output_file_prefix = bbf.get_option_value(OUTPUT, "output_file_prefix", "datamodel") diff --git a/tools/generate_dm_excel.py b/tools/generate_dm_excel.py index 0edbbee9..d0ec7cc7 100755 --- a/tools/generate_dm_excel.py +++ b/tools/generate_dm_excel.py @@ -196,13 +196,6 @@ if __name__ == '__main__': help= 'Includes OBJ/PARAM defined under remote repositories defined as bbf plugin' ) - parser.add_argument( - '-v', '--vendor-list', - metavar='iopsys', - action = 'append', - help='Generate data model tree with vendor extension OBJ/PARAM' - ) - parser.add_argument( '-p', '--vendor-prefix', default = 'X_IOPSYS_EU_', @@ -232,7 +225,7 @@ if __name__ == '__main__': plugins.append(r) - bbf.generate_supported_dm(args.vendor_prefix, args.vendor_list, plugins) + bbf.generate_supported_dm(args.vendor_prefix, plugins) generate_excel(args.output) print(f'Datamodel generation completed, aritifacts available in {args.output}') sys.exit(bbf.BBF_ERROR_CODE) diff --git a/tools/generate_dm_xml.py b/tools/generate_dm_xml.py index c2256ec3..eb2680bb 100755 --- a/tools/generate_dm_xml.py +++ b/tools/generate_dm_xml.py @@ -390,13 +390,6 @@ if __name__ == '__main__': help= 'Includes OBJ/PARAM defined under remote repositories defined as bbf plugin' ) - parser.add_argument( - '-v', '--vendor-list', - metavar='iopsys', - action = 'append', - help='Generate data model tree with vendor extension OBJ/PARAM.' - ) - parser.add_argument( '-p', '--vendor-prefix', default = 'X_IOPSYS_EU_', @@ -483,7 +476,7 @@ if __name__ == '__main__': plugins.append(r) - bbf.generate_supported_dm(args.vendor_prefix, args.vendor_list, plugins) + bbf.generate_supported_dm(args.vendor_prefix, plugins) generate_xml(args.format, args.dm_json_files, args.output) print(f'Datamodel generation completed, aritifacts available in {args.output}') sys.exit(bbf.BBF_ERROR_CODE) diff --git a/tools/tools_input.json b/tools/tools_input.json index e9d531df..ec8d1fa8 100644 --- a/tools/tools_input.json +++ b/tools/tools_input.json @@ -5,12 +5,9 @@ "product_class": "DG400PRIME", "model_name": "DG400PRIME-A", "software_version": "1.2.3.4", - "vendor_list": [ - "iopsys" - ], "dm_json_files": [ - "libbbfdm/dmtree/json/datamodel.json", - "libbbfdm/dmtree/vendor/iopsys/vendor.json" + "tools/datamodel.json", + "libbbfdm/vendor/vendor.json" ], "vendor_prefix": "X_IOPSYS_EU_", "plugins": [