cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1302
Views
0
Helpful
6
Replies

Ydk-gen XmlSubtree Encode use C++ example

AnkitGupta29279
Level 1
Level 1

Hi,

 

I am using the Ydk-gen's XmlSubtreeCodec Api's.

 

I am able to generate Ydk-gen C++ Object from Xml data using decode API.

Now I want to convert Ydk-gen C++ Object to Xml string using encode(). Somehow I am unable to do that, as from the documentation provided I am unable to understand the "path::RootSchemaNode" parameter being passed to the API.

 

std::string XmlSubtreeCodec::encode(Entity & entity, path::RootSchemaNode & root_schema)


Please help me in understanding and using this API. Thanks in Advance!

P.S. I have tried passing the object reference directly but it fails(probably due to some mistake).

 

1 Accepted Solution

Accepted Solutions

Hi Ankit

Here is an example of how XmlSubrtreeCodec could be used without connecting to device. You need though generate your model package in order to use Model API.

#include <iostream>
#include <spdlog/spdlog.h>

#include "ydk/codec_provider.hpp"
#include "ydk/xml_subtree_codec.hpp"

#include "ydk_openconfig/openconfig_bgp.hpp"
#include "ydk_openconfig/openconfig_bgp_types.hpp"

using namespace ydk;
using namespace openconfig;
using namespace std;

void config_bgp(openconfig_bgp::Bgp & bgp)
{
    bgp.global->config->as = 65172;
    bgp.global->config->router_id = "1.2.3.4";

    auto neighbor = make_shared<openconfig_bgp::Bgp::Neighbors::Neighbor>();
    neighbor->neighbor_address = "6.7.8.9";
    neighbor->config->neighbor_address = "6.7.8.9";
    neighbor->config->peer_as = 65001;
    neighbor->config->local_as = 65001;
    neighbor->config->peer_group = "IBGP";
    bgp.neighbors->neighbor.append(neighbor);
}

void aug_cap_func() {
  // do nothing
}

int main(int argc, char* argv[])
{
    auto logger = spdlog::stdout_color_mt("ydk");
    logger->set_level(spdlog::level::debug);

    CodecServiceProvider cp{EncodingFormat::XML};
    cp.initialize("my_openconfig", "/Users/ygorelik/ydk-gen/yang/openconfig-nis", aug_cap_func);
    auto & root = cp.get_root_schema_for_bundle("my_openconfig");

    try {
        auto bgp = openconfig_bgp::Bgp{};
        config_bgp(bgp);

        XmlSubtreeCodec xml_codec{};
        auto xml_bgp_config = xml_codec.encode(bgp, root);
        cout << xml_bgp_config << endl;
    }
    catch(YError & e) {
        cerr << "Error details: " << e << endl;
        return 1;
    }
    return 0;
}

The program produces the following output:

<bgp xmlns="http://openconfig.net/yang/bgp">
  <global>
    <config>
      <as>65172</as>
      <router-id>1.2.3.4</router-id>
    </config>
  </global>
  <neighbors>
    <neighbor>
      <neighbor-address>6.7.8.9</neighbor-address>
      <config>
        <peer-group>IBGP</peer-group>
        <neighbor-address>6.7.8.9</neighbor-address>
        <peer-as>65001</peer-as>
        <local-as>65001</local-as>
      </config>
    </neighbor>
  </neighbors>
</bgp>

For your information I have attached CMakeLists.txt file.

There is also another, probably more effective, way of initializing schema and getting root schema node:

auto repo = path::Repository{"/Users/ygorelik/ydk-gen/yang/openconfig-nis"};
std::vector<path::Capability> empty_caps;
auto root = repo.create_root_schema(empty_caps); // here root is shared_ptr<RootSchemaNode>
...
        XmlSubtreeCodec xml_codec{};
        auto xml_bgp_config = xml_codec.encode(bgp, *root);

I suggest to try the last method first and explore, if it is working for you. 

Yan Gorelik
YDK Solutions

View solution in original post

6 Replies 6

yangorelik
Spotlight
Spotlight

Hello Ankit

Here is documentation explaining what the RootSchemaNode is. In short it is a root of all YANG model nodes that you are working on. It is built internally when you create service provider, and there is API to get it and provide to the codec. For example you have instantiated NetconfServiceProvider. Then:

provider = NetconfServiceProvider(address, port, username, password)
root_schema_node = provider.get_session().get_root_schema()

If you are not connecting to a device, then you need to use CodecServiceProvider and initialize it on some repository (directory) of YANG models. In the example below the bundle package is used to define the repository:

from ydk.models import cisco_ios_xe as xe
from ydk.models.cisco_ios_xe import Cisco_IOS_XE_native as xe_native
from ydk.providers import CodecServiceProvider
from ydk.entity_utils import XmlSubtreeCodec

provider = CodecServiceProvider(type="xml")
provider.initialize('cisco_ios_xe', xe.__path__[0] + '/_yang')
root_schema = provider.get_root_schema('cisco_ios_xe')

xml_codec = XmlSubtreeCodec()

# create YDK native model object for IOS XE model generation
native = xe_native.Native()
# build object native ...

# Encode object as XML string
xml_output = xml_codec.encode(native, root_schema)
print(xml_output)
# ...

# Decode XML string to YDK object (need provide top level entity of expected object)
native_entity = xml_codec.decode(xml_output, xe_native.Native())
Yan Gorelik
YDK Solutions

Hi Yangorelik,

Thanks for the inputs. They were really helpful for me to proceed.
However on using the similar schema I am facing below errors.

terminate called after throwing an instance of 'ydk::YIllegalStateError'
what(): YIllegalStateError: Could not create repository in: /mnt/data0/angupta/cpp/gnbdu-bundle/ydk/models
Aborted (core dumped)
Could you please help with this. The error is coming as ly_ctx_new() is returning NULL, even though this is a valid directory.
P.S. I am using the C++ codec APIs.

Regards,
Ankit

I think something wrong with pointers. Could you attach your program to the post. I will then try to reproduce the issue.

Yan Gorelik
YDK Solutions

Hi Yan,

Below is the attached test code which I am trying for encode.
Here I have generated bundle for my own yang files and am passing xml string as an argument to decode and then the decoded object to encode(only for functionality test purpose).




#include <string.h>
#include <stdio.h>
#include <iostream>
#include <memory>

/* include generated file */
#include "xml_subtree_codec.hpp"
#include "ydk_gnbdu/y_3gpp_common_managed_element.hpp"
#include "generated_entity_lookup.hpp"

#include <unordered_set>
#include "entity_lookup.hpp"
#include <iterator>
#include <map>
#include "path_api.hpp"
#include "codec_provider.hpp"

extern void gnbdu::gnbdu_augment_lookup_tables();


int main()
{
// Provide the xml string to be tested, each node needs to have its namespace defined
char xmlData[8092]="<ManagedElement xmlns=\"urn:3gpp:sa5:_3gpp-common-managed-element\"><id>gNBAltiostar</id><attributes><userLabel>abcd</userLabel><priorityLabel>10</priorityLabel></attributes><GNBCUCPFunction xmlns=\"urn:3gpp:sa5:_3gpp-nr-nrm-gnbcucpfunction\"><id>gNBCUCPAltiostar</id><attributes><priorityLabel>10</priorityLabel><gNBId>10</gNBId><gNBIdLength>27</gNBIdLength><gNBCUName>gNBCUAltiostar</gNBCUName><pLMNId><mcc>289</mcc><mnc>88</mnc></pLMNId></attributes><NRCellCU xmlns=\"urn:3gpp:sa5:_3gpp-nr-nrm-nrcellcu\"><id>NRCellCUAltiostar</id><attributes><userLabel>Altiostar_userlabel</userLabel><vnfParametersList><vnfInstanceId>Altio_instance</vnfInstanceId><vnfdId>Altio_id</vnfdId><flavourId>Altio_flavour</flavourId><autoScalable>true</autoScalable></vnfParametersList><priorityLabel>1</priorityLabel><cellLocalId>2</cellLocalId><pLMNIdList><mcc>234</mcc><mnc>56</mnc></pLMNIdList><pLMNIdList><mcc>288</mcc><mnc>99</mnc></pLMNIdList><pLMNIdList><mcc>999</mcc><mnc>999</mnc></pLMNIdList><sNSSAIList>1</sNSSAIList><rRMPolicyType>1</rRMPolicyType><rRMPolicy>split_radio_resources</rRMPolicy><rRMPolicyRatio1List><groupId>1</groupId><sNSSAIList>1</sNSSAIList><rRRMPolicyRatio>1</rRRMPolicyRatio></rRMPolicyRatio1List><rRMPolicyRatio2><groupId>1</groupId><sNSSAIList>1</sNSSAIList><quotaType>STRICT</quotaType><rRMPolicyMaxRatio>1</rRMPolicyMaxRatio><rRMPolicyMarginMaxRatio>2</rRMPolicyMarginMaxRatio><rRMPolicyMinRatio>1</rRMPolicyMinRatio><rRMPolicyMarginMinRatio>1</rRMPolicyMarginMinRatio></rRMPolicyRatio2><rrmConfig xmlns=\"urn:altiostar:_altiostar-nr-nrm-nrcellcu\"></rrmConfig><macCellGroupConfig xmlns=\"urn:altiostar:_altiostar-nr-nrm-nrcellcu\"><drxConfig><milliSeconds>on_ms1</milliSeconds><drxInactivityTimer>ms2</drxInactivityTimer><harqRTTTimerDl>1</harqRTTTimerDl><harqRTTTimerUl>2</harqRTTTimerUl><drxRetransmissionDL>sl2</drxRetransmissionDL><drxRetransmissionUL>sl1</drxRetransmissionUL></drxConfig></macCellGroupConfig></attributes></NRCellCU></GNBCUCPFunction><GNBDUFunction xmlns=\"urn:3gpp:sa5:_3gpp-nr-nrm-gnbdufunction\"><id>gNBDUAltiostar</id><attributes><priorityLabel>27</priorityLabel><gNBId>245</gNBId><gNBIdLength>22</gNBIdLength><gNBDUId>10</gNBDUId><gNBDUName>Vijay123</gNBDUName></attributes></GNBDUFunction></ManagedElement>";


std::cout<<"=====================Printing configurations in xml format=======================\n";
std::cout<<xmlData<<std::endl;
std::shared_ptr<gnbdu::y_3gpp_common_managed_element::ManagedElement> entity (new gnbdu::y_3gpp_common_managed_element::ManagedElement);
entity->yang_name = "ManagedElement";

ydk::XmlSubtreeCodec XmlSubtreeCodec_t;
gnbdu::gnbdu_augment_lookup_tables();

XmlSubtreeCodec_t.decode(xmlData,entity);
std::cout <<"After decode";


std::cout <<"name "<<entity->id.name<<"value"<<entity->id.value<<std::endl;



ydk::CodecServiceProvider cs(ydk::EncodingFormat::XML);
cs.initialize("gnbdu","/mnt/data0/angupta/ydk_gen/cpp/gnbdu-bundle/ydk/models/gnbdu",entity->get_augment_capabilities_function());

std::cout <<"After encode";



return 0;

}

Hi Ankit

Here is an example of how XmlSubrtreeCodec could be used without connecting to device. You need though generate your model package in order to use Model API.

#include <iostream>
#include <spdlog/spdlog.h>

#include "ydk/codec_provider.hpp"
#include "ydk/xml_subtree_codec.hpp"

#include "ydk_openconfig/openconfig_bgp.hpp"
#include "ydk_openconfig/openconfig_bgp_types.hpp"

using namespace ydk;
using namespace openconfig;
using namespace std;

void config_bgp(openconfig_bgp::Bgp & bgp)
{
    bgp.global->config->as = 65172;
    bgp.global->config->router_id = "1.2.3.4";

    auto neighbor = make_shared<openconfig_bgp::Bgp::Neighbors::Neighbor>();
    neighbor->neighbor_address = "6.7.8.9";
    neighbor->config->neighbor_address = "6.7.8.9";
    neighbor->config->peer_as = 65001;
    neighbor->config->local_as = 65001;
    neighbor->config->peer_group = "IBGP";
    bgp.neighbors->neighbor.append(neighbor);
}

void aug_cap_func() {
  // do nothing
}

int main(int argc, char* argv[])
{
    auto logger = spdlog::stdout_color_mt("ydk");
    logger->set_level(spdlog::level::debug);

    CodecServiceProvider cp{EncodingFormat::XML};
    cp.initialize("my_openconfig", "/Users/ygorelik/ydk-gen/yang/openconfig-nis", aug_cap_func);
    auto & root = cp.get_root_schema_for_bundle("my_openconfig");

    try {
        auto bgp = openconfig_bgp::Bgp{};
        config_bgp(bgp);

        XmlSubtreeCodec xml_codec{};
        auto xml_bgp_config = xml_codec.encode(bgp, root);
        cout << xml_bgp_config << endl;
    }
    catch(YError & e) {
        cerr << "Error details: " << e << endl;
        return 1;
    }
    return 0;
}

The program produces the following output:

<bgp xmlns="http://openconfig.net/yang/bgp">
  <global>
    <config>
      <as>65172</as>
      <router-id>1.2.3.4</router-id>
    </config>
  </global>
  <neighbors>
    <neighbor>
      <neighbor-address>6.7.8.9</neighbor-address>
      <config>
        <peer-group>IBGP</peer-group>
        <neighbor-address>6.7.8.9</neighbor-address>
        <peer-as>65001</peer-as>
        <local-as>65001</local-as>
      </config>
    </neighbor>
  </neighbors>
</bgp>

For your information I have attached CMakeLists.txt file.

There is also another, probably more effective, way of initializing schema and getting root schema node:

auto repo = path::Repository{"/Users/ygorelik/ydk-gen/yang/openconfig-nis"};
std::vector<path::Capability> empty_caps;
auto root = repo.create_root_schema(empty_caps); // here root is shared_ptr<RootSchemaNode>
...
        XmlSubtreeCodec xml_codec{};
        auto xml_bgp_config = xml_codec.encode(bgp, *root);

I suggest to try the last method first and explore, if it is working for you. 

Yan Gorelik
YDK Solutions

Thanks a lot Yan for the detailed explanation and sample code.