Open vaibhav1713109 opened 1 year ago
I also had the same issue. Was there any progress on this?
For example, if I try to subscribe with xpath filter of /o-ran-sync:*
This is the debug from ncclient...
<?xml version="1.0" encoding="UTF-8"?>
<nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:5b4262f6-3ef5-47b7-b123-57c432cf0c10">
<ns0:create-subscription xmlns:ns0="urn:ietf:params:xml:ns:netconf:notification:1.0">
<nc:filter xmlns:o-ran-sync="urn:o-ran:sync:1.0" type="xpath" select="/o-ran-sync:*"/>
</ns0:create-subscription>
</nc:rpc>
And the same subscribe request as sent by netopeer2-cli...
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="46">
<create-subscription xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<filter type="xpath" xmlns:o-ran-sync="urn:o-ran:sync:1.0" select="/o-ran-sync:*"/>
</create-subscription>
</rpc>
Apart from slightly different order in the filter
tag and the namespace prefixes, they look the same. Yet, the one generated by ncclient gets rejected by the server.
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:5b4262f6-3ef5-47b7-b123-57c432cf0c10">
<rpc-error>
<error-type>application</error-type>
<error-tag>operation-failed</error-tag>
<error-severity>error</error-severity>
<error-message xml:lang="en">Node "filter" not found as a child of "create-subscription" node.</error-message>
</rpc-error>
</rpc-reply>
Actually, I think I see the problem now. The filter is using namespace "nc", shouldn't it be namespace "ns0" (i.e. "urn:ietf:params:xml:ns:netconf:notification:1.0")?
<nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:5b4262f6-3ef5-47b7-b123-57c432cf0c10">
<ns0:create-subscription xmlns:ns0="urn:ietf:params:xml:ns:netconf:notification:1.0">
<nc:filter xmlns:o-ran-sync="urn:o-ran:sync:1.0" type="xpath" select="/o-ran-sync:*"/>
</ns0:create-subscription>
</nc:rpc>
Actually, looking at the build_filter()
function in ncclient/utils.py you can see that the filter can be expressed in a number of ways, including directly as xml (etree) Elements. So, that's what I've done in the below code snippet to get filter working for subscriptions...
from ncclient import manager
from ncclient.xml_ import to_ele, to_xml, new_ele, new_ele_ns, new_ele_nsmap
from lxml import etree
mgr = manager.connect(host="localhost", port=5678, username="stevend")
# This is the xpath I'm using for test subscription
xpath = "/o-ran-sync:*"
# This is the namespace of the filter that we are using (in netconf.notifications)
filter_ns = "urn:ietf:params:xml:ns:netconf:notification:1.0"
# Create the filter
filter = etree.Element(f"{{{filter_ns}}}filter",
{"type": "xpath", "select": xpath},
{"o-ran-sync": "urn:o-ran:sync:1.0"})
# Printing it out to check it looks ok
print(etree.tostring(filter))
# Here goes for the subscription
result = mgr.create_subscription(filter=filter)
# It should work :-)
print(result.ok)
The output is...
b'<ns0:filter xmlns:o-ran-sync="urn:o-ran:sync:1.0" xmlns:ns0="urn:ietf:params:xml:ns:netconf:notification:1.0" type="xpath" select="/o-ran-sync:*"/>'
True
There might be a more elegant way to do it (ncclient/xml_.py has a bunch of small functions for doing this kind of thing, but I couldn't see one that worked - it was as easy just to write the etree.Element code directly).
Note, the same code could be used to generate filters for get and get-config, just replace filter_ns with "urn:ietf:params:xml:ns:netconf:base:1.0".
Hope that makes sense, and helps anyone who's seeing this problem.
Hi all,
I also ran into this issue and identified the root cause. As @sjd-xlnx correctly indicated, it seems that the XML namespace for the filter is incorrect.
According to IETF RFC5277 Section 4 (XML Schema for Event Notifications), the filter element MUST have the namespace set to exactly the following, or a syntactical equivalent of it:
xmlns='urn:ietf:params:xml:ns:netconf:notification:1.0'
However, as indicated above, the filter element that is generated has the XML namespace as follows (or at least, a syntactical equivalent as detailed by other commenters above):
xmlns='urn:ietf:params:xml:ns:netconf:base:1.0'
Here's how to reproduce. Basically, if you call this with a tuple, regardless of your chosen type (xpath
or subtree
), you'll run into this bug:
# This filter should show me alarm event notifications that relate to the resource "my-resource". Semantics of this depend on your YANG model and NETCONF server implementation.
my_filter = """<alarm-notification xmlns='urn:ietf:params:xml:ns:yang:ietf-alarms'><resource>my-resource</resource></alarm-notification>"""
with manager.connect(host=my_host_here, port=my_port_here, username=my_username_here, password=my_password_here, hostkey_verify=False) as m:
print("Now creating subscription...")
m.create_subscription(filter=('subtree', my_filter))
# RPCError will be returned by NETCONF server you are connected to. Complaint will be: "Invalid element: 'filter'" or similar.
print("Now awaiting notification...")
notif = m.take_notification()
print("Notification received! Dumping below:\n" + notif.notification_xml)
When create_subscription
is called, it can be called with a tuple like (filter_type, filter_criteria)
if the user doesn't want to define the filter element themselves.
Thankfully, create_subscription
can also be called with a raw XML, in which the user defines the filter
element themselves. So, if you need to create a subscription with a filter, just have to call it with the filter
element of the request XML passed in directly.
Example:
# This filter will show me alarm event notifications that relate to the resource "my-resource". Semantics of this depend on your YANG model and NETCONF server implementation.
my_filter = """<filter xmlns='urn:ietf:params:xml:ns:netconf:notification:1.0' type="subtree"><alarm-notification xmlns='urn:ietf:params:xml:ns:yang:ietf-alarms'><resource>my-resource</resource></alarm-notification></filter>"""
with manager.connect(host=my_host_here, port=my_port_here, username=my_username_here, password=my_password_here, hostkey_verify=False) as m:
print("Now creating subscription...")
m.create_subscription(filter=my_filter)
print("Now awaiting notification...")
notif = m.take_notification()
print("Notification received! Dumping below:\n" + notif.notification_xml)
Contributors please fix!!!! If no one does I might just have become a contributor myself and do it
Hi @einarnn
When i did create _subscription with filter ncclient throw errot of Unknown element "filter", but the same filter is working with get and get_config.