#!/usr/bin/python # # Copyright: Ansible Project # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community'} DOCUMENTATION = ''' --- module: onyx_facts author: "Waleed Mousa (@waleedym), Samer Deeb (@samerd)" short_description: Collect facts from Mellanox ONYX network devices description: - Collects a base set of device facts from a ONYX Mellanox network devices This module prepends all of the base network fact keys with C(ansible_net_). The facts module will always collect a base set of facts from the device and can enable or disable collection of additional facts. notes: - Tested against ONYX 3.6 options: gather_subset: description: - When supplied, this argument will restrict the facts collected to a given subset. Possible values for this argument include all, version, module, and interfaces. Can specify a list of values to include a larger subset. Values can also be used with an initial C(M(!)) to specify that a specific subset should not be collected. required: false default: version ''' EXAMPLES = """ --- - name: Collect all facts from the device onyx_facts: gather_subset: all - name: Collect only the interfaces facts onyx_facts: gather_subset: - interfaces - name: Do not collect version facts onyx_facts: gather_subset: - "!version" """ RETURN = """ ansible_net_gather_subset: description: The list of fact subsets collected from the device returned: always type: list # version ansible_net_version: description: A hash of all currently running system image information returned: when version is configured or when no gather_subset is provided type: dict # modules ansible_net_modules: description: A hash of all modules on the systeme with status returned: when modules is configured type: dict # interfaces ansible_net_interfaces: description: A hash of all interfaces running on the system returned: when interfaces is configured type: dict """ from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six import iteritems from ansible_collections.community.general.plugins.module_utils.network.onyx.onyx import BaseOnyxModule from ansible_collections.community.general.plugins.module_utils.network.onyx.onyx import show_cmd class OnyxFactsModule(BaseOnyxModule): def get_runable_subset(self, gather_subset): runable_subsets = set() exclude_subsets = set() for subset in gather_subset: if subset == 'all': runable_subsets.update(VALID_SUBSETS) continue if subset.startswith('!'): subset = subset[1:] if subset == 'all': exclude_subsets.update(VALID_SUBSETS) continue exclude = True else: exclude = False if subset not in VALID_SUBSETS: self._module.fail_json(msg='Bad subset') if exclude: exclude_subsets.add(subset) else: runable_subsets.add(subset) if not runable_subsets: runable_subsets.update(VALID_SUBSETS) runable_subsets.difference_update(exclude_subsets) if not runable_subsets: runable_subsets.add('version') return runable_subsets def init_module(self): """ module initialization """ argument_spec = dict( gather_subset=dict(default=['version'], type='list') ) self._module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True) def run(self): self.init_module() gather_subset = self._module.params['gather_subset'] runable_subsets = self.get_runable_subset(gather_subset) facts = dict() facts['gather_subset'] = list(runable_subsets) instances = list() for key in runable_subsets: facter_cls = FACT_SUBSETS[key] instances.append(facter_cls(self._module)) for inst in instances: inst.populate() facts.update(inst.facts) ansible_facts = dict() for key, value in iteritems(facts): key = 'ansible_net_%s' % key ansible_facts[key] = value self._module.exit_json(ansible_facts=ansible_facts) class FactsBase(object): COMMANDS = [''] def __init__(self, module): self.module = module self.facts = dict() self.responses = None def _show_cmd(self, cmd): return show_cmd(self.module, cmd, json_fmt=True) def populate(self): self.responses = [] for cmd in self.COMMANDS: self.responses.append(self._show_cmd(cmd)) class Version(FactsBase): COMMANDS = ['show version'] def populate(self): super(Version, self).populate() data = self.responses[0] if data: self.facts['version'] = data class Module(FactsBase): COMMANDS = ['show module'] def populate(self): super(Module, self).populate() data = self.responses[0] if data: self.facts['modules'] = data class Interfaces(FactsBase): COMMANDS = ['show version', 'show interfaces ethernet'] def populate(self): super(Interfaces, self).populate() version_data = self.responses[0] os_version = version_data['Product release'] data = self.responses[1] if data: self.facts['interfaces'] = self.populate_interfaces(data, os_version) def extractIfData(self, interface_data): return {"MAC Address": interface_data["Mac address"], "Actual Speed": interface_data["Actual speed"], "MTU": interface_data["MTU"], "Admin State": interface_data["Admin state"], "Operational State": interface_data["Operational state"]} def populate_interfaces(self, interfaces, os_version): interfaces_dict = dict() for if_data in interfaces: if_dict = dict() if os_version >= BaseOnyxModule.ONYX_API_VERSION: for if_name, interface_data in iteritems(if_data): interface_data = interface_data[0] if_dict = self.extractIfData(interface_data) if_name = if_dict["Interface Name"] = if_name else: if_dict = self.extractIfData(if_data) if_name = if_dict["Interface Name"] = if_data["header"] interfaces_dict[if_name] = if_dict return interfaces_dict FACT_SUBSETS = dict( version=Version, modules=Module, interfaces=Interfaces ) VALID_SUBSETS = frozenset(FACT_SUBSETS.keys()) def main(): """ main entry point for module execution """ OnyxFactsModule.main() if __name__ == '__main__': main()