/*
* Send get-data request.
*/
-int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
- uint64_t session_id, uint64_t req_id,
- LYD_FORMAT result_type, const char *xpath)
+int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client, uint64_t session_id,
+ uint64_t req_id, LYD_FORMAT result_type,
+ uint8_t flags, const char *xpath)
{
struct mgmt_msg_get_data *msg;
size_t xplen = strlen(xpath);
msg->req_id = req_id;
msg->code = MGMT_MSG_CODE_GET_DATA;
msg->result_type = result_type;
+ msg->flags = flags;
strlcpy(msg->xpath, xpath, xplen + 1);
MGMTD_FE_CLIENT_DBG("Sending GET_DATA_REQ session-id %" PRIu64
#include "mgmt_pb.h"
#include "frrevent.h"
#include "mgmt_defines.h"
+#include "mgmt_msg_native.h"
/***************************************************************
* Macros
* result_type
* The LYD_FORMAT of the result.
*
+ * flags
+ * Flags to control the behavior of the request.
+ *
* xpath
* the xpath to get.
*
*/
extern int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
uint64_t session_id, uint64_t req_id,
- LYD_FORMAT result_type, const char *xpath);
+ LYD_FORMAT result_type, uint8_t flags,
+ const char *xpath);
/*
* Destroy library and cleanup everything.
offsetof(struct mgmt_msg_tree_data, result),
"Size mismatch");
+/* Flags for get-data request */
+#define GET_DATA_FLAG_STATE 0x01 /* get only "config false" data */
+#define GET_DATA_FLAG_CONFIG 0x02 /* get only "config true" data */
+
/**
* struct mgmt_msg_get_data - frontend get-data request.
*
* @result_type: ``LYD_FORMAT`` for the returned result.
+ * @flags: combination of ``GET_DATA_FLAG_*`` flags.
* @xpath: the query for the data to return.
*/
struct mgmt_msg_get_data {
struct mgmt_msg_header;
uint8_t result_type;
- uint8_t resv2[7];
+ uint8_t flags;
+ uint8_t resv2[6];
alignas(8) char xpath[];
};
}
int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type,
- const char *xpath)
+ uint8_t flags, const char *xpath)
{
LYD_FORMAT intern_format = result_type;
vty->mgmt_req_id++;
if (mgmt_fe_send_get_data_req(mgmt_fe_client, vty->mgmt_session_id,
- vty->mgmt_req_id, intern_format, xpath)) {
+ vty->mgmt_req_id, intern_format, flags,
+ xpath)) {
zlog_err("Failed to send GET-DATA to MGMTD session-id: %" PRIu64
" req-id %" PRIu64 ".",
vty->mgmt_session_id, vty->mgmt_req_id);
Mgmtd__DatastoreId datastore,
const char **xpath_list, int num_req);
extern int vty_mgmt_send_get_data_req(struct vty *vty, LYD_FORMAT result_type,
- const char *xpath);
+ uint8_t flags, const char *xpath);
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);
darr_free(snodes);
clients = mgmt_be_interested_clients(msg->xpath, false);
- if (!clients) {
+ if (!clients && !CHECK_FLAG(msg->flags, GET_DATA_FLAG_CONFIG)) {
MGMTD_FE_ADAPTER_DBG("No backends provide xpath: %s for txn-id: %" PRIu64
" session-id: %" PRIu64,
msg->xpath, session->txn_id,
/* Create a GET-TREE request under the transaction */
ret = mgmt_txn_send_get_tree_oper(session->txn_id, req_id, clients,
- msg->result_type, simple_xpath,
- msg->xpath);
+ msg->result_type, msg->flags,
+ simple_xpath, msg->xpath);
if (ret) {
/* destroy the just created txn */
mgmt_destroy_txn(&session->txn_id);
*/
int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id,
uint64_t clients, LYD_FORMAT result_type,
- bool simple_xpath, const char *xpath)
+ uint8_t flags, bool simple_xpath,
+ const char *xpath)
{
struct mgmt_msg_get_tree *msg;
struct mgmt_txn_ctx *txn;
get_tree->simple_xpath = simple_xpath;
get_tree->xpath = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
+ if (CHECK_FLAG(flags, GET_DATA_FLAG_CONFIG)) {
+ struct mgmt_ds_ctx *ds =
+ mgmt_ds_get_ctx_by_id(mm, MGMTD_DS_RUNNING);
+ struct nb_config *config = mgmt_ds_get_nb_config(ds);
+
+ if (config) {
+ struct ly_set *set = NULL;
+ LY_ERR err;
+
+ err = lyd_find_xpath(config->dnode, xpath, &set);
+ if (err) {
+ get_tree->partial_error = err;
+ goto state;
+ }
+
+ /*
+ * If there's a single result, duplicate the returned
+ * node. If there are multiple results, duplicate the
+ * whole config and mark simple_xpath as false so the
+ * result is trimmed later in txn_get_tree_data_done.
+ */
+ if (set->count == 1) {
+ err = lyd_dup_single(set->dnodes[0], NULL,
+ LYD_DUP_WITH_PARENTS |
+ LYD_DUP_WITH_FLAGS |
+ LYD_DUP_RECURSIVE,
+ &get_tree->client_results);
+ if (!err)
+ while (get_tree->client_results->parent)
+ get_tree->client_results = lyd_parent(
+ get_tree->client_results);
+ } else if (set->count > 1) {
+ err = lyd_dup_siblings(config->dnode, NULL,
+ LYD_DUP_RECURSIVE |
+ LYD_DUP_WITH_FLAGS,
+ &get_tree->client_results);
+ if (!err)
+ get_tree->simple_xpath = false;
+ }
+
+ if (err)
+ get_tree->partial_error = err;
+
+ ly_set_free(set, NULL);
+ }
+ }
+state:
+ /* If we are only getting config, we are done */
+ if (!CHECK_FLAG(flags, GET_DATA_FLAG_STATE) || !clients)
+ return txn_get_tree_data_done(txn, txn_req);
+
msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_get_tree, slen + 1,
MTYPE_MSG_NATIVE_GET_TREE);
msg->refer_id = txn_id;
* req_id: FE client request identifier.
* clients: Bitmask of clients to send get-tree to.
* result_type: LYD_FORMAT result format.
+ * flags: option flags for the request.
* simple_xpath: true if xpath is simple (only key predicates).
* xpath: The xpath to get the tree from.
*
*/
extern int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id,
uint64_t clients, LYD_FORMAT result_type,
- bool simple_xpath, const char *xpath);
+ uint8_t flags, bool simple_xpath,
+ const char *xpath);
/*
* Notifiy backend adapter on connection.
}
DEFPY(show_mgmt_get_data, show_mgmt_get_data_cmd,
- "show mgmt get-data WORD$path [json|xml]$fmt",
+ "show mgmt get-data WORD$path [with-config|only-config]$content [json|xml]$fmt",
SHOW_STR
MGMTD_STR
"Get a data from the operational datastore\n"
"XPath expression specifying the YANG data root\n"
+ "Include \"config true\" data\n"
+ "Get only \"config true\" data\n"
"JSON output format\n"
"XML output format\n")
{
LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON;
int plen = strlen(path);
char *xpath = NULL;
+ uint8_t flags = content ? GET_DATA_FLAG_CONFIG : GET_DATA_FLAG_STATE;
+
+ if (content && content[0] == 'w')
+ flags |= GET_DATA_FLAG_STATE;
/* get rid of extraneous trailing slash-* or single '/' unless root */
if (plen > 2 && ((path[plen - 2] == '/' && path[plen - 1] == '*') ||
path = xpath;
}
- vty_mgmt_send_get_data_req(vty, format, path);
+ vty_mgmt_send_get_data_req(vty, format, flags, path);
if (xpath)
XFREE(MTYPE_TMP, xpath);