Pre-register micro-services

This commit is contained in:
Vivek Kumar Dutta 2024-12-04 15:00:53 +05:30
parent 311609a16f
commit c715185237
10 changed files with 182 additions and 161 deletions

View file

@ -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;

View file

@ -30,3 +30,5 @@ echo "Starting base services..."
supervisorctl reread
supervisorctl update
sleep 10
ubus list

View file

@ -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

View file

@ -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__

View file

@ -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);
}
}

View file

@ -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);
}
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;
}
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();
}

View file

@ -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

View file

@ -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"
}
}
}

View file

@ -0,0 +1,16 @@
{
"daemon": {
"enable": "1",
"service_name": "sysmngr",
"unified_daemon": true,
"services": [
{
"parent_dm": "Device.",
"object": "DeviceInfo"
}
],
"config": {
"loglevel": "3"
}
}
}

View file

@ -0,0 +1,16 @@
{
"daemon": {
"enable": "1",
"service_name": "wifidmd",
"unified_daemon": false,
"services": [
{
"parent_dm": "Device.",
"object": "WiFi"
}
],
"config": {
"loglevel": "3"
}
}
}