-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Missing new line and space when push device config via service
1. Overview
A formatting issue in Clixon causes malformed rpl-prefix-set values when a prefix-set contains multiple prefixes. The generated configuration omits required separators before end-set, resulting in invalid routing-policy syntax being sent to Cisco XR devices.
nobody@dc1528a56793[/]# commit Dec 18 06:26:31.071044: transaction_notification_handler: pid: 1222 Transaction 21 failed in xr: Device xr in state PUSH-EDIT2:application operation-failed 'YANG framework' detected the 'fatal' condition 'Operation failed' : ns1:routing-policy/ns1:sets/ns1:prefix-sets/ns1:prefix-set[set-name = 'prefixset']/ns1:rpl-prefix-set Failed
2. Step To Reproduce
Environment Setup
-
Set up a Cisco XR device (recommended over a VM).
-
Configure a prefix-set on the XR device that contains more than one prefix (at least two IP prefixes).
-
Set up the Clixon controller and ensure it is successfully connected to the XR device (NETCONF session established and device in sync).
Reproduction Steps
-
In the Clixon controller, create a service (for example, a service that updates an interface description).
-
Commit the service changes through the controller.
-
Observe the NETCONF edit-config payload sent to the XR device.
3. Possible Root Cause
the rpl-prefix-set string in your controller’s device config is malformed (at minimum missing a separator before end-set; XR typically expects proper spacing/newlines like the CLI form).le 24end-set (missing whitespace/newline before end-set).
Dec 18 06:26:29.265005: xml_cmp:412: vm vm eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265010: xml_cmp:412: config config eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265013: xml_cmp:412: memory memory eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265015: xml_cmp:412: admin admin eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265016: xml_cmp:412: rp rp eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265018: xml_cmp:412: lc lc eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265020: xml_cmp:412: cpu cpu eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265021: xml_cmp:412: assign assign eq:0 nr: 0 0 yi: 0 0
Dec 18 06:26:29.265242: clixon_msg_send:374: Send [xr]
#1124
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="13"><edit-config><target><candidate/></target><default-operation>merge</default-operation><config><interfaces xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-um-interface-cfg"><interface><interface-name>MgmtEth0/RP0/CPU0/0</interface-name><description nc:operation="replace">update from service 14</description></interface></interfaces><routing-policy xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-policy-repository-cfg"><sets><prefix-sets><prefix-set><set-name>prefixset</set-name><rpl-prefix-set nc:operation="replace">prefix-set prefixset 192.168.0.0/24 le 24, 192.168.1.0/24 le 24end-set</rpl-prefix-set></prefix-set></prefix-sets></sets></routing-policy><routing-policy xmlns="http://cisco.com/ns/yang/Cisco-IOS-XR-um-route-policy-cfg"><sets><prefix-sets><prefix-set><set-name>prefixset</set-name><rpl-prefix-set nc:operation="replace">prefix-set prefixset 192.168.0.0/24 le 24, 192.168.1.0/24 le 24end-set</rpl-prefix-set></prefix-set></prefix-sets></sets></routing-policy></config></edit-config></rpc>
##
4. Propose Solution / Fix
--- a/clixon/parser.py
+++ b/clixon/parser.py
@@ -81,14 +81,9 @@ class Handler(handler.ContentHandler):
- if cdata.startswith("\n"):
- cdata = cdata[1:]
-
- if cdata.endswith("\n"):
- cdata = cdata[:-1]
-
- if cdata.isspace() and self.last_cdata == "":
- return
+ if cdata.isspace():
+ if self.elements and self.elements[-1].cdata == "":
+ return`
--- a/tests/test_parse.py
+++ b/tests/test_parse.py
@@ -222,3 +222,21 @@ def test_delete_create():
root.foo.bar.delete()
assert root.dumps() == """<foo/>"""
+
+
+def test_preserve_newline_in_split_characters_chunks():
+ """
+ Expat/SAX may split element character data into multiple chunks.
+ Ensure we do not strip a leading newline from a non-whitespace chunk.
+ """
+
+ from clixon.parser import Handler
+
+ h = Handler()
+ h.startElement("rpl-prefix-set", {})
+ h.characters("prefix-set prefixset 192.168.1.0/24 le 24")
+ h.characters("\nend-set")
+ h.endElement("rpl-prefix-set")
+
+ elem = h.root.get_elements()[0]
+ assert elem.cdata == "prefix-set prefixset 192.168.1.0/24 le 24\nend-set"