Repository: ansible/ansible

Issue:
onyx_linkagg module failed when using onyx version 3.6.6000
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and devel branch are affected too.
Always add information AFTER of these html comments.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
 - Bug Report

##### COMPONENT NAME
<!---
Insert below this comment the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path
-->
onyx_linkagg.py
##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.6.0 (devel 93fc99c576) last updated 2018/04/02 04:34:32 (GMT +000)
  config file = None
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"
Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
N/A
##### SUMMARY
<!--- Explain the problem briefly -->
An exception is thrown when creating an MLAG port using ansible module onyx_linkagg on Mellanox Switch running ONYX 3.6.6000. 
##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: configure MLag port channel with server 1
  onyx_linkagg:
    name: Mpo1
    members:
      - Eth1/7
    mode: active
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
mlag will be configured

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
an exception was thrown
<!--- Paste verbatim command output between quotes below -->
```
TASK [leaf1 : configure MLag port channel with server 1] *************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'list' object has no attribute 'get'
fatal: [leaf1]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_C2lxdf/ansible_module_onyx_linkagg.py\", line 338, in <module>\n main()\n File \"/tmp/ansible_C2lxdf/ansible_module_onyx_linkagg.py\", line 334, in main\n OnyxLinkAggModule.main()\n File \"/tmp/ansible_C2lxdf/ansible_modlib.zip/ansible/module_utils/network/onyx/onyx.py\", line 240, in main\n File \"/tmp/ansible_C2lxdf/ansible_modlib.zip/ansible/module_utils/network/onyx/onyx.py\", line 218, in run\n File \"/tmp/ansible_C2lxdf/ansible_module_onyx_linkagg.py\", line 248, in load_current_config\n self._parse_port_channels_summary(lag_type, lag_summary)\n File \"/tmp/ansible_C2lxdf/ansible_module_onyx_linkagg.py\", line 228, in _parse_port_channels_summary\n lag_summary = lag_summary.get('MLAG Port-Channel Summary', {})\nAttributeError: 'list' object has no attribute 'get'\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 1}
to retry, use: --limit @/etc/ansible/site.retry
```



Discussion:
Files identified in the description:
* [lib/ansible/modules/network/onyx/onyx_linkagg.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/onyx/onyx_linkagg.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->

Resolving patch:
diff --git a/lib/ansible/modules/network/onyx/onyx_linkagg.py b/lib/ansible/modules/network/onyx/onyx_linkagg.py
--- a/lib/ansible/modules/network/onyx/onyx_linkagg.py
+++ b/lib/ansible/modules/network/onyx/onyx_linkagg.py
@@ -109,6 +109,7 @@ class OnyxLinkAggModule(BaseOnyxModule):
     CHANNEL_GROUP = 'channel-group'
     MLAG_PORT_CHANNEL = 'mlag-port-channel'
     MLAG_CHANNEL_GROUP = 'mlag-channel-group'
+    MLAG_SUMMARY = 'MLAG Port-Channel Summary'
 
     LAG_TYPE = 'lag'
     MLAG_TYPE = 'mlag'
@@ -225,7 +226,21 @@ def _get_port_channels(self, if_type):
 
     def _parse_port_channels_summary(self, lag_type, lag_summary):
         if lag_type == self.MLAG_TYPE:
-            lag_summary = lag_summary.get('MLAG Port-Channel Summary', {})
+            if self._os_version >= self.ONYX_API_VERSION:
+                found_summary = False
+                for summary_item in lag_summary:
+                    if self.MLAG_SUMMARY in summary_item:
+                        lag_summary = summary_item[self.MLAG_SUMMARY]
+                        if lag_summary:
+                            lag_summary = lag_summary[0]
+                        else:
+                            lag_summary = dict()
+                        found_summary = True
+                        break
+                if not found_summary:
+                    lag_summary = dict()
+            else:
+                lag_summary = lag_summary.get(self.MLAG_SUMMARY, dict())
         for lag_key, lag_data in iteritems(lag_summary):
             lag_name, state = self._extract_lag_name(lag_key)
             if not lag_name:
@@ -240,6 +255,7 @@ def _parse_port_channels_summary(self, lag_type, lag_summary):
 
     def load_current_config(self):
         self._current_config = dict()
+        self._os_version = self._get_os_version()
         lag_types = set([lag_obj['type'] for lag_obj in self._required_config])
         for lag_type in lag_types:
             if_type = self.IF_TYPE_MAP[lag_type]


Test patch:
diff --git a/test/units/modules/network/onyx/test_onyx_linkagg.py b/test/units/modules/network/onyx/test_onyx_linkagg.py
--- a/test/units/modules/network/onyx/test_onyx_linkagg.py
+++ b/test/units/modules/network/onyx/test_onyx_linkagg.py
@@ -26,15 +26,20 @@ def setUp(self):
         self.mock_load_config = patch(
             'ansible.module_utils.network.onyx.onyx.load_config')
         self.load_config = self.mock_load_config.start()
+        self.mock_get_version = patch.object(
+            onyx_linkagg.OnyxLinkAggModule, "_get_os_version")
+        self.get_version = self.mock_get_version.start()
 
     def tearDown(self):
         super(TestOnyxLinkaggModule, self).tearDown()
         self.mock_get_config.stop()
         self.mock_load_config.stop()
+        self.mock_get_version.stop()
 
     def load_fixture(self, config_file):
         self.get_config.return_value = load_fixture(config_file)
         self.load_config.return_value = None
+        self.get_version.return_value = "3.6.5000"
 
     def load_port_channel_fixture(self):
         config_file = 'onyx_port_channel_show.cfg'