From 95096164ddd5d0fcf101859194372be8720b029e Mon Sep 17 00:00:00 2001 From: Dag Wieers Date: Wed, 1 Mar 2017 17:02:50 +0100 Subject: [PATCH] hpilo_facts: Get facts from HP iLO mgmt board (#21673) This is the original `hpilo_facts` module that was once accepted in Ansible but had been removed subsequently because it could not be tested by the Ansible project. Since then it was moved to the ansible-provisioning project and maintained by HP engineers going forward. Now we are trying to get it upstreamed again. --- .../remote_management/hpilo/hpilo_facts.py | 245 ++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100755 lib/ansible/modules/remote_management/hpilo/hpilo_facts.py diff --git a/lib/ansible/modules/remote_management/hpilo/hpilo_facts.py b/lib/ansible/modules/remote_management/hpilo/hpilo_facts.py new file mode 100755 index 0000000000..235e5d56a1 --- /dev/null +++ b/lib/ansible/modules/remote_management/hpilo/hpilo_facts.py @@ -0,0 +1,245 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright 2012 Dag Wieers +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +ANSIBLE_METADATA = {'status': ['preview'], + 'supported_by': 'community', + 'version': '1.0'} + +DOCUMENTATION = r''' +--- +module: hpilo_facts +version_added: "2.3" +author: Dag Wieers (@dagwieers) +short_description: Gather facts through an HP iLO interface +description: +- This module gathers facts for a specific system using its HP iLO interface. + These facts include hardware and network related information useful + for provisioning (e.g. macaddress, uuid). +- This module requires the hpilo python module. +options: + host: + description: + - The HP iLO hostname/address that is linked to the physical system. + required: true + login: + description: + - The login name to authenticate to the HP iLO interface. + default: Administrator + password: + description: + - The password to authenticate to the HP iLO interface. + default: admin +requirements: +- hpilo +notes: +- This module ought to be run from a system that can access the HP iLO + interface directly, either by using C(local_action) or using C(delegate_to). +''' + +EXAMPLES = r''' +# Task to gather facts from a HP iLO interface only if the system is an HP server +- hpilo_facts: + host: YOUR_ILO_ADDRESS + login: YOUR_ILO_LOGIN + password: YOUR_ILO_PASSWORD + when: cmdb_hwmodel.startswith('HP ') + delegate_to: localhost + +- fail: + msg: 'CMDB serial ({{ cmdb_serialno }}) does not match hardware serial ({{ hw_system_serial }}) !' + when: cmdb_serialno != hw_system_serial +''' + +RETURN = r''' +# Typical output of HP iLO_facts for a physical system +hw_bios_date: + description: BIOS date + returned: always + type: string + sample: 05/05/2011 + +hw_bios_version: + description: BIOS version + returned: always + type: string + sample: P68 + +hw_ethX: + description: Interface information (for each interface) + returned: always + type: dictionary of information (macaddress) + sample: + - macaddress: 00:11:22:33:44:55 + macaddress_dash: 00-11-22-33-44-55 + +hw_eth_ilo: + description: Interface information (for the iLO network interface) + returned: always + type: dictionary of information (macaddress) + sample: + - macaddress: 00:11:22:33:44:BA + - macaddress_dash: 00-11-22-33-44-BA + +hw_product_name: + description: Product name + returned: always + type: string + sample: ProLiant DL360 G7 + +hw_product_uuid: + description: Product UUID + returned: always + type: string + sample: ef50bac8-2845-40ff-81d9-675315501dac + +hw_system_serial: + description: System serial number + returned: always + type: string + sample: ABC12345D6 + +hw_uuid: + description: Hardware UUID + returned: always + type: string + sample: 123456ABC78901D2 +''' + +import re +import warnings +from ansible.module_utils.basic import AnsibleModule + +try: + import hpilo + HAS_HPILO = True +except ImportError: + HAS_HPILO = False + + +# Suppress warnings from hpilo +warnings.simplefilter('ignore') + + +def parse_flat_interface(entry, non_numeric='hw_eth_ilo'): + try: + factname = 'hw_eth' + str(int(entry['Port']) - 1) + except: + factname = non_numeric + + facts = { + 'macaddress': entry['MAC'].replace('-', ':'), + 'macaddress_dash': entry['MAC'] + } + return (factname, facts) + + +def main(): + + module = AnsibleModule( + argument_spec = dict( + host = dict(required=True, type='str'), + login = dict(default='Administrator', type='str'), + password = dict(default='admin', type='str', no_log=True), + ), + supports_check_mode=True, + ) + + if not HAS_HPILO: + module.fail_json(msg='The hpilo python module is required') + + host = module.params['host'] + login = module.params['login'] + password = module.params['password'] + + ilo = hpilo.Ilo(host, login=login, password=password) + + facts = { + 'module_hw': True, + } + + # TODO: Count number of CPUs, DIMMs and total memory + data = ilo.get_host_data() + for entry in data: + if 'type' not in entry: + continue + elif entry['type'] == 0: # BIOS Information + facts['hw_bios_version'] = entry['Family'] + facts['hw_bios_date'] = entry['Date'] + elif entry['type'] == 1: # System Information + facts['hw_uuid'] = entry['UUID'] + facts['hw_system_serial'] = entry['Serial Number'].rstrip() + facts['hw_product_name'] = entry['Product Name'] + facts['hw_product_uuid'] = entry['cUUID'] + elif entry['type'] == 209: # Embedded NIC MAC Assignment + if 'fields' in entry: + for (name, value) in [ (e['name'], e['value']) for e in entry['fields'] ]: + if name.startswith('Port'): + try: + factname = 'hw_eth' + str(int(value) - 1) + except: + factname = 'hw_eth_ilo' + elif name.startswith('MAC'): + facts[factname] = { + 'macaddress': value.replace('-', ':'), + 'macaddress_dash': value + } + else: + (factname, entry_facts) = parse_flat_interface(entry, 'hw_eth_ilo') + facts[factname] = entry_facts + elif entry['type'] == 209: # HPQ NIC iSCSI MAC Info + for (name, value) in [(e['name'], e['value']) for e in entry['fields']]: + if name.startswith('Port'): + try: + factname = 'hw_iscsi' + str(int(value) - 1) + except: + factname = 'hw_iscsi_ilo' + elif name.startswith('MAC'): + facts[factname] = { + 'macaddress': value.replace('-', ':'), + 'macaddress_dash': value + } + elif entry['type'] == 233: # Embedded NIC MAC Assignment (Alternate data format) + (factname, entry_facts) = parse_flat_interface(entry, 'hw_eth_ilo') + facts[factname] = entry_facts + + # Collect health (RAM/CPU data) + health = ilo.get_embedded_health() + facts['hw_health'] = health + + memory_details_summary = health.get('memory', {}).get('memory_details_summary') + # RAM as reported by iLO 2.10 on ProLiant BL460c Gen8 + if memory_details_summary: + facts['hw_memory_details_summary'] = memory_details_summary + facts['hw_memory_total'] = 0 + for cpu, details in memory_details_summary.items(): + cpu_total_memory_size = details.get('total_memory_size') + if cpu_total_memory_size: + ram = re.search('(\d+)\s+(\w+)', cpu_total_memory_size) + if ram: + if ram.group(2) == 'GB': + facts['hw_memory_total'] = facts['hw_memory_total'] + int(ram.group(1)) + + # reformat into a text friendly format + facts['hw_memory_total'] = "{0} GB".format(facts['hw_memory_total']) + + module.exit_json(ansible_facts=facts) + +if __name__ == '__main__': + main()