diff --git a/lib/jnpr/junos/command/__init__.py b/lib/jnpr/junos/command/__init__.py index 8bb7f787c..142fee08d 100644 --- a/lib/jnpr/junos/command/__init__.py +++ b/lib/jnpr/junos/command/__init__.py @@ -5,6 +5,8 @@ from jnpr.junos.factory.factory_loader import FactoryLoader +import yamlordereddictloader + __all__ = [] @@ -28,7 +30,7 @@ def load_module(self, fullname): as stream: try: modules = FactoryLoader().load(yaml.load(stream, - Loader=yaml.FullLoader)) + Loader=yamlordereddictloader.Loader)) except yaml.YAMLError as exc: raise ImportError("%s is not loaded" % mod) for k, v in modules.items(): diff --git a/lib/jnpr/junos/factory/state_machine.py b/lib/jnpr/junos/factory/state_machine.py index 195843699..a8db9716c 100644 --- a/lib/jnpr/junos/factory/state_machine.py +++ b/lib/jnpr/junos/factory/state_machine.py @@ -711,18 +711,15 @@ def parse_using_regex(self, event): # checking index as there can be blank line at position 0 and 2 if line.strip() == '': if index > 2: - if self.is_row_column(): - try: - if len(_regex.scanString(self._lines[self._lines.index( - line) + 1])[0]) == 0: - break - except IndexError: - break - elif self.is_regex_data(): + if self.is_row_column() or self.is_regex_data(): try: + match = [] + # check if line after new line matches condition + # There can be data set where there are new line in between. for result, start, end in _regex.scanString( - self._lines[self._lines.index( - line) + 1]): + self._lines[index + 1]): + match.extend(result) + if match: continue else: break diff --git a/tests/unit/factory/rpc-reply/show_xmchip_0_lo_stats_0.xml b/tests/unit/factory/rpc-reply/show_xmchip_0_lo_stats_0.xml new file mode 100644 index 000000000..a24417112 --- /dev/null +++ b/tests/unit/factory/rpc-reply/show_xmchip_0_lo_stats_0.xml @@ -0,0 +1,54 @@ + +LO statistics (LO block 0) +-------------------------- + +------------------------------------------------------------------------------------------------ +LU Parcel Name Counter Name Total Rate +------------------------------------------------------------------------------------------------ +0 M2L_Packet Parcels sent to LU 7272889727 1502 pps +0 M2L_Packet Parcel bytes sent to LU 146050609612 241032 bps +0 M2L_PacketHead Parcels sent to LU 27896465 6 pps +0 M2L_PacketHead Parcel bytes sent to LU 3738126310 6432 bps +0 M2L_Backpressure Parcels sent to LU 0 0 pps +0 M2L_Backpressure Parcel bytes sent to LU 0 0 bps +0 M2L_ReadDataReply Parcels sent to LU 0 0 pps +0 M2L_ReadDataReply Parcel bytes sent to LU 0 0 bps +0 M2L_WriteDataReply Parcels sent to LU 0 0 pps +0 M2L_WriteDataReply Parcel bytes sent to LU 0 0 bps +0 M2L_StatsUpdate Parcels sent to LU 3735278 0 pps +0 M2L_StatsUpdate Parcel bytes sent to LU 33617502 32 bps +0 M2L_Gauge Parcels sent to LU 0 0 pps +0 M2L_Gauge Parcel bytes sent to LU 0 0 bps +0 M2L_XMReorder_Ack Parcels sent to LU 0 0 pps +0 M2L_XMReorder_Ack Parcel bytes sent to LU 0 0 bps +0 M2L_BulkThreshold Parcels sent to LU 0 0 pps +0 M2L_BulkThreshold Parcel bytes sent to LU 0 0 bps +0 Recirc_Packet Parcels sent to LU 0 0 pps +0 Recirc_Packet Parcel bytes sent to LU 0 0 bps +0 Error parcels sent to LU 410 0 ppsa +0 Parcel drops 0 0 pps + +1 M2L_Packet Parcels sent to LU 7280959770 1510 pps +1 M2L_Packet Parcel bytes sent to LU 146203006534 242568 bps +1 M2L_PacketHead Parcels sent to LU 19826422 4 pps +1 M2L_PacketHead Parcel bytes sent to LU 2656740548 4288 bps +1 M2L_Backpressure Parcels sent to LU 0 0 pps +1 M2L_Backpressure Parcel bytes sent to LU 0 0 bps +1 M2L_ReadDataReply Parcels sent to LU 0 0 pps +1 M2L_ReadDataReply Parcel bytes sent to LU 0 0 bps +1 M2L_WriteDataReply Parcels sent to LU 0 0 pps +1 M2L_WriteDataReply Parcel bytes sent to LU 0 0 bps +1 M2L_StatsUpdate Parcels sent to LU 3734751 0 pps +1 M2L_StatsUpdate Parcel bytes sent to LU 33612759 0 bps +1 M2L_Gauge Parcels sent to LU 0 0 pps +1 M2L_Gauge Parcel bytes sent to LU 0 0 bps +1 M2L_XMReorder_Ack Parcels sent to LU 0 0 pps +1 M2L_XMReorder_Ack Parcel bytes sent to LU 0 0 bps +1 M2L_BulkThreshold Parcels sent to LU 0 0 pps +1 M2L_BulkThreshold Parcel bytes sent to LU 0 0 bps +1 Recirc_Packet Parcels sent to LU 0 0 pps +1 Recirc_Packet Parcel bytes sent to LU 0 0 bps +1 Error parcels sent to LU 90 0 pps +1 Parcel drops 0 0 pps +------------------------------------------------------------------------------------------------ + \ No newline at end of file diff --git a/tests/unit/factory/test_cmdtable.py b/tests/unit/factory/test_cmdtable.py index 31c9e657f..2de6f04ec 100644 --- a/tests/unit/factory/test_cmdtable.py +++ b/tests/unit/factory/test_cmdtable.py @@ -79,7 +79,6 @@ def test_unstructured_sysctl_oneline_op(self, mock_execute): yaml_data, Loader=yamlordereddictloader.Loader))) stats = sysctlVeriexecTable(self.dev) stats = stats.get() - print (dict(stats)) self.assertEqual(dict(stats), {'veriexec-name': 'security.mac.veriexec.state', 'veriexec-state': 'loaded active enforce'}) @@ -115,17 +114,29 @@ def test_unstructured_cmerror_multiline_header(self, mock_execute): stats = CMErrorTable(self.dev) stats = stats.get(target='fpc1') self.assertEqual(dict(stats), - {1: {'errors': 0, 'pfe': 'Yes', 'name': 'PQ3 Chip', - 'module': 1, 'callback': '0x00000000', + {1: {'errors': 0, + 'pfe': 'Yes', + 'name': 'PQ3 Chip', + 'module': 1, + 'callback': '0x00000000', 'data': '0x00000000'}, - 2: {'errors': 0, 'pfe': 'No', 'name': 'Host Loopback', - 'module': 2, 'callback': '0x00000000', + 2: {'errors': 0, + 'pfe': 'No', + 'name': 'Host Loopback', + 'module': 2, + 'callback': '0x00000000', 'data': '0x464295b0'}, - 3: {'errors': 0, 'pfe': 'No', 'name': 'CM[0]', - 'module': 3, 'callback': '0x41f550f0', + 3: {'errors': 0, + 'pfe': 'No', + 'name': 'CM[0]', + 'module': 3, + 'callback': '0x41f550f0', 'data': '0x462f767c'}, - 4: {'errors': 0, 'pfe': 'No', 'name': 'LUCHIP(0)', - 'module': 4, 'callback': '0x00000000', + 4: {'errors': 0, + 'pfe': 'No', + 'name': 'LUCHIP(0)', + 'module': 4, + 'callback': '0x00000000', 'data': '0x481b84d8'}}) self.assertEqual(repr(stats), 'CMErrorTable:1.1.1.1: 4 items') self.assertEqual(len(stats), 4) @@ -197,7 +208,8 @@ def test_request_pfe_rpc_not_avialable(self, mock_execute, mock_ss, stats = CMErrorTable(self.dev) with patch('jnpr.junos.utils.start_shell.StartShell.run') as ss_run: stats.get() - ss_run.assert_called_with('cprod -A fpc1 -c "show cmerror module brief"') + ss_run.assert_called_with( + 'cprod -A fpc1 -c "show cmerror module brief"') @patch('jnpr.junos.Device.execute') def test_get_api_params(self, mock_execute): @@ -245,8 +257,8 @@ def test_cmdview_properties(self, mock_execute): self.assertEqual(stats.VIEW.T.__class__.__name__, 'property') self.assertEqual(stats.VIEW.xml.__class__.__name__, 'property') expected = ['Host Loopback', 'CM[1]', 'CM[0]', 'LUCHIP(0)', - 'TOE-LU-0:0:0', - 'PQ3 Chip'] + 'TOE-LU-0:0:0', + 'PQ3 Chip'] expected.sort() got_keys = list(stats.keys()) got_keys.sort() @@ -269,7 +281,7 @@ def test_cmdtable_iter(self, mock_execute): yaml_data, Loader=yamlordereddictloader.Loader))) stats = FPCLinkStatTable(self.dev) stats = stats.get(target='fpc1') - self.assertEqual({k: v for k,v in stats}, + self.assertEqual({k: v for k, v in stats}, {'PPP LCP/NCP': 0, 'ISIS': 0, 'BFD': 15, 'OAM': 0, 'ETHOAM': 0, 'LACP': 0, 'LMI': 0, 'UBFD': 0, 'HDLC keepalives': 0, 'OSPF Hello': 539156, 'RSVP': @@ -296,7 +308,7 @@ def test_title_in_view(self, mock_execute): active_zones: '\((0x[a-z0-9]+)\)' """ globals().update(FactoryLoader().load(yaml.load( - yaml_data, Loader=yamlordereddictloader.Loader))) + yaml_data, Loader=yamlordereddictloader.Loader))) stats = ShowLuchipTable(self.dev) stats = stats.get(target='fpc1') self.assertEqual(dict(stats), @@ -376,7 +388,7 @@ def test_field_eval(self, mock_execute): globals().update(FactoryLoader().load(yaml.load( yaml_data, Loader=yamlordereddictloader.Loader))) stats = XMChipStatsTable(self.dev) - stats = stats.get(target='fpc1', args = {'instance': 0}) + stats = stats.get(target='fpc1', args={'instance': 0}) self.assertEqual(dict(stats), {'pct_wi_1': 0, 'pct_wi_0': 0, 'total_pct': 0}) @@ -466,7 +478,7 @@ def test_unstructured_ttpstatistics(self, mock_execute): - High - Low view: _FPCTTPQueueSizesView - + _FPCTTPQueueSizesView: fields: high: High @@ -494,7 +506,7 @@ def test_unstructured_ttpstatistics(self, mock_execute): {'TTPQueueSizes': {'High': '0 (max is 4473)', 'Low': '0 (max is 2236)'}, 'TTPQueueSizes2': {'High': '0 (max is 4473)', - 'Low': '0 (max is 2236)'}, + 'Low': '0 (max is 2236)'}, 'TTPReceiveStatistics': {'Coalesce': {'control': 0, 'discard': 0, 'high': 0, @@ -600,7 +612,7 @@ def test_unstructured_icmpstats_nested(self, mock_execute): discards: _ICMPDiscardsTable errors: _ICMPErrorsTable rate: _ICMPRateTable - + _ICMPStatisticsTable: title: ICMP Statistics key: name @@ -610,7 +622,7 @@ def test_unstructured_icmpstats_nested(self, mock_execute): regex: value: numbers name: words - + _ICMPDiscardsTable: title: ICMP Discards key: name @@ -1738,7 +1750,7 @@ def test_table_eval_with_filters(self, mock_execute): - state """ globals().update(FactoryLoader().load(yaml.load( - yaml_data, Loader=yamlordereddictloader.Loader))) + yaml_data, Loader=yamlordereddictloader.Loader))) stats = FPCThreads(self.dev) stats = stats.get() self.assertEqual(dict(stats), @@ -1927,6 +1939,40 @@ def test_table_eval_with_filters(self, mock_execute): u'state': u'asleep'}} ) + @patch('jnpr.junos.Device.execute') + def test_new_line_in_data(self, mock_execute): + mock_execute.side_effect = self._mock_manager + yaml_data = """ +--- +CChipLoStatsTable: + command: show xmchip {{ chip_instance }} lo stats 0 + target: fpc4 + args: + chip_instance: 0 + title: 'LU Parcel Name Counter Name' + key: + - index + - parcel + - counter + eval: + cchip-lookup-out-errors: > + sum([v['total'] for k,v in {{ data }}.items() if v['parcel']=='Error']) + view: CChipLoStatsView + +CChipLoStatsView: + regex: + index: '^\d+' + parcel: '\w*(?=_)?\w*' + counter: '(\w+(\s\w+)+)' + total: '\d+' + rate: '\d+ pps' +""" + globals().update(FactoryLoader().load(yaml.load( + yaml_data, Loader=yamlordereddictloader.Loader))) + stats = CChipLoStatsTable(self.dev) + stats = stats.get(target='fpc0') + self.assertEqual(stats['cchip-lookup-out-errors'], 500) + def _read_file(self, fname): from ncclient.xml_ import NCElement