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)
{
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;
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;
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,
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.
*/
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);
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,
.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,
};
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)
{
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);
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
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);