Repository: juniper/py-junos-eznc
Issue: Utils.sw.rollback() not catching failure

The sw.rollback() function does not catch the following response from Junos
`<output>WARNING: Cannot rollback, /packages/junos.old is not valid</output>`

Also unit-test for rollback currently not functioning properly.


Changed files:
lib/jnpr/junos/transport/tty_netconf.py, lib/jnpr/junos/console.py, lib/jnpr/junos/transport/tty.py, lib/jnpr/junos/device.py

diff --git a/lib/jnpr/junos/console.py b/lib/jnpr/junos/console.py
index 8ce6209c..e3241ff8 100644
--- a/lib/jnpr/junos/console.py
+++ b/lib/jnpr/junos/console.py
@@ -122,6 +122,7 @@ class Console(_Connection):
         self._attempts = kvargs.get('attempts', 10)
         self._gather_facts = kvargs.get('gather_facts', False)
         self._fact_style = kvargs.get('fact_style', 'new')
+        self._huge_tree = kvargs.get('huge_tree', False)
         if self._fact_style != 'new':
             warnings.warn('fact-style %s will be removed in '
                           'a future release.' %
@@ -275,7 +276,8 @@ class Console(_Connection):
             if isinstance(rpc_cmd_e, etree._Element) else rpc_cmd_e
         reply = self._tty.nc.rpc(rpc_cmd)
         rpc_rsp_e = NCElement(reply,
-                              self.junos_dev_handler.transform_reply()
+                              self.junos_dev_handler.transform_reply(),
+                              self._huge_tree
                               )._NCElement__doc
         return rpc_rsp_e
 
@@ -290,6 +292,7 @@ class Console(_Connection):
         tty_args['timeout'] = float(self._timeout)
         tty_args['attempts'] = int(self._attempts)
         tty_args['baud'] = self._baud
+        tty_args['huge_tree'] = self._huge_tree
         if self._mode and self._mode.upper() == 'TELNET':
             tty_args['host'] = self._hostname
             tty_args['port'] = self._port
diff --git a/lib/jnpr/junos/device.py b/lib/jnpr/junos/device.py
index c430b938..5c17708b 100644
--- a/lib/jnpr/junos/device.py
+++ b/lib/jnpr/junos/device.py
@@ -1145,6 +1145,9 @@ class Device(_Connection):
             default is ``False`` to use DOM.
             Select ``True`` to use SAX (if SAX input is provided).
 
+        :param bool huge_tree:
+            *OPTIONAL* parse XML with very deep trees and long text content.
+            default is ``False``.
         """
 
         # ----------------------------------------
@@ -1160,6 +1163,7 @@ class Device(_Connection):
         self._auto_probe = kvargs.get('auto_probe', self.__class__.auto_probe)
         self._fact_style = kvargs.get('fact_style', 'new')
         self._use_filter = kvargs.get('use_filter', False)
+        self._huge_tree = kvargs.get('huge_tree', False)
         if self._fact_style != 'new':
             warnings.warn('fact-style %s will be removed in a future '
                           'release.' %
@@ -1339,6 +1343,8 @@ class Device(_Connection):
             cnx_err._orig = err
             raise cnx_err
 
+        if self._huge_tree:
+            self._conn.huge_tree = True
         self.connected = True
 
         self._nc_transform = self.transform
diff --git a/lib/jnpr/junos/transport/tty.py b/lib/jnpr/junos/transport/tty.py
index 82c8bf60..c7f3b758 100644
--- a/lib/jnpr/junos/transport/tty.py
+++ b/lib/jnpr/junos/transport/tty.py
@@ -82,6 +82,7 @@ class Terminal(object):
         self.cs_passwd = kvargs.get('cs_passwd')
         self.login_attempts = kvargs.get('attempts') or self.LOGIN_RETRY
         self.console_has_banner = kvargs.get('console_has_banner') or False
+        self._huge_tree = kvargs.get('huge_tree', False)
 
         # misc setup
         self.nc = tty_netconf(self)
diff --git a/lib/jnpr/junos/transport/tty_netconf.py b/lib/jnpr/junos/transport/tty_netconf.py
index d7e4f31b..dcbb9606 100644
--- a/lib/jnpr/junos/transport/tty_netconf.py
+++ b/lib/jnpr/junos/transport/tty_netconf.py
@@ -119,7 +119,7 @@ class tty_netconf(object):
 
         rsp = self._receive()
         rsp = rsp.decode('utf-8') if isinstance(rsp, bytes) else rsp
-        reply = RPCReply(rsp)
+        reply = RPCReply(rsp, huge_tree=self._tty._huge_tree)
         errors = reply.errors
         if len(errors) > 1:
             raise RPCError(to_ele(reply._raw), errs=errors)
@@ -161,8 +161,10 @@ class tty_netconf(object):
             rxbuf = [i.strip() for i in rxbuf if i.strip() != PY6.EMPTY_STR]
             rcvd_data = PY6.NEW_LINE.join(rxbuf)
             logger.debug('Received: \\n%s' % rcvd_data)
+            parser = etree.XMLParser(remove_blank_text=True,
+                                     huge_tree=self._tty._huge_tree)
             try:
-                etree.XML(rcvd_data)
+                etree.XML(rcvd_data, parser)
             except XMLSyntaxError:
                 if _NETCONF_EOM in rcvd_data:
                     rcvd_data = rcvd_data[:rcvd_data.index(_NETCONF_EOM)]