clicon / clixon

YANG-based toolchain including NETCONF and RESTCONF interfaces and an interactive CLI
http://www.clicon.org/
Other
206 stars 69 forks source link

does not return the default values from the configuration #484

Closed khromenokroman closed 4 months ago

khromenokroman commented 6 months ago

Hi, tell me why I can't get the configuration with the default values? I get it in the terminal, but it doesn't work through the api, although I transmit that it is necessary to output everything

in c++

cxobj *xtop = NULL;
withdefaults_type wd = WITHDEFAULTS_REPORT_ALL;
cbuf *cb;

if (xmldb_get0(h, "running", YB_NONE, NULL, "/", 1, wd, &xtop, NULL, NULL) != 1) {
        clicon_err(OE_FATAL, 0, "xmldb_get0 failed");
        return -1;
    }
cb = cbuf_new();
if (cb == NULL) {
    xml_free(xtop);
    return -1;
}
if (clixon_xml2cbuf(cb, xtop, 0, 1, nullptr, -1, 0) < 0) {
    cbuf_free(cb);
    xml_free(xtop);
    return -1;
}

output:

      <context>
         <name>sample</name>
         <vlans>
            <vlan>
               <vlan-id>100</vlan-id>
               <config>
                  <vlan-id>100</vlan-id>
                  <name>DCN</name>
                  <status>ACTIVE</status>
               </config>
            </vlan>

in terminal: clixon_cli -1 -f /etc/clixon/clixon.xml show state xml default explicit output:

   <context>
      <name>sample</name>
      <vlans>
         <vlan>
            <vlan-id>100</vlan-id>
            <config>
               <vlan-id>100</vlan-id>
               <name>DCN</name>
               <status>ACTIVE</status>
            </config>
            <state>
               <status>ACTIVE</status>
            </state>
         </vlan>

in NetConf request.xml

<?xml version="1.0" encoding="utf-8"?>
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capabilities>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
  </capabilities>
</hello>

]]>]]>

<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <get-config>
    <source>
      <running/>
    </source>
    <with-defaults xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults">report-all</with-defaults>
  </get-config>
</rpc>

]]>]]>

cat request.xml | clixon_netconf -f /etc/clixon/clixon.xml | less output

<contexts
    xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
    <context>
        <name>sample</name>
        <vlans>
            <vlan>
                <vlan-id>100</vlan-id>
                <config>
                    <vlan-id>100</vlan-id>
                    <name>DCN</name>
                    <status>ACTIVE</status>
                </config>
            </vlan>
            <vlan>
                <vlan-id>200</vlan-id>
                <config>
                    <vlan-id>200</vlan-id>
                    <name>DCN</name>
                    <status>ACTIVE</status>
                </config>
            </vlan>
            <vlan>
                <vlan-id>201</vlan-id>
                <config>
                    <vlan-id>201</vlan-id>
                    <name>DCN</name>
                    <status>ACTIVE</status>
                </config>

in programm c++ or NetConf not found block

<state>
    <status>ACTIVE</status>
</state>

if send request:

<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
   <get/>
</rpc>

cat request.xml | clixon_netconf -f /etc/clixon/clixon.xml | less

<hello
    xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
    <capabilities>
        <capability>urn:ietf:params:netconf:base:1.1</capability>
        <capability>urn:ietf:params:netconf:base:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&amp;module-set-id=0</capability>
        <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:validate:1.1</capability>
        <capability>urn:ietf:params:netconf:capability:startup:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>
        <capability>urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&amp;also-supported=report-all,trim,report-all-tagged</capability>
        <capability>urn:ietf:params:netconf:capability:notification:1.0</capability>
        <capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</capability>
        <capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>
    </capabilities>
    <session-id>15</session-id></hello>]]>]]>

as I understand it, it supports the output of everything, including default values, but for some reason it does not output

need help :)

khromenokroman commented 6 months ago

I found how to do it via NetConf in the terminal, but I still don't understand how to do it in C or C++

<?xml version="1.0" encoding="utf-8"?>
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capabilities>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
  </capabilities>
</hello>

]]>]]>

<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
  <get>
    <with-defaults xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults">report-all</with-defaults>
  </get>
</rpc>

]]>]]>

cat request.xml | clixon_netconf -f /etc/clixon/clixon.xml

<hello
  xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <capabilities>
    <capability>urn:ietf:params:netconf:base:1.1</capability>
    <capability>urn:ietf:params:netconf:base:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:yang-library:1.0?revision=2019-01-04&amp;module-set-id=0</capability>
    <capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:validate:1.1</capability>
    <capability>urn:ietf:params:netconf:capability:startup:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:xpath:1.0</capability>
    <capability>urn:ietf:params:netconf:capability:with-defaults:1.0?basic-mode=explicit&amp;also-supported=report-all,trim,report-all-tagged</capability>
    <capability>urn:ietf:params:netconf:capability:notification:1.0</capability>
    <capability>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</capability>
    <capability>urn:ietf:params:netconf:capability:confirmed-commit:1.1</capability>
  </capabilities>
  <session-id>6</session-id></hello>]]>]]>
  <rpc-reply
    xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
    <data>
      <contexts
        xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm">
        <context>
          <name>sample</name>
          <vlans>
            <vlan>
              <vlan-id>100</vlan-id>
              <config>
                <vlan-id>100</vlan-id>
                <name>DCN</name>
                <status>ACTIVE</status>
              </config>
              <state>
                <status>ACTIVE</status>
              </state>
            </vlan>
            <vlan>
              <vlan-id>200</vlan-id>
              <config>
                <vlan-id>200</vlan-id>
                <name>DCN</name>
                <status>ACTIVE</status>
              </config>
              <state>
                <status>ACTIVE</status>
              </state>
            </vlan>
            <vlan>
              <vlan-id>201</vlan-id>
              <config>
                <vlan-id>201</vlan-id>
                <name>DCN</name>
                <status>ACTIVE</status>
              </config>
              <state>
                <status>ACTIVE</status>
              </state>
            </vlan>

the default values are given by

<state>
   <status>ACTIVE</status>
</state>

so far, in c++, here is a solution, but the program stops at clicon_rpc_netconf_xml, as I understand it, it is waiting for an answer, but the answer does not come and it hangs I do not understand what needs to be done, help :)

int get_default_values(clicon_handle h) {
    int ret = 0;
    cxobj *xret = NULL;
    cxobj *xerr = NULL;
    cxobj *xreq = NULL;
    yang_stmt *yspec = NULL;

    const char *request = "<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\"1\">"
                          "<get>"
                          "<with-defaults xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\">report-all</with-defaults>"
                          "</get>"
                          "</rpc>";

   if ((yspec = clicon_dbspec_yang(h)) == NULL) {
        return -1;
    }

    if (clixon_xml_parse_string(request, YB_MODULE, yspec, &xreq, &xerr) < 0) {
        return -1;
    }

    if (clicon_rpc_netconf_xml(h, xreq, &xret, NULL) < 0) {
        return -1;
    }

    cbuf *cb = cbuf_new();
    if (cb == NULL) {
        return -1;
    }

    if (clixon_xml2cbuf(cb, xret, 0, 1, nullptr, -1, 0) < 0) {
        return -1;
    }

    fprintf(stdout, "%s\n", cbuf_get(cb));
    cbuf_free(cb);

    if (xreq != NULL) xml_free(xreq);
    if (xret != NULL) xml_free(xret);
    if (xerr != NULL) xml_free(xerr);
    return ret;

}
khromenokroman commented 6 months ago

I rewrote the code using other functions, the result is the same when sending a clicon_rpc1 request, the program is blocked and waiting for a response, how to understand what the problem is, I am not forming the request correctly or what is with the logic of the program

int my_netconf_get_report_all(clicon_handle h) {
    int ret;
    int sock = -1;
    int eof;
    cbuf *msg_in;
    cbuf *msg_out;
    char *sockpath = nullptr;
    char *str_reply = nullptr;

    cxobj *rpc = xml_new((char*)"get", nullptr, CX_ELMNT);
    if (!rpc)
        return -1;

    cxobj *filter = xml_new((char*)"filter", rpc, CX_ELMNT);
    if (!filter) {
        xml_free(rpc);
        return -1;
    }

    cxobj *report_all = xml_new((char*)"report-all", filter, CX_ELMNT);
    if (!report_all) {
        xml_free(rpc);
        return -1;
    }

    msg_in = cbuf_new();
    if (clixon_xml2cbuf(msg_in, rpc, 0, 0, NULL, 0, 0) < 0) {
        xml_free(rpc);
        return -1;
    }
    xml_free(rpc);

    sockpath = clicon_sock_str(h);
    if (clicon_rpc_connect_unix(h, sockpath, &sock) < 0)
        return -1;

    msg_out = cbuf_new();
    ret = clicon_rpc1(sock, "my request", msg_in, msg_out, &eof);
    if (ret < 0) {
        cbuf_free(msg_in);
        cbuf_free(msg_out);
        return -1;
    }

    str_reply = cbuf_get(msg_out);
    printf("Reply: %s\n", str_reply);

    cbuf_free(msg_in);
    cbuf_free(msg_out);
    close(sock);
    return 0;
}
olofhagsand commented 5 months ago
if (xmldb_get0(h, "running", YB_NONE, NULL, "/", 1, wd, &xtop, NULL, NULL) != 1) {
        clicon_err(OE_FATAL, 0, "xmldb_get0 failed");
        return -1;
    }

gets the configured state with wd set as with-default parameter. But as I understand, "status" is a non-config (i.e., state) field? State data is retrieved via the get_statedata() API. I see this is a static function and therefore not available directly in the API, only indirectly via the from_client_get() function. Therefore you get it via protocol action which invokes from_client_get() . It seems like you should be able to get the state in the API. Incidentally I am refactoring this code in branch https://github.com/clicon/clixon/tree/optimize-get and I can take this into account. However this is a mid-time project (not short/long) If you want a quick fix you may be able to look in the withdefaults code at the end of get_statedata() here: https://github.com/clicon/clixon/blob/391179730e5e9a25aae0aa2fca61ab6c08995a30/apps/backend/backend_get.c#L322

khromenokroman commented 5 months ago
from_client_get(clixon_handle h,
                cxobj        *xe,
                cbuf         *cbret,
                void         *arg,
                void         *regarg)
{
    netconf_content      content = CONTENT_ALL;
    char                *attr;
    struct client_entry *ce = (struct client_entry *)arg;

    /* Clixon extensions: content */
    if ((attr = xml_find_value(xe, "content")) != NULL)
        content = netconf_content_str2int(attr);
    return get_common(h, ce, xe, content, "running", cbret);
}

Thank you very much, I looked, but as I understand it, you can only get a "running" DB, but what if I need to get both "running" and "candidate"

olofhagsand commented 5 months ago

Non-config data is not defined for candidate as far as I remember from RFC6241

olofhagsand commented 5 months ago

Is this resolved? Do you have further questions?

khromenokroman commented 5 months ago

Is this resolved? Do you have further questions?

Everything is working, thank you very much :))