Skip to content

Commit

Permalink
Resolved CiscoDevNet#799
Browse files Browse the repository at this point in the history
  • Loading branch information
ygorelik committed Apr 2, 2019
1 parent 1317bdf commit 634aed4
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 2019-05-15 version 0.8.3

#### Resolved GitHub issues
* YDK netconf read fails when <data> tag has namespace prefix ([#799](https://github.com/CiscoDevNet/ydk-gen/issues/799))
* YDK return value of YANG action missing some attributes ([#871](https://github.com/CiscoDevNet/ydk-gen/issues/871))
* Duplicate code in generated cisco-ios-xe Go bundle ([#891](https://github.com/CiscoDevNet/ydk-gen/issues/891))
* Memory leaks in YDK C++ core ([#899](https://github.com/CiscoDevNet/ydk-gen/issues/899))
Expand Down
1 change: 1 addition & 0 deletions sdk/cpp/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 2019-05-15 version 0.8.3

#### Resolved GitHub issues
* YDK netconf read fails when <data> tag has namespace prefix ([#799](https://github.com/CiscoDevNet/ydk-gen/issues/799))
* YDK return value of YANG action missing some attributes ([#871](https://github.com/CiscoDevNet/ydk-gen/issues/871))
* Duplicate code in generated cisco-ios-xe Go bundle ([#891](https://github.com/CiscoDevNet/ydk-gen/issues/891))
* Memory leaks in YDK C++ core ([#899](https://github.com/CiscoDevNet/ydk-gen/issues/899))
Expand Down
34 changes: 16 additions & 18 deletions sdk/cpp/core/src/netconf_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ const char* CANDIDATE = "urn:ietf:params:netconf:capability:candidate:1.0";
const string PROTOCOL_SSH = "ssh";
const string PROTOCOL_TCP = "tcp";

string get_netconf_output(const string & reply);

static bool is_netconf_get_rpc(path::Rpc & rpc);
static shared_ptr<path::DataNode> netconf_output_to_datanode(const string & data, path::RootSchemaNode & root_schema);
static string get_netconf_output(const string & reply);
static string extract_rpc_output(const string & reply);
static string extract_rpc_data(const string & reply, const string & start_tag, const string & end_tag, bool is_first_tag=false);

NetconfSession::NetconfSession(path::Repository & repo,
const string& address,
Expand Down Expand Up @@ -579,30 +581,26 @@ static bool is_netconf_get_rpc(path::Rpc & rpc)
or rpc.get_schema_node().get_path() == "/ietf-netconf:get-config");
}

static std::string get_netconf_output(const string & reply)
std::string get_netconf_output(const string & reply)
{
auto empty_data = reply.find("<data/>");
if(empty_data != string::npos)
if (reply.find("<data/>") != string::npos || reply.find("<nc:data/>") != string::npos)
{
YLOG_INFO( "Found empty data tag");
YLOG_INFO( "Found empty data tag, meaning requested data are not found on Netconf server");
return {};
}

auto data_start = reply.find("<data>");
if(data_start == string::npos)
{
YLOG_ERROR( "Can't find data tag in reply sent by device {}", reply);
throw(YServiceProviderError{reply});
string rpc_output = extract_rpc_data(reply, "<data>", "</data>");
if (rpc_output.length() == reply.length()) {
rpc_output = extract_rpc_data(reply, "<nc:data>", "</nc:data>");
}
data_start += sizeof("<data>") - 1;
auto data_end = reply.rfind("</data>");
if(data_end == string::npos)

if (rpc_output.length() == reply.length())
{
YLOG_ERROR( "No end data tag found in reply sent by device {}", reply);
throw(YError{"No end data tag found"});
YLOG_ERROR( "Cannot find 'data' tag in RPC from device\n{}", reply);
throw(YServiceProviderError{reply});
}

return reply.substr(data_start, data_end-data_start);
return rpc_output;
}

static shared_ptr<path::DataNode> netconf_output_to_datanode(const string & data, path::RootSchemaNode & root_schema)
Expand All @@ -618,11 +616,11 @@ static shared_ptr<path::DataNode> netconf_output_to_datanode(const string & data
}

static string
extract_rpc_data(const string & reply, const string & start_tag, const string & end_tag, bool first_tag=false)
extract_rpc_data(const string & reply, const string & start_tag, const string & end_tag, bool is_first)
{
auto data_start = reply.find(start_tag);
auto data_end = reply.rfind(end_tag);
if (data_start == string::npos || data_end == string::npos || (first_tag && data_start > 0)) {
if (data_start == string::npos || data_end == string::npos || (is_first && data_start > 0)) {
return reply;
}
if (start_tag.find("<") == 0 && start_tag.find("<!") != 0) {
Expand Down
38 changes: 38 additions & 0 deletions sdk/cpp/core/tests/test_codec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,41 @@ TEST_CASE("value_error")

CHECK_NOTHROW(s.decode(schema, value_error_json, EncodingFormat::JSON));
}

namespace ydk {
namespace path {
std::string get_netconf_output(const string & reply);
}
}

TEST_CASE( "decode_rpc_with_nc_prefix" )
{
auto rpc_reply = R"(
<nc:rpc-reply xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/15.1X49/junos" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
<nc:data>
<interfaces xmlns="http://openconfig.net/yang/interfaces">
<interface>
<name>GigabitEthernet0/0/0/2</name>
<config>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<name>GigabitEthernet0/0/0/2</name>
</config>
</interface>
</interfaces>
</nc:data>
</nc:rpc-reply>
)";
auto reply_xml = ydk::path::get_netconf_output(rpc_reply);
REQUIRE(!reply_xml.empty());

auto rpc_reply_extracted = R"(<interfaces xmlns="http://openconfig.net/yang/interfaces">
<interface>
<name>GigabitEthernet0/0/0/2</name>
<config>
<type xmlns:ianaift="urn:ietf:params:xml:ns:yang:iana-if-type">ianaift:ethernetCsmacd</type>
<name>GigabitEthernet0/0/0/2</name>
</config>
</interface>
</interfaces>)";
REQUIRE(reply_xml == rpc_reply_extracted);
}
1 change: 1 addition & 0 deletions sdk/go/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 2019-05-15 version 0.8.3

#### Resolved GitHub issues
* YDK netconf read fails when <data> tag has namespace prefix ([#799](https://github.com/CiscoDevNet/ydk-gen/issues/799))
* YDK return value of YANG action missing some attributes ([#871](https://github.com/CiscoDevNet/ydk-gen/issues/871))
* Duplicate code in generated cisco-ios-xe Go bundle ([#891](https://github.com/CiscoDevNet/ydk-gen/issues/891))

Expand Down
1 change: 1 addition & 0 deletions sdk/python/CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
### 2019-05-15 version 0.8.3

#### Resolved GitHub issues
* YDK netconf read fails when <data> tag has namespace prefix ([#799](https://github.com/CiscoDevNet/ydk-gen/issues/799))
* YDK return value of YANG action missing some attributes ([#871](https://github.com/CiscoDevNet/ydk-gen/issues/871))
* Duplicate code in generated cisco-ios-xe Go bundle ([#891](https://github.com/CiscoDevNet/ydk-gen/issues/891))

Expand Down

0 comments on commit 634aed4

Please sign in to comment.