Accessing NETCONF server configuration data using Python ncclient

96 views Asked by At

I have created and initialized a custom NETCONF server using libnetconf2 and libyang within a C++ program. My intention is to access this server and pull the configuration data using ncclient in a Python program. I have been able to successfully connect to the server, but anytime I try to send an rpc <get> or <get-config> command I get the following error

Request could not be completed because the requested operation is not supported by this implementation.

I have confirmed that I loaded the default YANG modules into my context so I am at a loss of why the commands are not being recognized. I have included the relevant parts of my code, my custom XML file, and my server capabilities below.

My Python function to connect to the server.

def connect_to_netconf_server():
     host = '127.0.0.1'
     port = 830
     username = 'user'
     password = 'password'

     # Define the NETCONF filter for the <get> operation
     filter = '''
     <filter xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:ex="urn:example">
         <ex:device>
             <ex:hostname/>
             <ex:ip-address/>
         </ex:device>
     </filter>
     '''

     # Establish a NETCONF session
     with manager.connect(host=host, 
                     port=port, 
                     username=username, 
                     password=password, 
                     hostkey_verify=False, 
                     allow_agent=False, 
                     look_for_keys=False) as m:
         print("Server Capabilities:")
         for capability in m.server_capabilities:
              print(capability)
         # Perform the <get>/<get-config> operation
         try:
             running_config = m.get(filter=filter)
             print("Running Configuration:")
             print(running_config)
         except Exception as e:
             print(f"Error during <get> operation: {e}")
         try:
             print(m.get_config(source='running').data_xml)
         except Exception as e:
             print(f"Error during <get-config> operation: {e}")

My C++ code to create a new context, load default libnetconf2 modules, and load a custom YANG module.

// Initialize libyang context with required netconf yang models
if (ly_ctx_new("libnetconf2/modules", 0, &m_ctx) != 0) {
    printf("Failed to create a new libyang context.");
    lyd_free_all(tree);
    tearDown();
    return;
}

if (nc_server_init_ctx(&m_ctx) != 0) {
    printf("Failed to initialize libyang context.");
    lyd_free_all(tree);
    tearDown();
    return;
}
else {
    printf("Libyang context created and initialized.");
    if (nc_server_config_load_modules(&m_ctx) != 0) {
        printf("ERROR loading modules required for configuration of the server.");
        lyd_free_all(tree);
        tearDown();
        return;
    }
    else{
        const char *yang_module_content = 
        R"(module example 
        {
            namespace "urn:example";
            prefix "ex";
            
            container device {
                leaf hostname {
                    type string;
                }
                leaf ip-address {
                    type string;
                }
            }
        })";

        // Load your custom YANG module into the context
        struct lys_module *custom_module = NULL;
        lys_parse_mem(m_ctx, yang_module_content, LYS_IN_YANG, &custom_module);

        if (!custom_module) {
            printf("Failed to parse YANG module.");
            lyd_free_all(tree);
            tearDown();
            return;
        }
        printf("Successfully added custom yang module to server");
    }
    if (nc_server_config_setup_path(m_ctx, "network_almanac.xml") != 0) {
        printf("ERROR configuring server data.");
        lyd_free_all(tree);
        tearDown();
        return;
    }
    // configure server based on yang ssh data above
    if(nc_server_config_setup_data(tree) != 0){
        printf("ERROR configuring server with YANG data.");
        lyd_free_all(tree);
        tearDown();
        return;
    }
    // Initialize NETCONF server
    if (nc_server_init() != 0) {
        printf("ERROR occurred while initializing the server.");
        lyd_free_all(tree);
        tearDown();
        return;
    }
    else if(nc_client_init() != 0){
        printf("ERROR occurred while initializing the client.");
        lyd_free_all(tree);
        tearDown();
        return;
    }
    else {
        printf("NETCONF server and client have been initialized.");
        lyd_free_all(tree);
        m_pollSession = nc_ps_new();

        if (!m_pollSession) {
            printf("Failed to create poll session.");
            tearDown();
            return;
        }
    }
}

XML File

<ex:device xmlns:ex="urn:example">
   <ex:hostname>example-host</ex:hostname>
   <ex:ip-address>192.168.0.1</ex:ip-address>
</ex:device>

Server Capabilities

urn:ietf:params:netconf:base:1.0
urn:ietf:params:netconf:base:1.1
urn:ietf:params:netconf:capability:writable-running:1.0
urn:ietf:params:netconf:capability:candidate:1.0
urn:ietf:params:netconf:capability:confirmed-commit:1.1
urn:ietf:params:netconf:capability:rollback-on-error:1.0
urn:ietf:params:netconf:capability:validate:1.1
urn:ietf:params:netconf:capability:startup:1.0
urn:ietf:params:netconf:capability:xpath:1.0
urn:ietf:params:xml:ns:yang:ietf-yang-metadata?module=ietf-yang-metadata&revision=2016- 
08-05
urn:ietf:params:xml:ns:yang:ietf-inet-types?module=ietf-inet-types&revision=2013-07-15
urn:ietf:params:xml:ns:yang:ietf-yang-types?module=ietf-yang-types&revision=2013-07-15
urn:ietf:params:netconf:capability:yang-library:1.1?revision=2019-01-04&content-id=254
urn:ietf:params:xml:ns:netconf:base:1.0?module=ietf-netconf&revision=2013-09- 
29&features=writable-running,candidate,confirmed-commit,rollback-on- 
error,validate,startup,url,xpath
urn:ietf:params:xml:ns:yang:ietf-netconf-acm?module=ietf-netconf-acm&revision=2018-02- 
14
urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring?module=ietf-netconf- 
monitoring&revision=2010-10-04
urn:ietf:params:xml:ns:yang:ietf-x509-cert-to-name?module=ietf-x509-cert-to- 
name&revision=2014-12-10
urn:ietf:params:xml:ns:yang:iana-crypt-hash?module=iana-crypt-hash&revision=2014-04- 
04&features=crypt-hash-md5,crypt-hash-sha-256,crypt-hash-sha-512
urn:example?module=example

I am able to see that my custom module (urn:example?module=example) was successfully added to the server and from my understanding the capabilities such as urn:ietf:params:netconf:base:1.0, urn:ietf:params:netconf:base:1.1, urn:ietf:params:netconf:capability:writable-running:1.0 should allow rpc commands such as <get> and <get-config>. I have not been able to find many resources regarding this error and would really appreciate any help regarding my implementation and/or understanding of NETCONF. I have also verified the behavior is the same when connecting to the server using the libnetconf2 library from a C++ program as well.

0

There are 0 answers