Repository: juniper/py-junos-eznc
Issue: Facts gathering fails on an EX8208 in standalone mode fails

The following traceback is raised on an EX8208, operating standalone mode, running 12.3R9 during facts gathering:

```
Traceback (most recent call last):
  File "2.py", line 9, in <module>
    dev.open ()
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/device.py", line 494, in open
    self.facts_refresh()
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/device.py", line 758, in facts_refresh
    gather(self, self._facts)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/facts/swver.py", line 103, in facts_software_version
    x_swver = _get_swver(junos, facts)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/facts/swver.py", line 83, in _get_swver
    return dev.rpc.cli("show version all-members", format='xml')
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/rpcmeta.py", line 86, in cli
    return self._junos.execute(rpc)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/decorators.py", line 71, in wrapper
    return function(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/decorators.py", line 26, in wrapper
    return function(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/jnpr/junos/device.py", line 569, in execute
    raise e(cmd=rpc_cmd_e, rsp=rsp)
jnpr.junos.exception.RpcError: RpcError(severity: error, bad_element: all-members, message: syntax error, expecting <command>)
```

_get_vc_status() attempts to execute the get-virtual-chassis-information RPC and if this command returns a non-empty response, it sets:

```
 facts['vc_capable'] = True
```

An EX8208 operating in standalone mode returns this response to the get-virtual-chassis-information RPC:

```
user@ex8208> show virtual-chassis status | display xml        
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/12.3R6/junos">
    <virtual-chassis-information>
        <virtual-chassis-id-information>
            <virtual-chassis-id>2893.26ca.afb8</virtual-chassis-id>
            <virtual-chassis-mode>Disabled</virtual-chassis-mode>
        </virtual-chassis-id-information>
        <member-list junos:style="slot-range">
            <member>
                <member-status>Prsnt</member-status>
                <member-id>0</member-id>
                <fpc-slot-range>(FPC 0-7)</fpc-slot-range>
                <member-serial-number>BT0910333396</member-serial-number>
                <member-model>ex8208</member-model>
                <member-priority>128</member-priority>
                <member-mixed-mode>NA</member-mixed-mode>
                <member-role>Master*</member-role>
                <neighbor-list>
                </neighbor-list>
            </member>
        </member-list>
        <next-member-information>
            <next-member-id>1</next-member-id>
        </next-member-information>
    </virtual-chassis-information>
    <cli>
        <banner></banner>
    </cli>
</rpc-reply>
```

This causes facts['vc_capable'] to be set to True

Later, in _get_swver() this code is executed:

```
def _get_swver(dev, facts):
    # See if we're VC Capable
    if facts['vc_capable'] is True:
        return dev.rpc.cli("show version all-members", format='xml')
    else:
        try:
            return dev.rpc.cli("show version invoke-on all-routing-engines", format='xml')
        except:
            return dev.rpc.get_software_information()
```

However, "show version all-members" is not a valid CLI command on an EX8208, at least when it is operating in standalone mode. This causes the unhandled exception to be raised.

```
user@ex8208> show version ?
Possible completions:
  <[Enter]>            Execute this command
  brief                Display brief output
  detail               Display detailed output
  fpc                  Show software version on FPC
  invoke-on            Remote command execution
  rollback             Show version of previous set of packages
  |                    Pipe through a command
user@ex8208> show version all-members
                                 ^
syntax error, expecting <command>.

user@ex8208> 
```

I have been unable to check an EX8208 operating in a virtual chassis, so I'm unsure of the responses in this case.


Changed files:
lib/jnpr/junos/facts/swver.py, tests/unit/facts/test_swver.py

diff --git a/lib/jnpr/junos/facts/swver.py b/lib/jnpr/junos/facts/swver.py
index 3693da32..c2065df4 100644
--- a/lib/jnpr/junos/facts/swver.py
+++ b/lib/jnpr/junos/facts/swver.py
@@ -80,12 +80,15 @@ class version_info(object):
 def _get_swver(dev, facts):
     # See if we're VC Capable
     if facts['vc_capable'] is True:
-        return dev.rpc.cli("show version all-members", format='xml')
-    else:
         try:
-            return dev.rpc.cli("show version invoke-on all-routing-engines", format='xml')
+            return dev.rpc.cli("show version all-members", format='xml')
         except:
-            return dev.rpc.get_software_information()
+            pass
+    try:
+        return dev.rpc.cli("show version invoke-on all-routing-engines",
+                           format='xml')
+    except:
+        return dev.rpc.get_software_information()
 
 
 def facts_software_version(junos, facts):
diff --git a/tests/unit/facts/test_swver.py b/tests/unit/facts/test_swver.py
index f65e2120..7d62c2b1 100644
--- a/tests/unit/facts/test_swver.py
+++ b/tests/unit/facts/test_swver.py
@@ -11,6 +11,7 @@ from jnpr.junos.facts.swver import facts_software_version as software_version, v
 from jnpr.junos.facts.swver import _get_swver
 from ncclient.manager import Manager, make_device_handler
 from ncclient.transport import SSHSession
+from jnpr.junos.exception import RpcError
 
 
 @attr('unit')
@@ -47,14 +48,20 @@ class TestVersionInfo(unittest.TestCase):
 
     def test_version_to_json(self):
         import json
-        self.assertEqual(json.dumps(version_info('11.4R7.5')), '{"major": [11, 4], "type": "R", "build": 5, "minor": "7"}')
+        self.assertEqual(
+            json.dumps(version_info('11.4R7.5')),
+            '{"major": [11, 4], "type": "R", "build": 5, "minor": "7"}')
 
     def test_version_to_yaml(self):
         import yaml
-        self.assertEqual(yaml.dump(version_info('11.4R7.5')), "build: 5\\nmajor: !!python/tuple [11, 4]\\nminor: '7'\\ntype: R\\n")
+        self.assertEqual(
+            yaml.dump(version_info('11.4R7.5')),
+            "build: 5\\nmajor: !!python/tuple [11, 4]\\nminor: '7'\\ntype: R\\n")
 
     def test_version_iter(self):
-        self.assertItemsEqual(version_info('11.4R7.5'), [('build', 5), ('major', (11, 4)), ('minor', '7'), ('type', 'R')])
+        self.assertItemsEqual(
+            version_info('11.4R7.5'),
+            [('build', 5), ('major', (11, 4)), ('minor', '7'), ('type', 'R')])
 
 
 @attr('unit')
@@ -75,6 +82,17 @@ class TestSwver(unittest.TestCase):
         _get_swver(self.dev, self.facts)
         self.dev.rpc.cli.assert_called_with('show version all-members', format='xml')
 
+    def test_get_swver_vc_capable_standalone(self):
+        def raise_ex(*args):
+            if args[0] == 'show version all-members':
+                raise RpcError()
+        self.dev.rpc.cli = MagicMock(
+            side_effect=lambda *args, **kwargs: raise_ex(*args))
+        self.facts['vc_capable'] = True
+        _get_swver(self.dev, self.facts)
+        self.dev.rpc.cli.assert_called_with('show version invoke-on all-routing-engines',
+                                            format='xml')
+
     @patch('jnpr.junos.Device.execute')
     def test_swver(self, mock_execute):
         mock_execute.side_effect = self._mock_manager