lib: add native RPC processing to mgmt frontend client

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
This commit is contained in:
Igor Ryzhov 2024-03-20 00:46:07 +02:00
parent cb6c182852
commit a94f74bc2e
6 changed files with 154 additions and 0 deletions

View file

@ -360,6 +360,33 @@ int mgmt_fe_send_edit_req(struct mgmt_fe_client *client, uint64_t session_id,
return ret;
}
int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client, uint64_t session_id,
uint64_t req_id, LYD_FORMAT request_type,
const char *xpath, const char *data)
{
struct mgmt_msg_rpc *msg;
int ret;
msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc, 0,
MTYPE_MSG_NATIVE_RPC);
msg->refer_id = session_id;
msg->req_id = req_id;
msg->code = MGMT_MSG_CODE_RPC;
msg->request_type = request_type;
mgmt_msg_native_xpath_encode(msg, xpath);
if (data)
mgmt_msg_native_append(msg, data, strlen(data) + 1);
debug_fe_client("Sending RPC_REQ session-id %" PRIu64 " req-id %" PRIu64
" xpath: %s",
session_id, req_id, xpath);
ret = mgmt_msg_native_send_msg(&client->client.conn, msg, false);
mgmt_msg_native_free_msg(msg);
return ret;
}
static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
Mgmtd__FeMessage *fe_msg)
{
@ -534,6 +561,7 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
struct mgmt_msg_notify_data *notify_msg;
struct mgmt_msg_tree_data *tree_msg;
struct mgmt_msg_edit_reply *edit_msg;
struct mgmt_msg_rpc_reply *rpc_msg;
struct mgmt_msg_error *err_msg;
const char *xpath = NULL;
const char *data = NULL;
@ -608,6 +636,23 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
session->user_ctx, msg->req_id,
xpath);
break;
case MGMT_MSG_CODE_RPC_REPLY:
if (!session->client->cbs.rpc_notify)
return;
rpc_msg = (typeof(rpc_msg))msg;
if (msg_len < sizeof(*rpc_msg)) {
log_err_fe_client("Corrupt rpc-reply msg recv");
return;
}
dlen = msg_len - sizeof(*rpc_msg);
session->client->cbs.rpc_notify(client, client->user_data,
session->client_id,
msg->refer_id,
session->user_ctx, msg->req_id,
dlen ? rpc_msg->data : NULL);
break;
case MGMT_MSG_CODE_NOTIFY:
if (!session->client->cbs.async_notification)
return;

View file

@ -120,6 +120,12 @@ struct mgmt_fe_client_cbs {
uintptr_t session_ctx, uint64_t req_id,
const char *xpath);
/* Called when RPC result is returned */
int (*rpc_notify)(struct mgmt_fe_client *client, uintptr_t user_data,
uint64_t client_id, uint64_t session_id,
uintptr_t session_ctx, uint64_t req_id,
const char *result);
/* Called with asynchronous notifications from backends */
int (*async_notification)(struct mgmt_fe_client *client,
uintptr_t user_data, uint64_t client_id,
@ -454,6 +460,35 @@ extern int mgmt_fe_send_edit_req(struct mgmt_fe_client *client,
uint8_t flags, uint8_t operation,
const char *xpath, const char *data);
/*
* Send RPC request to MGMTD daemon.
*
* client
* Client object.
*
* session_id
* Client session ID.
*
* req_id
* Client request ID.
*
* result_type
* The LYD_FORMAT of the result.
*
* xpath
* the xpath of the RPC.
*
* data
* the data tree.
*
* Returns:
* 0 on success, otherwise msg_conn_send_msg() return values.
*/
extern int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client,
uint64_t session_id, uint64_t req_id,
LYD_FORMAT request_type, const char *xpath,
const char *data);
/*
* Destroy library and cleanup everything.
*/

View file

@ -322,6 +322,22 @@ int nb_cli_rpc(struct vty *vty, const char *xpath, struct lyd_node **output_p)
assert(err == LY_SUCCESS);
}
if (vty_mgmt_fe_enabled()) {
char *data = NULL;
err = lyd_print_mem(&data, input, LYD_JSON, LYD_PRINT_SHRINK);
assert(err == LY_SUCCESS);
ret = vty_mgmt_send_rpc_req(vty, LYD_JSON, xpath, data);
free(data);
lyd_free_all(input);
if (ret < 0)
return CMD_WARNING;
return CMD_SUCCESS;
}
/* validate input tree to create implicit defaults */
err = lyd_validate_op(input, NULL, LYD_TYPE_RPC_YANG, NULL);
assert(err == LY_SUCCESS);

View file

@ -3843,6 +3843,26 @@ static int vty_mgmt_edit_result_notified(struct mgmt_fe_client *client,
return 0;
}
static int vty_mgmt_rpc_result_notified(struct mgmt_fe_client *client,
uintptr_t user_data, uint64_t client_id,
uint64_t session_id,
uintptr_t session_ctx, uint64_t req_id,
const char *result)
{
struct vty *vty = (struct vty *)session_ctx;
debug_fe_client("RPC request for client 0x%" PRIx64 " req-id %" PRIu64
" was successful",
client_id, req_id);
if (result)
vty_out(vty, "%s\n", result);
vty_mgmt_resume_response(vty, CMD_SUCCESS);
return 0;
}
static int vty_mgmt_error_notified(struct mgmt_fe_client *client,
uintptr_t user_data, uint64_t client_id,
uint64_t session_id, uintptr_t session_ctx,
@ -3885,6 +3905,7 @@ static struct mgmt_fe_client_cbs mgmt_cbs = {
.get_data_notify = vty_mgmt_get_data_result_notified,
.get_tree_notify = vty_mgmt_get_tree_result_notified,
.edit_notify = vty_mgmt_edit_result_notified,
.rpc_notify = vty_mgmt_rpc_result_notified,
.error_notify = vty_mgmt_error_notified,
};
@ -4162,6 +4183,25 @@ int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
return 0;
}
int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type,
const char *xpath, const char *data)
{
vty->mgmt_req_id++;
if (mgmt_fe_send_rpc_req(mgmt_fe_client, vty->mgmt_session_id,
vty->mgmt_req_id, request_type, xpath, data)) {
zlog_err("Failed to send RPC to MGMTD session-id: %" PRIu64
" req-id %" PRIu64 ".",
vty->mgmt_session_id, vty->mgmt_req_id);
vty_out(vty, "Failed to send RPC to MGMTD!\n");
return -1;
}
vty->mgmt_req_pending_cmd = "MESSAGE_RPC_REQ";
return 0;
}
/* Install vty's own commands like `who' command. */
void vty_init(struct event_loop *master_thread, bool do_command_logging)
{

View file

@ -427,6 +427,8 @@ extern int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
LYD_FORMAT request_type, uint8_t flags,
uint8_t operation, const char *xpath,
const char *data);
extern int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type,
const char *xpath, const char *data);
extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
bool lock, bool scok);
extern void vty_mgmt_resume_response(struct vty *vty, int ret);

View file

@ -296,6 +296,21 @@ DEFPY(mgmt_edit, mgmt_edit_cmd,
return CMD_SUCCESS;
}
DEFPY(mgmt_rpc, mgmt_rpc_cmd,
"mgmt rpc XPATH [json|xml]$fmt [DATA]",
MGMTD_STR
"Invoke RPC\n"
"XPath expression specifying the YANG data path\n"
"JSON input format (default)\n"
"XML input format\n"
"Input data tree\n")
{
LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON;
vty_mgmt_send_rpc_req(vty, format, xpath, data);
return CMD_SUCCESS;
}
DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
"show mgmt get-config [candidate|operational|running]$dsname WORD$path",
SHOW_STR MGMTD_STR
@ -702,6 +717,7 @@ void mgmt_vty_init(void)
install_element(CONFIG_NODE, &mgmt_remove_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_replace_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_edit_cmd);
install_element(CONFIG_NODE, &mgmt_rpc_cmd);
install_element(CONFIG_NODE, &mgmt_load_config_cmd);
install_element(CONFIG_NODE, &mgmt_save_config_cmd);
install_element(CONFIG_NODE, &mgmt_rollback_cmd);